diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-07 11:10:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-07 11:10:48 -0500 |
commit | 5331be090567d9335476f876b2d85427cd7c4426 (patch) | |
tree | 356842da9d4c3966a9781f6eb05fa77beec144bc /fs | |
parent | d3f8fd765e94b9137e1f27bbb0ac25289f9e565c (diff) | |
parent | 7220c0177b45600eef2cfd3e5e57ab5b96f3222c (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6:
JFS: Remove incorrect kgdb define
JFS: call io_schedule() instead of schedule() to avoid deadlock
JFS: Add lockdep annotations
JFS: Avoid BUG() on a damaged file system
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jfs/inode.c | 6 | ||||
-rw-r--r-- | fs/jfs/jfs_debug.h | 5 | ||||
-rw-r--r-- | fs/jfs/jfs_dmap.c | 16 | ||||
-rw-r--r-- | fs/jfs/jfs_imap.c | 16 | ||||
-rw-r--r-- | fs/jfs/jfs_incore.h | 29 | ||||
-rw-r--r-- | fs/jfs/jfs_lock.h | 2 | ||||
-rw-r--r-- | fs/jfs/jfs_metapage.c | 2 | ||||
-rw-r--r-- | fs/jfs/jfs_txnmgr.c | 2 | ||||
-rw-r--r-- | fs/jfs/jfs_xtree.c | 15 | ||||
-rw-r--r-- | fs/jfs/namei.c | 48 |
10 files changed, 92 insertions, 49 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_debug.h b/fs/jfs/jfs_debug.h index ddffbbd4d955..7378798f0b21 100644 --- a/fs/jfs/jfs_debug.h +++ b/fs/jfs/jfs_debug.h | |||
@@ -39,10 +39,6 @@ extern void jfs_proc_clean(void); | |||
39 | /* | 39 | /* |
40 | * assert with traditional printf/panic | 40 | * assert with traditional printf/panic |
41 | */ | 41 | */ |
42 | #ifdef CONFIG_KERNEL_ASSERTS | ||
43 | /* kgdb stuff */ | ||
44 | #define assert(p) KERNEL_ASSERT(#p, p) | ||
45 | #else | ||
46 | #define assert(p) do { \ | 42 | #define assert(p) do { \ |
47 | if (!(p)) { \ | 43 | if (!(p)) { \ |
48 | printk(KERN_CRIT "BUG at %s:%d assert(%s)\n", \ | 44 | printk(KERN_CRIT "BUG at %s:%d assert(%s)\n", \ |
@@ -50,7 +46,6 @@ extern void jfs_proc_clean(void); | |||
50 | BUG(); \ | 46 | BUG(); \ |
51 | } \ | 47 | } \ |
52 | } while (0) | 48 | } while (0) |
53 | #endif | ||
54 | 49 | ||
55 | /* | 50 | /* |
56 | * debug ON | 51 | * debug ON |
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 | */ | ||
135 | enum 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 | */ | ||
148 | enum 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/jfs_lock.h b/fs/jfs/jfs_lock.h index 7d78e83d7c40..df48ece4b7a3 100644 --- a/fs/jfs/jfs_lock.h +++ b/fs/jfs/jfs_lock.h | |||
@@ -42,7 +42,7 @@ do { \ | |||
42 | if (cond) \ | 42 | if (cond) \ |
43 | break; \ | 43 | break; \ |
44 | unlock_cmd; \ | 44 | unlock_cmd; \ |
45 | schedule(); \ | 45 | io_schedule(); \ |
46 | lock_cmd; \ | 46 | lock_cmd; \ |
47 | } \ | 47 | } \ |
48 | current->state = TASK_RUNNING; \ | 48 | current->state = TASK_RUNNING; \ |
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index ceaf03b94935..58deae007507 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c | |||
@@ -56,7 +56,7 @@ static inline void __lock_metapage(struct metapage *mp) | |||
56 | set_current_state(TASK_UNINTERRUPTIBLE); | 56 | set_current_state(TASK_UNINTERRUPTIBLE); |
57 | if (metapage_locked(mp)) { | 57 | if (metapage_locked(mp)) { |
58 | unlock_page(mp->page); | 58 | unlock_page(mp->page); |
59 | schedule(); | 59 | io_schedule(); |
60 | lock_page(mp->page); | 60 | lock_page(mp->page); |
61 | } | 61 | } |
62 | } while (trylock_metapage(mp)); | 62 | } while (trylock_metapage(mp)); |
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index d558e51b0df8..6988a1082f58 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c | |||
@@ -135,7 +135,7 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event) | |||
135 | add_wait_queue(event, &wait); | 135 | add_wait_queue(event, &wait); |
136 | set_current_state(TASK_UNINTERRUPTIBLE); | 136 | set_current_state(TASK_UNINTERRUPTIBLE); |
137 | TXN_UNLOCK(); | 137 | TXN_UNLOCK(); |
138 | schedule(); | 138 | io_schedule(); |
139 | current->state = TASK_RUNNING; | 139 | current->state = TASK_RUNNING; |
140 | remove_wait_queue(event, &wait); | 140 | remove_wait_queue(event, &wait); |
141 | } | 141 | } |
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index e98eb03e5310..acc97c46d8a4 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c | |||
@@ -757,6 +757,11 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp, | |||
757 | nsplit = 0; | 757 | nsplit = 0; |
758 | 758 | ||
759 | /* push (bn, index) of the parent page/entry */ | 759 | /* push (bn, index) of the parent page/entry */ |
760 | if (BT_STACK_FULL(btstack)) { | ||
761 | jfs_error(ip->i_sb, "stack overrun in xtSearch!"); | ||
762 | XT_PUTPAGE(mp); | ||
763 | return -EIO; | ||
764 | } | ||
760 | BT_PUSH(btstack, bn, index); | 765 | BT_PUSH(btstack, bn, index); |
761 | 766 | ||
762 | /* get the child page block number */ | 767 | /* get the child page block number */ |
@@ -3915,6 +3920,11 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) | |||
3915 | */ | 3920 | */ |
3916 | getChild: | 3921 | getChild: |
3917 | /* save current parent entry for the child page */ | 3922 | /* save current parent entry for the child page */ |
3923 | if (BT_STACK_FULL(&btstack)) { | ||
3924 | jfs_error(ip->i_sb, "stack overrun in xtTruncate!"); | ||
3925 | XT_PUTPAGE(mp); | ||
3926 | return -EIO; | ||
3927 | } | ||
3918 | BT_PUSH(&btstack, bn, index); | 3928 | BT_PUSH(&btstack, bn, index); |
3919 | 3929 | ||
3920 | /* get child page */ | 3930 | /* get child page */ |
@@ -4112,6 +4122,11 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) | |||
4112 | */ | 4122 | */ |
4113 | getChild: | 4123 | getChild: |
4114 | /* save current parent entry for the child page */ | 4124 | /* save current parent entry for the child page */ |
4125 | if (BT_STACK_FULL(&btstack)) { | ||
4126 | jfs_error(ip->i_sb, "stack overrun in xtTruncate_pmap!"); | ||
4127 | XT_PUTPAGE(mp); | ||
4128 | return -EIO; | ||
4129 | } | ||
4115 | BT_PUSH(&btstack, bn, index); | 4130 | BT_PUSH(&btstack, bn, index); |
4116 | 4131 | ||
4117 | /* get child page */ | 4132 | /* get child page */ |
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) |