summaryrefslogtreecommitdiff
path: root/fs/ntfs/attrlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ntfs/attrlist.c')
-rw-r--r--fs/ntfs/attrlist.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/fs/ntfs/attrlist.c b/fs/ntfs/attrlist.c
index c2594d4c83b0..be3086d34338 100644
--- a/fs/ntfs/attrlist.c
+++ b/fs/ntfs/attrlist.c
@@ -57,6 +57,15 @@ int ntfs_attrlist_update(struct ntfs_inode *base_ni)
struct ntfs_inode *attr_ni;
int err;
+ /*
+ * generic_shutdown_super() clears SB_ACTIVE before evicting cached
+ * inodes. Do not look up the attribute-list inode after SB_ACTIVE has
+ * been cleared; it may already be I_FREEING, and waiting on it can
+ * self-deadlock.
+ */
+ if (!(VFS_I(base_ni)->i_sb->s_flags & SB_ACTIVE))
+ return -EIO;
+
attr_vi = ntfs_attr_iget(VFS_I(base_ni), AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
if (IS_ERR(attr_vi)) {
err = PTR_ERR(attr_vi);
@@ -118,6 +127,7 @@ int ntfs_attrlist_entry_add(struct ntfs_inode *ni, struct attr_record *attr)
int entry_len, entry_offset, err;
struct mft_record *ni_mrec;
u8 *old_al;
+ __le64 lowest_vcn;
if (!ni || !attr) {
ntfs_debug("Invalid arguments.\n");
@@ -158,17 +168,21 @@ int ntfs_attrlist_entry_add(struct ntfs_inode *ni, struct attr_record *attr)
ntfs_error(ni->vol->sb, "Failed to get search context");
goto err_out;
}
+ if (attr->non_resident)
+ lowest_vcn = attr->data.non_resident.lowest_vcn;
+ else
+ lowest_vcn = 0;
err = ntfs_attr_lookup(attr->type, (attr->name_length) ? (__le16 *)
((u8 *)attr + le16_to_cpu(attr->name_offset)) :
AT_UNNAMED, attr->name_length, CASE_SENSITIVE,
- (attr->non_resident) ? le64_to_cpu(attr->data.non_resident.lowest_vcn) :
- 0, (attr->non_resident) ? NULL : ((u8 *)attr +
+ le64_to_cpu(lowest_vcn),
+ (attr->non_resident) ? NULL : ((u8 *)attr +
le16_to_cpu(attr->data.resident.value_offset)), (attr->non_resident) ?
0 : le32_to_cpu(attr->data.resident.value_length), ctx);
if (!err) {
/* Found some extent, check it to be before new extent. */
- if (ctx->al_entry->lowest_vcn == attr->data.non_resident.lowest_vcn) {
+ if (ctx->al_entry->lowest_vcn == lowest_vcn) {
err = -EEXIST;
ntfs_debug("Such attribute already present in the attribute list.\n");
ntfs_attr_put_search_ctx(ctx);