diff options
author | Ingo Molnar <mingo@elte.hu> | 2006-07-03 03:25:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-03 18:27:08 -0400 |
commit | 59345374742ee6673c2d04b0fa8c888e881b7209 (patch) | |
tree | c58ca74efe0c361086c6ffa70bc7597ec5674c95 | |
parent | c6573c2904231279de0584787d6214f19a128d0b (diff) |
[PATCH] lockdep: annotate NTFS locking rules
NTFS uses lots of type-opaque objects which acquire their true identity
runtime - so the lock validator needs to be helped in a couple of places to
figure out object types.
Many thanks to Anton Altaparmakov for giving lots of explanations about NTFS
locking rules.
Has no effect on non-lockdep kernels.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-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) | |||
367 | kmem_cache_free(ntfs_inode_cache, ni); | 367 | kmem_cache_free(ntfs_inode_cache, ni); |
368 | } | 368 | } |
369 | 369 | ||
370 | /* | ||
371 | * The attribute runlist lock has separate locking rules from the | ||
372 | * normal runlist lock, so split the two lock-classes: | ||
373 | */ | ||
374 | static struct lock_class_key attr_list_rl_lock_class; | ||
375 | |||
370 | /** | 376 | /** |
371 | * __ntfs_init_inode - initialize ntfs specific part of an inode | 377 | * __ntfs_init_inode - initialize ntfs specific part of an inode |
372 | * @sb: super block of mounted volume | 378 | * @sb: super block of mounted volume |
@@ -394,6 +400,8 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni) | |||
394 | ni->attr_list_size = 0; | 400 | ni->attr_list_size = 0; |
395 | ni->attr_list = NULL; | 401 | ni->attr_list = NULL; |
396 | ntfs_init_runlist(&ni->attr_list_rl); | 402 | ntfs_init_runlist(&ni->attr_list_rl); |
403 | lockdep_set_class(&ni->attr_list_rl.lock, | ||
404 | &attr_list_rl_lock_class); | ||
397 | ni->itype.index.bmp_ino = NULL; | 405 | ni->itype.index.bmp_ino = NULL; |
398 | ni->itype.index.block_size = 0; | 406 | ni->itype.index.block_size = 0; |
399 | ni->itype.index.vcn_size = 0; | 407 | ni->itype.index.vcn_size = 0; |
@@ -405,6 +413,13 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni) | |||
405 | ni->ext.base_ntfs_ino = NULL; | 413 | ni->ext.base_ntfs_ino = NULL; |
406 | } | 414 | } |
407 | 415 | ||
416 | /* | ||
417 | * Extent inodes get MFT-mapped in a nested way, while the base inode | ||
418 | * is still mapped. Teach this nesting to the lock validator by creating | ||
419 | * a separate class for nested inode's mrec_lock's: | ||
420 | */ | ||
421 | static struct lock_class_key extent_inode_mrec_lock_key; | ||
422 | |||
408 | inline ntfs_inode *ntfs_new_extent_inode(struct super_block *sb, | 423 | inline ntfs_inode *ntfs_new_extent_inode(struct super_block *sb, |
409 | unsigned long mft_no) | 424 | unsigned long mft_no) |
410 | { | 425 | { |
@@ -413,6 +428,7 @@ inline ntfs_inode *ntfs_new_extent_inode(struct super_block *sb, | |||
413 | ntfs_debug("Entering."); | 428 | ntfs_debug("Entering."); |
414 | if (likely(ni != NULL)) { | 429 | if (likely(ni != NULL)) { |
415 | __ntfs_init_inode(sb, ni); | 430 | __ntfs_init_inode(sb, ni); |
431 | lockdep_set_class(&ni->mrec_lock, &extent_inode_mrec_lock_key); | ||
416 | ni->mft_no = mft_no; | 432 | ni->mft_no = mft_no; |
417 | ni->type = AT_UNUSED; | 433 | ni->type = AT_UNUSED; |
418 | ni->name = NULL; | 434 | ni->name = NULL; |
@@ -1722,6 +1738,15 @@ err_out: | |||
1722 | return err; | 1738 | return err; |
1723 | } | 1739 | } |
1724 | 1740 | ||
1741 | /* | ||
1742 | * The MFT inode has special locking, so teach the lock validator | ||
1743 | * about this by splitting off the locking rules of the MFT from | ||
1744 | * the locking rules of other inodes. The MFT inode can never be | ||
1745 | * accessed from the VFS side (or even internally), only by the | ||
1746 | * map_mft functions. | ||
1747 | */ | ||
1748 | static struct lock_class_key mft_ni_runlist_lock_key, mft_ni_mrec_lock_key; | ||
1749 | |||
1725 | /** | 1750 | /** |
1726 | * ntfs_read_inode_mount - special read_inode for mount time use only | 1751 | * ntfs_read_inode_mount - special read_inode for mount time use only |
1727 | * @vi: inode to read | 1752 | * @vi: inode to read |
@@ -2148,6 +2173,14 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
2148 | ntfs_attr_put_search_ctx(ctx); | 2173 | ntfs_attr_put_search_ctx(ctx); |
2149 | ntfs_debug("Done."); | 2174 | ntfs_debug("Done."); |
2150 | ntfs_free(m); | 2175 | ntfs_free(m); |
2176 | |||
2177 | /* | ||
2178 | * Split the locking rules of the MFT inode from the | ||
2179 | * locking rules of other inodes: | ||
2180 | */ | ||
2181 | lockdep_set_class(&ni->runlist.lock, &mft_ni_runlist_lock_key); | ||
2182 | lockdep_set_class(&ni->mrec_lock, &mft_ni_mrec_lock_key); | ||
2183 | |||
2151 | return 0; | 2184 | return 0; |
2152 | 2185 | ||
2153 | em_put_err_out: | 2186 | 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: | |||
1724 | return FALSE; | 1724 | return FALSE; |
1725 | } | 1725 | } |
1726 | 1726 | ||
1727 | /* | ||
1728 | * The lcn and mft bitmap inodes are NTFS-internal inodes with | ||
1729 | * their own special locking rules: | ||
1730 | */ | ||
1731 | static struct lock_class_key | ||
1732 | lcnbmp_runlist_lock_key, lcnbmp_mrec_lock_key, | ||
1733 | mftbmp_runlist_lock_key, mftbmp_mrec_lock_key; | ||
1734 | |||
1727 | /** | 1735 | /** |
1728 | * load_system_files - open the system files using normal functions | 1736 | * load_system_files - open the system files using normal functions |
1729 | * @vol: ntfs super block describing device whose system files to load | 1737 | * @vol: ntfs super block describing device whose system files to load |
@@ -1780,6 +1788,10 @@ static BOOL load_system_files(ntfs_volume *vol) | |||
1780 | ntfs_error(sb, "Failed to load $MFT/$BITMAP attribute."); | 1788 | ntfs_error(sb, "Failed to load $MFT/$BITMAP attribute."); |
1781 | goto iput_mirr_err_out; | 1789 | goto iput_mirr_err_out; |
1782 | } | 1790 | } |
1791 | lockdep_set_class(&NTFS_I(vol->mftbmp_ino)->runlist.lock, | ||
1792 | &mftbmp_runlist_lock_key); | ||
1793 | lockdep_set_class(&NTFS_I(vol->mftbmp_ino)->mrec_lock, | ||
1794 | &mftbmp_mrec_lock_key); | ||
1783 | /* Read upcase table and setup @vol->upcase and @vol->upcase_len. */ | 1795 | /* Read upcase table and setup @vol->upcase and @vol->upcase_len. */ |
1784 | if (!load_and_init_upcase(vol)) | 1796 | if (!load_and_init_upcase(vol)) |
1785 | goto iput_mftbmp_err_out; | 1797 | goto iput_mftbmp_err_out; |
@@ -1802,6 +1814,11 @@ static BOOL load_system_files(ntfs_volume *vol) | |||
1802 | iput(vol->lcnbmp_ino); | 1814 | iput(vol->lcnbmp_ino); |
1803 | goto bitmap_failed; | 1815 | goto bitmap_failed; |
1804 | } | 1816 | } |
1817 | lockdep_set_class(&NTFS_I(vol->lcnbmp_ino)->runlist.lock, | ||
1818 | &lcnbmp_runlist_lock_key); | ||
1819 | lockdep_set_class(&NTFS_I(vol->lcnbmp_ino)->mrec_lock, | ||
1820 | &lcnbmp_mrec_lock_key); | ||
1821 | |||
1805 | NInoSetSparseDisabled(NTFS_I(vol->lcnbmp_ino)); | 1822 | NInoSetSparseDisabled(NTFS_I(vol->lcnbmp_ino)); |
1806 | if ((vol->nr_clusters + 7) >> 3 > i_size_read(vol->lcnbmp_ino)) { | 1823 | if ((vol->nr_clusters + 7) >> 3 > i_size_read(vol->lcnbmp_ino)) { |
1807 | iput(vol->lcnbmp_ino); | 1824 | iput(vol->lcnbmp_ino); |
@@ -2743,6 +2760,17 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2743 | struct inode *tmp_ino; | 2760 | struct inode *tmp_ino; |
2744 | int blocksize, result; | 2761 | int blocksize, result; |
2745 | 2762 | ||
2763 | /* | ||
2764 | * We do a pretty difficult piece of bootstrap by reading the | ||
2765 | * MFT (and other metadata) from disk into memory. We'll only | ||
2766 | * release this metadata during umount, so the locking patterns | ||
2767 | * observed during bootstrap do not count. So turn off the | ||
2768 | * observation of locking patterns (strictly for this context | ||
2769 | * only) while mounting NTFS. [The validator is still active | ||
2770 | * otherwise, even for this context: it will for example record | ||
2771 | * lock class registrations.] | ||
2772 | */ | ||
2773 | lockdep_off(); | ||
2746 | ntfs_debug("Entering."); | 2774 | ntfs_debug("Entering."); |
2747 | #ifndef NTFS_RW | 2775 | #ifndef NTFS_RW |
2748 | sb->s_flags |= MS_RDONLY; | 2776 | sb->s_flags |= MS_RDONLY; |
@@ -2754,6 +2782,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2754 | if (!silent) | 2782 | if (!silent) |
2755 | ntfs_error(sb, "Allocation of NTFS volume structure " | 2783 | ntfs_error(sb, "Allocation of NTFS volume structure " |
2756 | "failed. Aborting mount..."); | 2784 | "failed. Aborting mount..."); |
2785 | lockdep_on(); | ||
2757 | return -ENOMEM; | 2786 | return -ENOMEM; |
2758 | } | 2787 | } |
2759 | /* Initialize ntfs_volume structure. */ | 2788 | /* Initialize ntfs_volume structure. */ |
@@ -2940,6 +2969,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2940 | mutex_unlock(&ntfs_lock); | 2969 | mutex_unlock(&ntfs_lock); |
2941 | sb->s_export_op = &ntfs_export_ops; | 2970 | sb->s_export_op = &ntfs_export_ops; |
2942 | lock_kernel(); | 2971 | lock_kernel(); |
2972 | lockdep_on(); | ||
2943 | return 0; | 2973 | return 0; |
2944 | } | 2974 | } |
2945 | ntfs_error(sb, "Failed to allocate root directory."); | 2975 | ntfs_error(sb, "Failed to allocate root directory."); |
@@ -3059,6 +3089,7 @@ err_out_now: | |||
3059 | sb->s_fs_info = NULL; | 3089 | sb->s_fs_info = NULL; |
3060 | kfree(vol); | 3090 | kfree(vol); |
3061 | ntfs_debug("Failed, returning -EINVAL."); | 3091 | ntfs_debug("Failed, returning -EINVAL."); |
3092 | lockdep_on(); | ||
3062 | return -EINVAL; | 3093 | return -EINVAL; |
3063 | } | 3094 | } |
3064 | 3095 | ||