aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jfs/inode.c6
-rw-r--r--fs/jfs/jfs_dmap.c16
-rw-r--r--fs/jfs/jfs_imap.c16
-rw-r--r--fs/jfs/jfs_incore.h29
-rw-r--r--fs/jfs/namei.c48
5 files changed, 74 insertions, 41 deletions
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index f5719117edfe..e285022f006c 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -182,9 +182,9 @@ int jfs_get_block(struct inode *ip, sector_t lblock,
182 * Take appropriate lock on inode 182 * Take appropriate lock on inode
183 */ 183 */
184 if (create) 184 if (create)
185 IWRITE_LOCK(ip); 185 IWRITE_LOCK(ip, RDWRLOCK_NORMAL);
186 else 186 else
187 IREAD_LOCK(ip); 187 IREAD_LOCK(ip, RDWRLOCK_NORMAL);
188 188
189 if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && 189 if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
190 (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) && 190 (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) &&
@@ -359,7 +359,7 @@ void jfs_truncate(struct inode *ip)
359 359
360 nobh_truncate_page(ip->i_mapping, ip->i_size); 360 nobh_truncate_page(ip->i_mapping, ip->i_size);
361 361
362 IWRITE_LOCK(ip); 362 IWRITE_LOCK(ip, RDWRLOCK_NORMAL);
363 jfs_truncate_nolock(ip, ip->i_size); 363 jfs_truncate_nolock(ip, ip->i_size);
364 IWRITE_UNLOCK(ip); 364 IWRITE_UNLOCK(ip);
365} 365}
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 23546c8fd48b..82b0544bd76d 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -337,7 +337,7 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
337 struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap; 337 struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
338 struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; 338 struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
339 339
340 IREAD_LOCK(ipbmap); 340 IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
341 341
342 /* block to be freed better be within the mapsize. */ 342 /* block to be freed better be within the mapsize. */
343 if (unlikely((blkno == 0) || (blkno + nblocks > bmp->db_mapsize))) { 343 if (unlikely((blkno == 0) || (blkno + nblocks > bmp->db_mapsize))) {
@@ -733,7 +733,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
733 * allocation group size, try to allocate anywhere. 733 * allocation group size, try to allocate anywhere.
734 */ 734 */
735 if (l2nb > bmp->db_agl2size) { 735 if (l2nb > bmp->db_agl2size) {
736 IWRITE_LOCK(ipbmap); 736 IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
737 737
738 rc = dbAllocAny(bmp, nblocks, l2nb, results); 738 rc = dbAllocAny(bmp, nblocks, l2nb, results);
739 739
@@ -774,7 +774,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
774 * the hint using a tiered strategy. 774 * the hint using a tiered strategy.
775 */ 775 */
776 if (nblocks <= BPERDMAP) { 776 if (nblocks <= BPERDMAP) {
777 IREAD_LOCK(ipbmap); 777 IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
778 778
779 /* get the buffer for the dmap containing the hint. 779 /* get the buffer for the dmap containing the hint.
780 */ 780 */
@@ -844,7 +844,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
844 /* try to satisfy the allocation request with blocks within 844 /* try to satisfy the allocation request with blocks within
845 * the same allocation group as the hint. 845 * the same allocation group as the hint.
846 */ 846 */
847 IWRITE_LOCK(ipbmap); 847 IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
848 if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) != -ENOSPC) 848 if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) != -ENOSPC)
849 goto write_unlock; 849 goto write_unlock;
850 850
@@ -856,7 +856,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
856 * Let dbNextAG recommend a preferred allocation group 856 * Let dbNextAG recommend a preferred allocation group
857 */ 857 */
858 agno = dbNextAG(ipbmap); 858 agno = dbNextAG(ipbmap);
859 IWRITE_LOCK(ipbmap); 859 IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
860 860
861 /* Try to allocate within this allocation group. if that fails, try to 861 /* Try to allocate within this allocation group. if that fails, try to
862 * allocate anywhere in the map. 862 * allocate anywhere in the map.
@@ -900,7 +900,7 @@ int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
900 s64 lblkno; 900 s64 lblkno;
901 struct metapage *mp; 901 struct metapage *mp;
902 902
903 IREAD_LOCK(ipbmap); 903 IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
904 904
905 /* 905 /*
906 * validate extent request: 906 * validate extent request:
@@ -1050,7 +1050,7 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
1050 */ 1050 */
1051 extblkno = lastblkno + 1; 1051 extblkno = lastblkno + 1;
1052 1052
1053 IREAD_LOCK(ipbmap); 1053 IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
1054 1054
1055 /* better be within the file system */ 1055 /* better be within the file system */
1056 bmp = sbi->bmap; 1056 bmp = sbi->bmap;
@@ -3116,7 +3116,7 @@ int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks)
3116 struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap; 3116 struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
3117 struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; 3117 struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
3118 3118
3119 IREAD_LOCK(ipbmap); 3119 IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
3120 3120
3121 /* block to be allocated better be within the mapsize. */ 3121 /* block to be allocated better be within the mapsize. */
3122 ASSERT(nblocks <= bmp->db_mapsize - blkno); 3122 ASSERT(nblocks <= bmp->db_mapsize - blkno);
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 53f63b47a6d3..aa5124b643b1 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -331,7 +331,7 @@ int diRead(struct inode *ip)
331 331
332 /* read the iag */ 332 /* read the iag */
333 imap = JFS_IP(ipimap)->i_imap; 333 imap = JFS_IP(ipimap)->i_imap;
334 IREAD_LOCK(ipimap); 334 IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
335 rc = diIAGRead(imap, iagno, &mp); 335 rc = diIAGRead(imap, iagno, &mp);
336 IREAD_UNLOCK(ipimap); 336 IREAD_UNLOCK(ipimap);
337 if (rc) { 337 if (rc) {
@@ -920,7 +920,7 @@ int diFree(struct inode *ip)
920 /* Obtain read lock in imap inode. Don't release it until we have 920 /* Obtain read lock in imap inode. Don't release it until we have
921 * read all of the IAG's that we are going to. 921 * read all of the IAG's that we are going to.
922 */ 922 */
923 IREAD_LOCK(ipimap); 923 IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
924 924
925 /* read the iag. 925 /* read the iag.
926 */ 926 */
@@ -1415,7 +1415,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
1415 AG_LOCK(imap, agno); 1415 AG_LOCK(imap, agno);
1416 1416
1417 /* Get read lock on imap inode */ 1417 /* Get read lock on imap inode */
1418 IREAD_LOCK(ipimap); 1418 IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
1419 1419
1420 /* get the iag number and read the iag */ 1420 /* get the iag number and read the iag */
1421 iagno = INOTOIAG(inum); 1421 iagno = INOTOIAG(inum);
@@ -1808,7 +1808,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
1808 return -ENOSPC; 1808 return -ENOSPC;
1809 1809
1810 /* obtain read lock on imap inode */ 1810 /* obtain read lock on imap inode */
1811 IREAD_LOCK(imap->im_ipimap); 1811 IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP);
1812 1812
1813 /* read the iag at the head of the list. 1813 /* read the iag at the head of the list.
1814 */ 1814 */
@@ -1946,7 +1946,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
1946 } else { 1946 } else {
1947 /* read the iag. 1947 /* read the iag.
1948 */ 1948 */
1949 IREAD_LOCK(imap->im_ipimap); 1949 IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP);
1950 if ((rc = diIAGRead(imap, iagno, &mp))) { 1950 if ((rc = diIAGRead(imap, iagno, &mp))) {
1951 IREAD_UNLOCK(imap->im_ipimap); 1951 IREAD_UNLOCK(imap->im_ipimap);
1952 jfs_error(ip->i_sb, "diAllocExt: error reading iag"); 1952 jfs_error(ip->i_sb, "diAllocExt: error reading iag");
@@ -2509,7 +2509,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
2509 */ 2509 */
2510 2510
2511 /* acquire inode map lock */ 2511 /* acquire inode map lock */
2512 IWRITE_LOCK(ipimap); 2512 IWRITE_LOCK(ipimap, RDWRLOCK_IMAP);
2513 2513
2514 if (ipimap->i_size >> L2PSIZE != imap->im_nextiag + 1) { 2514 if (ipimap->i_size >> L2PSIZE != imap->im_nextiag + 1) {
2515 IWRITE_UNLOCK(ipimap); 2515 IWRITE_UNLOCK(ipimap);
@@ -2648,7 +2648,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
2648 } 2648 }
2649 2649
2650 /* obtain read lock on map */ 2650 /* obtain read lock on map */
2651 IREAD_LOCK(ipimap); 2651 IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
2652 2652
2653 /* read the iag */ 2653 /* read the iag */
2654 if ((rc = diIAGRead(imap, iagno, &mp))) { 2654 if ((rc = diIAGRead(imap, iagno, &mp))) {
@@ -2779,7 +2779,7 @@ diUpdatePMap(struct inode *ipimap,
2779 return -EIO; 2779 return -EIO;
2780 } 2780 }
2781 /* read the iag */ 2781 /* read the iag */
2782 IREAD_LOCK(ipimap); 2782 IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
2783 rc = diIAGRead(imap, iagno, &mp); 2783 rc = diIAGRead(imap, iagno, &mp);
2784 IREAD_UNLOCK(ipimap); 2784 IREAD_UNLOCK(ipimap);
2785 if (rc) 2785 if (rc)
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index 94005584445a..8f453eff3c83 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -109,9 +109,11 @@ struct jfs_inode_info {
109 109
110#define JFS_ACL_NOT_CACHED ((void *)-1) 110#define JFS_ACL_NOT_CACHED ((void *)-1)
111 111
112#define IREAD_LOCK(ip) down_read(&JFS_IP(ip)->rdwrlock) 112#define IREAD_LOCK(ip, subclass) \
113 down_read_nested(&JFS_IP(ip)->rdwrlock, subclass)
113#define IREAD_UNLOCK(ip) up_read(&JFS_IP(ip)->rdwrlock) 114#define IREAD_UNLOCK(ip) up_read(&JFS_IP(ip)->rdwrlock)
114#define IWRITE_LOCK(ip) down_write(&JFS_IP(ip)->rdwrlock) 115#define IWRITE_LOCK(ip, subclass) \
116 down_write_nested(&JFS_IP(ip)->rdwrlock, subclass)
115#define IWRITE_UNLOCK(ip) up_write(&JFS_IP(ip)->rdwrlock) 117#define IWRITE_UNLOCK(ip) up_write(&JFS_IP(ip)->rdwrlock)
116 118
117/* 119/*
@@ -127,6 +129,29 @@ enum cflags {
127 COMMIT_Synclist, /* metadata pages on group commit synclist */ 129 COMMIT_Synclist, /* metadata pages on group commit synclist */
128}; 130};
129 131
132/*
133 * commit_mutex nesting subclasses:
134 */
135enum commit_mutex_class
136{
137 COMMIT_MUTEX_PARENT,
138 COMMIT_MUTEX_CHILD,
139 COMMIT_MUTEX_SECOND_PARENT, /* Renaming */
140 COMMIT_MUTEX_VICTIM /* Inode being unlinked due to rename */
141};
142
143/*
144 * rdwrlock subclasses:
145 * The dmap inode may be locked while a normal inode or the imap inode are
146 * locked.
147 */
148enum rdwrlock_class
149{
150 RDWRLOCK_NORMAL,
151 RDWRLOCK_IMAP,
152 RDWRLOCK_DMAP
153};
154
130#define set_cflag(flag, ip) set_bit(flag, &(JFS_IP(ip)->cflag)) 155#define set_cflag(flag, ip) set_bit(flag, &(JFS_IP(ip)->cflag))
131#define clear_cflag(flag, ip) clear_bit(flag, &(JFS_IP(ip)->cflag)) 156#define clear_cflag(flag, ip) clear_bit(flag, &(JFS_IP(ip)->cflag))
132#define test_cflag(flag, ip) test_bit(flag, &(JFS_IP(ip)->cflag)) 157#define test_cflag(flag, ip) test_bit(flag, &(JFS_IP(ip)->cflag))
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index a6a8c16c872c..7ab47561b68d 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -104,8 +104,8 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
104 104
105 tid = txBegin(dip->i_sb, 0); 105 tid = txBegin(dip->i_sb, 0);
106 106
107 mutex_lock(&JFS_IP(dip)->commit_mutex); 107 mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
108 mutex_lock(&JFS_IP(ip)->commit_mutex); 108 mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
109 109
110 rc = jfs_init_acl(tid, ip, dip); 110 rc = jfs_init_acl(tid, ip, dip);
111 if (rc) 111 if (rc)
@@ -238,8 +238,8 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
238 238
239 tid = txBegin(dip->i_sb, 0); 239 tid = txBegin(dip->i_sb, 0);
240 240
241 mutex_lock(&JFS_IP(dip)->commit_mutex); 241 mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
242 mutex_lock(&JFS_IP(ip)->commit_mutex); 242 mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
243 243
244 rc = jfs_init_acl(tid, ip, dip); 244 rc = jfs_init_acl(tid, ip, dip);
245 if (rc) 245 if (rc)
@@ -365,8 +365,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
365 365
366 tid = txBegin(dip->i_sb, 0); 366 tid = txBegin(dip->i_sb, 0);
367 367
368 mutex_lock(&JFS_IP(dip)->commit_mutex); 368 mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
369 mutex_lock(&JFS_IP(ip)->commit_mutex); 369 mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
370 370
371 iplist[0] = dip; 371 iplist[0] = dip;
372 iplist[1] = ip; 372 iplist[1] = ip;
@@ -483,12 +483,12 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
483 if ((rc = get_UCSname(&dname, dentry))) 483 if ((rc = get_UCSname(&dname, dentry)))
484 goto out; 484 goto out;
485 485
486 IWRITE_LOCK(ip); 486 IWRITE_LOCK(ip, RDWRLOCK_NORMAL);
487 487
488 tid = txBegin(dip->i_sb, 0); 488 tid = txBegin(dip->i_sb, 0);
489 489
490 mutex_lock(&JFS_IP(dip)->commit_mutex); 490 mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
491 mutex_lock(&JFS_IP(ip)->commit_mutex); 491 mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
492 492
493 iplist[0] = dip; 493 iplist[0] = dip;
494 iplist[1] = ip; 494 iplist[1] = ip;
@@ -802,8 +802,8 @@ static int jfs_link(struct dentry *old_dentry,
802 802
803 tid = txBegin(ip->i_sb, 0); 803 tid = txBegin(ip->i_sb, 0);
804 804
805 mutex_lock(&JFS_IP(dir)->commit_mutex); 805 mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
806 mutex_lock(&JFS_IP(ip)->commit_mutex); 806 mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
807 807
808 /* 808 /*
809 * scan parent directory for entry/freespace 809 * scan parent directory for entry/freespace
@@ -913,8 +913,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
913 913
914 tid = txBegin(dip->i_sb, 0); 914 tid = txBegin(dip->i_sb, 0);
915 915
916 mutex_lock(&JFS_IP(dip)->commit_mutex); 916 mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
917 mutex_lock(&JFS_IP(ip)->commit_mutex); 917 mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
918 918
919 rc = jfs_init_security(tid, ip, dip); 919 rc = jfs_init_security(tid, ip, dip);
920 if (rc) 920 if (rc)
@@ -1127,7 +1127,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1127 goto out3; 1127 goto out3;
1128 } 1128 }
1129 } else if (new_ip) { 1129 } else if (new_ip) {
1130 IWRITE_LOCK(new_ip); 1130 IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);
1131 /* Init inode for quota operations. */ 1131 /* Init inode for quota operations. */
1132 DQUOT_INIT(new_ip); 1132 DQUOT_INIT(new_ip);
1133 } 1133 }
@@ -1137,13 +1137,21 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1137 */ 1137 */
1138 tid = txBegin(new_dir->i_sb, 0); 1138 tid = txBegin(new_dir->i_sb, 0);
1139 1139
1140 mutex_lock(&JFS_IP(new_dir)->commit_mutex); 1140 /*
1141 mutex_lock(&JFS_IP(old_ip)->commit_mutex); 1141 * How do we know the locking is safe from deadlocks?
1142 * The vfs does the hard part for us. Any time we are taking nested
1143 * commit_mutexes, the vfs already has i_mutex held on the parent.
1144 * Here, the vfs has already taken i_mutex on both old_dir and new_dir.
1145 */
1146 mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT);
1147 mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1142 if (old_dir != new_dir) 1148 if (old_dir != new_dir)
1143 mutex_lock(&JFS_IP(old_dir)->commit_mutex); 1149 mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex,
1150 COMMIT_MUTEX_SECOND_PARENT);
1144 1151
1145 if (new_ip) { 1152 if (new_ip) {
1146 mutex_lock(&JFS_IP(new_ip)->commit_mutex); 1153 mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex,
1154 COMMIT_MUTEX_VICTIM);
1147 /* 1155 /*
1148 * Change existing directory entry to new inode number 1156 * Change existing directory entry to new inode number
1149 */ 1157 */
@@ -1357,8 +1365,8 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
1357 1365
1358 tid = txBegin(dir->i_sb, 0); 1366 tid = txBegin(dir->i_sb, 0);
1359 1367
1360 mutex_lock(&JFS_IP(dir)->commit_mutex); 1368 mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
1361 mutex_lock(&JFS_IP(ip)->commit_mutex); 1369 mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1362 1370
1363 rc = jfs_init_acl(tid, ip, dir); 1371 rc = jfs_init_acl(tid, ip, dir);
1364 if (rc) 1372 if (rc)