aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/mrlock.h12
-rw-r--r--fs/xfs/xfs_iget.c15
-rw-r--r--fs/xfs/xfs_inode.h60
-rw-r--r--fs/xfs/xfs_vfsops.c2
-rw-r--r--fs/xfs/xfs_vnodeops.c27
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
46static inline void mraccess_nested(mrlock_t *mrp, int subclass)
47{
48 down_read_nested(&mrp->mr_lock, subclass);
49}
50
51static 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
46static inline int mrtryaccess(mrlock_t *mrp) 58static 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
2143again: 2143again:
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 */
2216static inline int
2217xfs_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.