diff options
Diffstat (limited to 'fs/ntfs')
| -rw-r--r-- | fs/ntfs/inode.c | 33 | ||||
| -rw-r--r-- | fs/ntfs/super.c | 31 | 
2 files changed, 64 insertions, 0 deletions
| diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 4c86b7e1d1eb..d313f356e66a 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -367,6 +367,12 @@ static void ntfs_destroy_extent_inode(ntfs_inode *ni)  	kmem_cache_free(ntfs_inode_cache, ni);  } +/* + * The attribute runlist lock has separate locking rules from the + * normal runlist lock, so split the two lock-classes: + */ +static struct lock_class_key attr_list_rl_lock_class; +  /**   * __ntfs_init_inode - initialize ntfs specific part of an inode   * @sb:		super block of mounted volume @@ -394,6 +400,8 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)  	ni->attr_list_size = 0;  	ni->attr_list = NULL;  	ntfs_init_runlist(&ni->attr_list_rl); +	lockdep_set_class(&ni->attr_list_rl.lock, +				&attr_list_rl_lock_class);  	ni->itype.index.bmp_ino = NULL;  	ni->itype.index.block_size = 0;  	ni->itype.index.vcn_size = 0; @@ -405,6 +413,13 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)  	ni->ext.base_ntfs_ino = NULL;  } +/* + * Extent inodes get MFT-mapped in a nested way, while the base inode + * is still mapped. Teach this nesting to the lock validator by creating + * a separate class for nested inode's mrec_lock's: + */ +static struct lock_class_key extent_inode_mrec_lock_key; +  inline ntfs_inode *ntfs_new_extent_inode(struct super_block *sb,  		unsigned long mft_no)  { @@ -413,6 +428,7 @@ inline ntfs_inode *ntfs_new_extent_inode(struct super_block *sb,  	ntfs_debug("Entering.");  	if (likely(ni != NULL)) {  		__ntfs_init_inode(sb, ni); +		lockdep_set_class(&ni->mrec_lock, &extent_inode_mrec_lock_key);  		ni->mft_no = mft_no;  		ni->type = AT_UNUSED;  		ni->name = NULL; @@ -1722,6 +1738,15 @@ err_out:  	return err;  } +/* + * The MFT inode has special locking, so teach the lock validator + * about this by splitting off the locking rules of the MFT from + * the locking rules of other inodes. The MFT inode can never be + * accessed from the VFS side (or even internally), only by the + * map_mft functions. + */ +static struct lock_class_key mft_ni_runlist_lock_key, mft_ni_mrec_lock_key; +  /**   * ntfs_read_inode_mount - special read_inode for mount time use only   * @vi:		inode to read @@ -2148,6 +2173,14 @@ int ntfs_read_inode_mount(struct inode *vi)  	ntfs_attr_put_search_ctx(ctx);  	ntfs_debug("Done.");  	ntfs_free(m); + +	/* +	 * Split the locking rules of the MFT inode from the +	 * locking rules of other inodes: +	 */ +	lockdep_set_class(&ni->runlist.lock, &mft_ni_runlist_lock_key); +	lockdep_set_class(&ni->mrec_lock, &mft_ni_mrec_lock_key); +  	return 0;  em_put_err_out: diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 0e14acea3f8b..74e0ee8fce72 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -1724,6 +1724,14 @@ upcase_failed:  	return FALSE;  } +/* + * The lcn and mft bitmap inodes are NTFS-internal inodes with + * their own special locking rules: + */ +static struct lock_class_key +	lcnbmp_runlist_lock_key, lcnbmp_mrec_lock_key, +	mftbmp_runlist_lock_key, mftbmp_mrec_lock_key; +  /**   * load_system_files - open the system files using normal functions   * @vol:	ntfs super block describing device whose system files to load @@ -1780,6 +1788,10 @@ static BOOL load_system_files(ntfs_volume *vol)  		ntfs_error(sb, "Failed to load $MFT/$BITMAP attribute.");  		goto iput_mirr_err_out;  	} +	lockdep_set_class(&NTFS_I(vol->mftbmp_ino)->runlist.lock, +			   &mftbmp_runlist_lock_key); +	lockdep_set_class(&NTFS_I(vol->mftbmp_ino)->mrec_lock, +			   &mftbmp_mrec_lock_key);  	/* Read upcase table and setup @vol->upcase and @vol->upcase_len. */  	if (!load_and_init_upcase(vol))  		goto iput_mftbmp_err_out; @@ -1802,6 +1814,11 @@ static BOOL load_system_files(ntfs_volume *vol)  			iput(vol->lcnbmp_ino);  		goto bitmap_failed;  	} +	lockdep_set_class(&NTFS_I(vol->lcnbmp_ino)->runlist.lock, +			   &lcnbmp_runlist_lock_key); +	lockdep_set_class(&NTFS_I(vol->lcnbmp_ino)->mrec_lock, +			   &lcnbmp_mrec_lock_key); +  	NInoSetSparseDisabled(NTFS_I(vol->lcnbmp_ino));  	if ((vol->nr_clusters + 7) >> 3 > i_size_read(vol->lcnbmp_ino)) {  		iput(vol->lcnbmp_ino); @@ -2743,6 +2760,17 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)  	struct inode *tmp_ino;  	int blocksize, result; +	/* +	 * We do a pretty difficult piece of bootstrap by reading the +	 * MFT (and other metadata) from disk into memory. We'll only +	 * release this metadata during umount, so the locking patterns +	 * observed during bootstrap do not count. So turn off the +	 * observation of locking patterns (strictly for this context +	 * only) while mounting NTFS. [The validator is still active +	 * otherwise, even for this context: it will for example record +	 * lock class registrations.] +	 */ +	lockdep_off();  	ntfs_debug("Entering.");  #ifndef NTFS_RW  	sb->s_flags |= MS_RDONLY; @@ -2754,6 +2782,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)  		if (!silent)  			ntfs_error(sb, "Allocation of NTFS volume structure "  					"failed. Aborting mount..."); +		lockdep_on();  		return -ENOMEM;  	}  	/* Initialize ntfs_volume structure. */ @@ -2940,6 +2969,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)  		mutex_unlock(&ntfs_lock);  		sb->s_export_op = &ntfs_export_ops;  		lock_kernel(); +		lockdep_on();  		return 0;  	}  	ntfs_error(sb, "Failed to allocate root directory."); @@ -3059,6 +3089,7 @@ err_out_now:  	sb->s_fs_info = NULL;  	kfree(vol);  	ntfs_debug("Failed, returning -EINVAL."); +	lockdep_on();  	return -EINVAL;  } | 
