diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2020-10-25 17:16:06 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2020-10-26 18:32:31 -0700 |
commit | bfe6ffd16865f1c5bfef696447ea691f656d1b02 (patch) | |
tree | 57aa8744ca4b4969fbcbc97a8c8014a1793f8038 | |
parent | 0e99beb79524ac10087f53169490a010a648f9eb (diff) |
xfs: put metadata inodes in a separate lockdep class
Metadata inodes are not supposed to be exposed to userspace, which
eliminates most conflicts with vfs rwseasm, page cache locks, etc. This
means that we actually /can/ do things like copy data to userspace while
holding a metadata inode's ILOCK, since, uh.... well what happens if we
copy rt fsmap data to an rt file, which then causes an rt allocation and
therfore needs the rtrmap ilock...?
Confused-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r-- | fs/xfs/xfs_iops.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 793ff08a9933..6289b3f3268c 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -41,6 +41,15 @@ static struct lock_class_key xfs_nondir_ilock_class; static struct lock_class_key xfs_dir_ilock_class; +/* + * Metadata directories and files are not exposed to userspace, which means + * that they never access any of the VFS IO locks and never experience page + * faults. Give them separate locking classes so that lockdep will not + * complain about conflicts that cannot happen. + */ +static struct lock_class_key xfs_metadata_file_ilock_class; +static struct lock_class_key xfs_metadata_dir_ilock_class; + static int xfs_initxattrs( struct inode *inode, @@ -1330,6 +1339,7 @@ xfs_setup_inode( { struct inode *inode = &ip->i_vnode; gfp_t gfp_mask; + bool is_meta = xfs_is_metadata_inode(ip); inode->i_ino = ip->i_ino; inode->i_state = I_NEW; @@ -1350,9 +1360,19 @@ xfs_setup_inode( */ lockdep_set_class(&inode->i_rwsem, &inode->i_sb->s_type->i_mutex_dir_key); - lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class); + if (is_meta) + lockdep_set_class(&ip->i_lock.mr_lock, + &xfs_metadata_dir_ilock_class); + else + lockdep_set_class(&ip->i_lock.mr_lock, + &xfs_dir_ilock_class); } else { - lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class); + if (is_meta) + lockdep_set_class(&ip->i_lock.mr_lock, + &xfs_metadata_file_ilock_class); + else + lockdep_set_class(&ip->i_lock.mr_lock, + &xfs_nondir_ilock_class); } /* |