diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/linux-2.6/mrlock.h | 12 | ||||
-rw-r--r-- | fs/xfs/xfs_iget.c | 15 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 60 | ||||
-rw-r--r-- | fs/xfs/xfs_vfsops.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 27 |
5 files changed, 88 insertions, 28 deletions
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h index af168a1a98c1..c110bb002665 100644 --- a/fs/xfs/linux-2.6/mrlock.h +++ b/fs/xfs/linux-2.6/mrlock.h | |||
@@ -43,6 +43,18 @@ static inline void mrupdate(mrlock_t *mrp) | |||
43 | mrp->mr_writer = 1; | 43 | mrp->mr_writer = 1; |
44 | } | 44 | } |
45 | 45 | ||
46 | static inline void mraccess_nested(mrlock_t *mrp, int subclass) | ||
47 | { | ||
48 | down_read_nested(&mrp->mr_lock, subclass); | ||
49 | } | ||
50 | |||
51 | static inline void mrupdate_nested(mrlock_t *mrp, int subclass) | ||
52 | { | ||
53 | down_write_nested(&mrp->mr_lock, subclass); | ||
54 | mrp->mr_writer = 1; | ||
55 | } | ||
56 | |||
57 | |||
46 | static inline int mrtryaccess(mrlock_t *mrp) | 58 | static inline int mrtryaccess(mrlock_t *mrp) |
47 | { | 59 | { |
48 | return down_read_trylock(&mrp->mr_lock); | 60 | return down_read_trylock(&mrp->mr_lock); |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index c1c89dac19cc..114433a22baa 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -879,17 +879,17 @@ xfs_ilock(xfs_inode_t *ip, | |||
879 | (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); | 879 | (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); |
880 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != | 880 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != |
881 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); | 881 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); |
882 | ASSERT((lock_flags & ~XFS_LOCK_MASK) == 0); | 882 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0); |
883 | 883 | ||
884 | if (lock_flags & XFS_IOLOCK_EXCL) { | 884 | if (lock_flags & XFS_IOLOCK_EXCL) { |
885 | mrupdate(&ip->i_iolock); | 885 | mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags)); |
886 | } else if (lock_flags & XFS_IOLOCK_SHARED) { | 886 | } else if (lock_flags & XFS_IOLOCK_SHARED) { |
887 | mraccess(&ip->i_iolock); | 887 | mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags)); |
888 | } | 888 | } |
889 | if (lock_flags & XFS_ILOCK_EXCL) { | 889 | if (lock_flags & XFS_ILOCK_EXCL) { |
890 | mrupdate(&ip->i_lock); | 890 | mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags)); |
891 | } else if (lock_flags & XFS_ILOCK_SHARED) { | 891 | } else if (lock_flags & XFS_ILOCK_SHARED) { |
892 | mraccess(&ip->i_lock); | 892 | mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags)); |
893 | } | 893 | } |
894 | xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address); | 894 | xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address); |
895 | } | 895 | } |
@@ -923,7 +923,7 @@ xfs_ilock_nowait(xfs_inode_t *ip, | |||
923 | (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); | 923 | (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); |
924 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != | 924 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != |
925 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); | 925 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); |
926 | ASSERT((lock_flags & ~XFS_LOCK_MASK) == 0); | 926 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0); |
927 | 927 | ||
928 | iolocked = 0; | 928 | iolocked = 0; |
929 | if (lock_flags & XFS_IOLOCK_EXCL) { | 929 | if (lock_flags & XFS_IOLOCK_EXCL) { |
@@ -983,7 +983,8 @@ xfs_iunlock(xfs_inode_t *ip, | |||
983 | (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); | 983 | (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); |
984 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != | 984 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != |
985 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); | 985 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); |
986 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_IUNLOCK_NONOTIFY)) == 0); | 986 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_IUNLOCK_NONOTIFY | |
987 | XFS_LOCK_DEP_MASK)) == 0); | ||
987 | ASSERT(lock_flags != 0); | 988 | ASSERT(lock_flags != 0); |
988 | 989 | ||
989 | if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) { | 990 | if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) { |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index cfe7b58c4533..f75afecef8e7 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -382,26 +382,58 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) | |||
382 | 382 | ||
383 | /* | 383 | /* |
384 | * Flags for inode locking. | 384 | * Flags for inode locking. |
385 | * Bit ranges: 1<<1 - 1<<16-1 -- iolock/ilock modes (bitfield) | ||
386 | * 1<<16 - 1<<32-1 -- lockdep annotation (integers) | ||
385 | */ | 387 | */ |
386 | #define XFS_IOLOCK_EXCL 0x001 | 388 | #define XFS_IOLOCK_EXCL (1<<0) |
387 | #define XFS_IOLOCK_SHARED 0x002 | 389 | #define XFS_IOLOCK_SHARED (1<<1) |
388 | #define XFS_ILOCK_EXCL 0x004 | 390 | #define XFS_ILOCK_EXCL (1<<2) |
389 | #define XFS_ILOCK_SHARED 0x008 | 391 | #define XFS_ILOCK_SHARED (1<<3) |
390 | #define XFS_IUNLOCK_NONOTIFY 0x010 | 392 | #define XFS_IUNLOCK_NONOTIFY (1<<4) |
391 | /* XFS_IOLOCK_NESTED 0x020 */ | 393 | /* #define XFS_IOLOCK_NESTED (1<<5) */ |
392 | #define XFS_EXTENT_TOKEN_RD 0x040 | 394 | #define XFS_EXTENT_TOKEN_RD (1<<6) |
393 | #define XFS_SIZE_TOKEN_RD 0x080 | 395 | #define XFS_SIZE_TOKEN_RD (1<<7) |
394 | #define XFS_EXTSIZE_RD (XFS_EXTENT_TOKEN_RD|XFS_SIZE_TOKEN_RD) | 396 | #define XFS_EXTSIZE_RD (XFS_EXTENT_TOKEN_RD|XFS_SIZE_TOKEN_RD) |
395 | #define XFS_WILLLEND 0x100 /* Always acquire tokens for lending */ | 397 | #define XFS_WILLLEND (1<<8) /* Always acquire tokens for lending */ |
396 | #define XFS_EXTENT_TOKEN_WR (XFS_EXTENT_TOKEN_RD | XFS_WILLLEND) | 398 | #define XFS_EXTENT_TOKEN_WR (XFS_EXTENT_TOKEN_RD | XFS_WILLLEND) |
397 | #define XFS_SIZE_TOKEN_WR (XFS_SIZE_TOKEN_RD | XFS_WILLLEND) | 399 | #define XFS_SIZE_TOKEN_WR (XFS_SIZE_TOKEN_RD | XFS_WILLLEND) |
398 | #define XFS_EXTSIZE_WR (XFS_EXTSIZE_RD | XFS_WILLLEND) | 400 | #define XFS_EXTSIZE_WR (XFS_EXTSIZE_RD | XFS_WILLLEND) |
399 | /* XFS_SIZE_TOKEN_WANT 0x200 */ | 401 | /* TODO:XFS_SIZE_TOKEN_WANT (1<<9) */ |
400 | 402 | ||
401 | #define XFS_LOCK_MASK \ | 403 | #define XFS_LOCK_MASK (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED \ |
402 | (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL | \ | 404 | | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED \ |
403 | XFS_ILOCK_SHARED | XFS_EXTENT_TOKEN_RD | XFS_SIZE_TOKEN_RD | \ | 405 | | XFS_EXTENT_TOKEN_RD | XFS_SIZE_TOKEN_RD \ |
404 | XFS_WILLLEND) | 406 | | XFS_WILLLEND) |
407 | |||
408 | /* | ||
409 | * Flags for lockdep annotations. | ||
410 | * | ||
411 | * XFS_I[O]LOCK_PARENT - for operations that require locking two inodes | ||
412 | * (ie directory operations that require locking a directory inode and | ||
413 | * an entry inode). The first inode gets locked with this flag so it | ||
414 | * gets a lockdep subclass of 1 and the second lock will have a lockdep | ||
415 | * subclass of 0. | ||
416 | * | ||
417 | * XFS_I[O]LOCK_INUMORDER - for locking several inodes at the some time | ||
418 | * with xfs_lock_inodes(). This flag is used as the starting subclass | ||
419 | * and each subsequent lock acquired will increment the subclass by one. | ||
420 | * So the first lock acquired will have a lockdep subclass of 2, the | ||
421 | * second lock will have a lockdep subclass of 3, and so on. | ||
422 | */ | ||
423 | #define XFS_IOLOCK_SHIFT 16 | ||
424 | #define XFS_IOLOCK_PARENT (1 << XFS_IOLOCK_SHIFT) | ||
425 | #define XFS_IOLOCK_INUMORDER (2 << XFS_IOLOCK_SHIFT) | ||
426 | |||
427 | #define XFS_ILOCK_SHIFT 24 | ||
428 | #define XFS_ILOCK_PARENT (1 << XFS_ILOCK_SHIFT) | ||
429 | #define XFS_ILOCK_INUMORDER (2 << XFS_ILOCK_SHIFT) | ||
430 | |||
431 | #define XFS_IOLOCK_DEP_MASK 0x00ff0000 | ||
432 | #define XFS_ILOCK_DEP_MASK 0xff000000 | ||
433 | #define XFS_LOCK_DEP_MASK (XFS_IOLOCK_DEP_MASK | XFS_ILOCK_DEP_MASK) | ||
434 | |||
435 | #define XFS_IOLOCK_DEP(flags) (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT) | ||
436 | #define XFS_ILOCK_DEP(flags) (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT) | ||
405 | 437 | ||
406 | /* | 438 | /* |
407 | * Flags for xfs_iflush() | 439 | * Flags for xfs_iflush() |
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 2e830e7f52e0..65c561201cb8 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c | |||
@@ -696,7 +696,7 @@ xfs_unmount_flush( | |||
696 | bhv_vnode_t *rvp = XFS_ITOV(rip); | 696 | bhv_vnode_t *rvp = XFS_ITOV(rip); |
697 | int error; | 697 | int error; |
698 | 698 | ||
699 | xfs_ilock(rip, XFS_ILOCK_EXCL); | 699 | xfs_ilock(rip, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); |
700 | xfs_iflock(rip); | 700 | xfs_iflock(rip); |
701 | 701 | ||
702 | /* | 702 | /* |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index e2c9bbc27823..de17aed578f0 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1947,7 +1947,7 @@ xfs_create( | |||
1947 | goto error_return; | 1947 | goto error_return; |
1948 | } | 1948 | } |
1949 | 1949 | ||
1950 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 1950 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); |
1951 | 1951 | ||
1952 | XFS_BMAP_INIT(&free_list, &first_block); | 1952 | XFS_BMAP_INIT(&free_list, &first_block); |
1953 | 1953 | ||
@@ -2141,7 +2141,7 @@ xfs_lock_dir_and_entry( | |||
2141 | attempts = 0; | 2141 | attempts = 0; |
2142 | 2142 | ||
2143 | again: | 2143 | again: |
2144 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 2144 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); |
2145 | 2145 | ||
2146 | e_inum = ip->i_ino; | 2146 | e_inum = ip->i_ino; |
2147 | 2147 | ||
@@ -2210,6 +2210,21 @@ int xfs_lock_delays; | |||
2210 | #endif | 2210 | #endif |
2211 | 2211 | ||
2212 | /* | 2212 | /* |
2213 | * Bump the subclass so xfs_lock_inodes() acquires each lock with | ||
2214 | * a different value | ||
2215 | */ | ||
2216 | static inline int | ||
2217 | xfs_lock_inumorder(int lock_mode, int subclass) | ||
2218 | { | ||
2219 | if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) | ||
2220 | lock_mode |= (subclass + XFS_IOLOCK_INUMORDER) << XFS_IOLOCK_SHIFT; | ||
2221 | if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) | ||
2222 | lock_mode |= (subclass + XFS_ILOCK_INUMORDER) << XFS_ILOCK_SHIFT; | ||
2223 | |||
2224 | return lock_mode; | ||
2225 | } | ||
2226 | |||
2227 | /* | ||
2213 | * The following routine will lock n inodes in exclusive mode. | 2228 | * The following routine will lock n inodes in exclusive mode. |
2214 | * We assume the caller calls us with the inodes in i_ino order. | 2229 | * We assume the caller calls us with the inodes in i_ino order. |
2215 | * | 2230 | * |
@@ -2276,7 +2291,7 @@ again: | |||
2276 | * that is in the AIL. | 2291 | * that is in the AIL. |
2277 | */ | 2292 | */ |
2278 | ASSERT(i != 0); | 2293 | ASSERT(i != 0); |
2279 | if (!xfs_ilock_nowait(ips[i], lock_mode)) { | 2294 | if (!xfs_ilock_nowait(ips[i], xfs_lock_inumorder(lock_mode, i))) { |
2280 | attempts++; | 2295 | attempts++; |
2281 | 2296 | ||
2282 | /* | 2297 | /* |
@@ -2311,7 +2326,7 @@ again: | |||
2311 | goto again; | 2326 | goto again; |
2312 | } | 2327 | } |
2313 | } else { | 2328 | } else { |
2314 | xfs_ilock(ips[i], lock_mode); | 2329 | xfs_ilock(ips[i], xfs_lock_inumorder(lock_mode, i)); |
2315 | } | 2330 | } |
2316 | } | 2331 | } |
2317 | 2332 | ||
@@ -2845,7 +2860,7 @@ xfs_mkdir( | |||
2845 | goto error_return; | 2860 | goto error_return; |
2846 | } | 2861 | } |
2847 | 2862 | ||
2848 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 2863 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); |
2849 | 2864 | ||
2850 | /* | 2865 | /* |
2851 | * Check for directory link count overflow. | 2866 | * Check for directory link count overflow. |
@@ -3399,7 +3414,7 @@ xfs_symlink( | |||
3399 | goto error_return; | 3414 | goto error_return; |
3400 | } | 3415 | } |
3401 | 3416 | ||
3402 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 3417 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); |
3403 | 3418 | ||
3404 | /* | 3419 | /* |
3405 | * Check whether the directory allows new symlinks or not. | 3420 | * Check whether the directory allows new symlinks or not. |