diff options
| author | Yazen Ghannam <yazen.ghannam@amd.com> | 2026-09-03 10:43:25 -0500 |
|---|---|---|
| committer | Borislav Petkov (AMD) <bp@alien8.de> | 2026-09-10 18:05:43 -0700 |
| commit | 27600805e62f800bacf990354632eae4e487d34c (patch) | |
| tree | e8aec0ddfaa0bc264d79af632e3de3f1b75ae4c8 /fs/ntfs/object_id.c | |
| download | linux-stable-27600805e62f800bacf990354632eae4e487d34c.tar.gz linux-stable-27600805e62f800bacf990354632eae4e487d34c.zip | |
x86/amd_node: Fix PCI device reference counting in amd_smn_init()grafted
The local "root" pointer is a temporary variable used during the device
search. Therefore, refcount related to the search iterators should be cleaned
up after the search is complete.
Use the __free() cleanup macro to ensure the refcount is decremented when the
temporary pointer goes out of scope.
Additionally, increment the refcount when caching a root pointer. This ensures
the in-use refcount is separate from the temporary search refcounting.
Finally, drop the redundant "root = NULL" before the second search loop. The
pci_get_class() iterator always decrements the refcount of its "from"
argument, so the first loop can only fall through with "root" already NULL.
Fixes: 0a4b61d9c2e4 ("x86/amd_node: Fix AMD root device caching")
Closes: https://sashiko.dev/#/patchset/20260806160159.230453-1-jason.andryuk%40amd.com
Reported-by: Sashiko <sashiko-bot@kernel.org>
Assisted-by: LLM
Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Cc: <stable@kernel.org>
Link: https://patch.msgid.link/20260903154325.74343-1-yazen.ghannam@amd.com
Diffstat (limited to 'fs/ntfs/object_id.c')
| -rw-r--r-- | fs/ntfs/object_id.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/fs/ntfs/object_id.c b/fs/ntfs/object_id.c new file mode 100644 index 000000000..89002c375 --- /dev/null +++ b/fs/ntfs/object_id.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Pocessing of object ids + * + * Part of this file is based on code from the NTFS-3G. + * + * Copyright (c) 2009-2019 Jean-Pierre Andre + * Copyright (c) 2026 LG Electronics Co., Ltd. + */ + +#include "ntfs.h" +#include "index.h" +#include "object_id.h" + +struct object_id_index_key { + union { + u32 alignment; + struct guid guid; + } object_id; +} __packed; + +struct object_id_index_data { + __le64 file_id; + struct guid birth_volume_id; + struct guid birth_object_id; + struct guid domain_id; +} __packed; + +/* Index entry in $Extend/$ObjId */ +struct object_id_index { + struct index_entry_header header; + struct object_id_index_key key; + struct object_id_index_data data; +} __packed; + +__le16 objid_index_name[] = {cpu_to_le16('$'), cpu_to_le16('O'), 0}; + +/* + * open_object_id_index - Open the $Extend/$ObjId file and its index + * @vol: NTFS volume structure + * + * Opens the $ObjId system file and retrieves its index context. + * + * Return: The index context if opened successfully, or NULL if an error + * occurred. + */ +static struct ntfs_index_context *open_object_id_index(struct ntfs_volume *vol) +{ + struct inode *dir_vi, *vi; + struct ntfs_inode *dir_ni; + struct ntfs_index_context *xo = NULL; + struct ntfs_name *name = NULL; + u64 mref; + int uname_len; + __le16 *uname; + + uname_len = ntfs_nlstoucs(vol, "$ObjId", 6, &uname, + NTFS_MAX_NAME_LEN); + if (uname_len < 0) + return NULL; + + /* do not use path_name_to inode - could reopen root */ + dir_vi = ntfs_iget(vol->sb, FILE_Extend); + if (IS_ERR(dir_vi)) { + kmem_cache_free(ntfs_name_cache, uname); + return NULL; + } + dir_ni = NTFS_I(dir_vi); + + mutex_lock_nested(&dir_ni->mrec_lock, NTFS_EXTEND_MUTEX_PARENT); + mref = ntfs_lookup_inode_by_name(dir_ni, uname, uname_len, &name); + mutex_unlock(&dir_ni->mrec_lock); + kfree(name); + kmem_cache_free(ntfs_name_cache, uname); + if (IS_ERR_MREF(mref)) + goto put_dir_vi; + + vi = ntfs_iget(vol->sb, MREF(mref)); + if (IS_ERR(vi)) + goto put_dir_vi; + + xo = ntfs_index_ctx_get(NTFS_I(vi), objid_index_name, 2); + if (!xo) + iput(vi); +put_dir_vi: + iput(dir_vi); + return xo; +} + + +/* + * remove_object_id_index - Remove an object id index entry if attribute present + * @ni: NTFS inode structure containing the attribute + * @xo: Index context for the object id index + * + * Reads the existing object ID attribute and removes it from the index. + * + * Return: 0 on success, or a negative error code on failure. + */ +static int remove_object_id_index(struct ntfs_inode *ni, struct ntfs_index_context *xo) +{ + struct object_id_index_key key = {0}; + s64 size; + + if (ni->data_size == 0) + return -ENODATA; + + /* read the existing object id attribute */ + size = ntfs_inode_attr_pread(VFS_I(ni), 0, sizeof(struct guid), + (char *)&key); + if (size != sizeof(struct guid)) + return -ENODATA; + + if (!ntfs_index_lookup(&key, sizeof(struct object_id_index_key), xo)) + return ntfs_index_rm(xo); + + return 0; +} + +/* + * ntfs_delete_object_id_index - Delete an object_id index entry + * @ni: NTFS inode structure + * + * Opens the object ID index and removes the entry corresponding to the inode. + * + * Return: 0 on success, or a negative error code on failure. + */ +int ntfs_delete_object_id_index(struct ntfs_inode *ni) +{ + struct ntfs_index_context *xo; + struct ntfs_inode *xoni; + struct inode *attr_vi; + int ret = 0; + + attr_vi = ntfs_attr_iget(VFS_I(ni), AT_OBJECT_ID, AT_UNNAMED, 0); + if (IS_ERR(attr_vi)) + return PTR_ERR(attr_vi); + + /* + * read the existing object id and un-index it + */ + xo = open_object_id_index(ni->vol); + if (xo) { + xoni = xo->idx_ni; + mutex_lock_nested(&xoni->mrec_lock, NTFS_EXTEND_MUTEX_PARENT); + ret = remove_object_id_index(NTFS_I(attr_vi), xo); + if (!ret) { + ntfs_index_entry_mark_dirty(xo); + mark_mft_record_dirty(xoni); + } + ntfs_index_ctx_put(xo); + mutex_unlock(&xoni->mrec_lock); + iput(VFS_I(xoni)); + } + + iput(attr_vi); + return ret; +} |
