diff options
author | Jeff Mahoney <jeffm@suse.com> | 2013-08-08 17:34:47 -0400 |
---|---|---|
committer | Jeff Mahoney <jeffm@suse.de> | 2013-08-08 17:34:47 -0400 |
commit | d2d0395fd1778d4bf714adc5bfd23a5d748d7802 (patch) | |
tree | 7205eff1242051818b57423142394690620c2731 /fs/reiserfs | |
parent | 278f6679f454bf185a07d9a4ca355b153482d17a (diff) |
reiserfs: locking, release lock around quota operations
Previous commits released the write lock across quota operations but
missed several places. In particular, the free operations can also
call into the file system code and take the write lock, causing
deadlocks.
This patch introduces some more helpers and uses them for quota call
sites. Without this patch applied, reiserfs + quotas runs into deadlocks
under anything more than trivial load.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Diffstat (limited to 'fs/reiserfs')
-rw-r--r-- | fs/reiserfs/bitmap.c | 17 | ||||
-rw-r--r-- | fs/reiserfs/inode.c | 19 | ||||
-rw-r--r-- | fs/reiserfs/stree.c | 28 | ||||
-rw-r--r-- | fs/reiserfs/super.c | 22 |
4 files changed, 63 insertions, 23 deletions
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 881f8ea2a6ac..dc9a6829f7c6 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c | |||
@@ -423,8 +423,11 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
423 | set_sb_free_blocks(rs, sb_free_blocks(rs) + 1); | 423 | set_sb_free_blocks(rs, sb_free_blocks(rs) + 1); |
424 | 424 | ||
425 | journal_mark_dirty(th, s, sbh); | 425 | journal_mark_dirty(th, s, sbh); |
426 | if (for_unformatted) | 426 | if (for_unformatted) { |
427 | int depth = reiserfs_write_unlock_nested(s); | ||
427 | dquot_free_block_nodirty(inode, 1); | 428 | dquot_free_block_nodirty(inode, 1); |
429 | reiserfs_write_lock_nested(s, depth); | ||
430 | } | ||
428 | } | 431 | } |
429 | 432 | ||
430 | void reiserfs_free_block(struct reiserfs_transaction_handle *th, | 433 | void reiserfs_free_block(struct reiserfs_transaction_handle *th, |
@@ -1128,6 +1131,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start | |||
1128 | b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1; | 1131 | b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1; |
1129 | int passno = 0; | 1132 | int passno = 0; |
1130 | int nr_allocated = 0; | 1133 | int nr_allocated = 0; |
1134 | int depth; | ||
1131 | 1135 | ||
1132 | determine_prealloc_size(hint); | 1136 | determine_prealloc_size(hint); |
1133 | if (!hint->formatted_node) { | 1137 | if (!hint->formatted_node) { |
@@ -1137,10 +1141,13 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start | |||
1137 | "reiserquota: allocating %d blocks id=%u", | 1141 | "reiserquota: allocating %d blocks id=%u", |
1138 | amount_needed, hint->inode->i_uid); | 1142 | amount_needed, hint->inode->i_uid); |
1139 | #endif | 1143 | #endif |
1144 | depth = reiserfs_write_unlock_nested(s); | ||
1140 | quota_ret = | 1145 | quota_ret = |
1141 | dquot_alloc_block_nodirty(hint->inode, amount_needed); | 1146 | dquot_alloc_block_nodirty(hint->inode, amount_needed); |
1142 | if (quota_ret) /* Quota exceeded? */ | 1147 | if (quota_ret) { /* Quota exceeded? */ |
1148 | reiserfs_write_lock_nested(s, depth); | ||
1143 | return QUOTA_EXCEEDED; | 1149 | return QUOTA_EXCEEDED; |
1150 | } | ||
1144 | if (hint->preallocate && hint->prealloc_size) { | 1151 | if (hint->preallocate && hint->prealloc_size) { |
1145 | #ifdef REISERQUOTA_DEBUG | 1152 | #ifdef REISERQUOTA_DEBUG |
1146 | reiserfs_debug(s, REISERFS_DEBUG_CODE, | 1153 | reiserfs_debug(s, REISERFS_DEBUG_CODE, |
@@ -1153,6 +1160,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start | |||
1153 | hint->preallocate = hint->prealloc_size = 0; | 1160 | hint->preallocate = hint->prealloc_size = 0; |
1154 | } | 1161 | } |
1155 | /* for unformatted nodes, force large allocations */ | 1162 | /* for unformatted nodes, force large allocations */ |
1163 | reiserfs_write_lock_nested(s, depth); | ||
1156 | } | 1164 | } |
1157 | 1165 | ||
1158 | do { | 1166 | do { |
@@ -1181,9 +1189,11 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start | |||
1181 | hint->inode->i_uid); | 1189 | hint->inode->i_uid); |
1182 | #endif | 1190 | #endif |
1183 | /* Free not allocated blocks */ | 1191 | /* Free not allocated blocks */ |
1192 | depth = reiserfs_write_unlock_nested(s); | ||
1184 | dquot_free_block_nodirty(hint->inode, | 1193 | dquot_free_block_nodirty(hint->inode, |
1185 | amount_needed + hint->prealloc_size - | 1194 | amount_needed + hint->prealloc_size - |
1186 | nr_allocated); | 1195 | nr_allocated); |
1196 | reiserfs_write_lock_nested(s, depth); | ||
1187 | } | 1197 | } |
1188 | while (nr_allocated--) | 1198 | while (nr_allocated--) |
1189 | reiserfs_free_block(hint->th, hint->inode, | 1199 | reiserfs_free_block(hint->th, hint->inode, |
@@ -1214,10 +1224,13 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start | |||
1214 | REISERFS_I(hint->inode)->i_prealloc_count, | 1224 | REISERFS_I(hint->inode)->i_prealloc_count, |
1215 | hint->inode->i_uid); | 1225 | hint->inode->i_uid); |
1216 | #endif | 1226 | #endif |
1227 | |||
1228 | depth = reiserfs_write_unlock_nested(s); | ||
1217 | dquot_free_block_nodirty(hint->inode, amount_needed + | 1229 | dquot_free_block_nodirty(hint->inode, amount_needed + |
1218 | hint->prealloc_size - nr_allocated - | 1230 | hint->prealloc_size - nr_allocated - |
1219 | REISERFS_I(hint->inode)-> | 1231 | REISERFS_I(hint->inode)-> |
1220 | i_prealloc_count); | 1232 | i_prealloc_count); |
1233 | reiserfs_write_lock_nested(s, depth); | ||
1221 | } | 1234 | } |
1222 | 1235 | ||
1223 | return CARRY_ON; | 1236 | return CARRY_ON; |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 4a3a57c66820..ad62bdbb451e 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -57,8 +57,11 @@ void reiserfs_evict_inode(struct inode *inode) | |||
57 | /* Do quota update inside a transaction for journaled quotas. We must do that | 57 | /* Do quota update inside a transaction for journaled quotas. We must do that |
58 | * after delete_object so that quota updates go into the same transaction as | 58 | * after delete_object so that quota updates go into the same transaction as |
59 | * stat data deletion */ | 59 | * stat data deletion */ |
60 | if (!err) | 60 | if (!err) { |
61 | int depth = reiserfs_write_unlock_nested(inode->i_sb); | ||
61 | dquot_free_inode(inode); | 62 | dquot_free_inode(inode); |
63 | reiserfs_write_lock_nested(inode->i_sb, depth); | ||
64 | } | ||
62 | 65 | ||
63 | if (journal_end(&th, inode->i_sb, jbegin_count)) | 66 | if (journal_end(&th, inode->i_sb, jbegin_count)) |
64 | goto out; | 67 | goto out; |
@@ -1768,7 +1771,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1768 | struct inode *inode, | 1771 | struct inode *inode, |
1769 | struct reiserfs_security_handle *security) | 1772 | struct reiserfs_security_handle *security) |
1770 | { | 1773 | { |
1771 | struct super_block *sb; | 1774 | struct super_block *sb = dir->i_sb; |
1772 | struct reiserfs_iget_args args; | 1775 | struct reiserfs_iget_args args; |
1773 | INITIALIZE_PATH(path_to_key); | 1776 | INITIALIZE_PATH(path_to_key); |
1774 | struct cpu_key key; | 1777 | struct cpu_key key; |
@@ -1780,9 +1783,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1780 | 1783 | ||
1781 | BUG_ON(!th->t_trans_id); | 1784 | BUG_ON(!th->t_trans_id); |
1782 | 1785 | ||
1783 | reiserfs_write_unlock(inode->i_sb); | 1786 | depth = reiserfs_write_unlock_nested(sb); |
1784 | err = dquot_alloc_inode(inode); | 1787 | err = dquot_alloc_inode(inode); |
1785 | reiserfs_write_lock(inode->i_sb); | 1788 | reiserfs_write_lock_nested(sb, depth); |
1786 | if (err) | 1789 | if (err) |
1787 | goto out_end_trans; | 1790 | goto out_end_trans; |
1788 | if (!dir->i_nlink) { | 1791 | if (!dir->i_nlink) { |
@@ -1790,8 +1793,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1790 | goto out_bad_inode; | 1793 | goto out_bad_inode; |
1791 | } | 1794 | } |
1792 | 1795 | ||
1793 | sb = dir->i_sb; | ||
1794 | |||
1795 | /* item head of new item */ | 1796 | /* item head of new item */ |
1796 | ih.ih_key.k_dir_id = reiserfs_choose_packing(dir); | 1797 | ih.ih_key.k_dir_id = reiserfs_choose_packing(dir); |
1797 | ih.ih_key.k_objectid = cpu_to_le32(reiserfs_get_unused_objectid(th)); | 1798 | ih.ih_key.k_objectid = cpu_to_le32(reiserfs_get_unused_objectid(th)); |
@@ -1983,14 +1984,16 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1983 | INODE_PKEY(inode)->k_objectid = 0; | 1984 | INODE_PKEY(inode)->k_objectid = 0; |
1984 | 1985 | ||
1985 | /* Quota change must be inside a transaction for journaling */ | 1986 | /* Quota change must be inside a transaction for journaling */ |
1987 | depth = reiserfs_write_unlock_nested(inode->i_sb); | ||
1986 | dquot_free_inode(inode); | 1988 | dquot_free_inode(inode); |
1989 | reiserfs_write_lock_nested(inode->i_sb, depth); | ||
1987 | 1990 | ||
1988 | out_end_trans: | 1991 | out_end_trans: |
1989 | journal_end(th, th->t_super, th->t_blocks_allocated); | 1992 | journal_end(th, th->t_super, th->t_blocks_allocated); |
1990 | reiserfs_write_unlock(inode->i_sb); | ||
1991 | /* Drop can be outside and it needs more credits so it's better to have it outside */ | 1993 | /* Drop can be outside and it needs more credits so it's better to have it outside */ |
1994 | depth = reiserfs_write_unlock_nested(inode->i_sb); | ||
1992 | dquot_drop(inode); | 1995 | dquot_drop(inode); |
1993 | reiserfs_write_lock(inode->i_sb); | 1996 | reiserfs_write_lock_nested(inode->i_sb, depth); |
1994 | inode->i_flags |= S_NOQUOTA; | 1997 | inode->i_flags |= S_NOQUOTA; |
1995 | make_bad_inode(inode); | 1998 | make_bad_inode(inode); |
1996 | 1999 | ||
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 4d7d476d7bff..b14706a05d52 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c | |||
@@ -1186,6 +1186,7 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, | |||
1186 | struct item_head *q_ih; | 1186 | struct item_head *q_ih; |
1187 | int quota_cut_bytes; | 1187 | int quota_cut_bytes; |
1188 | int ret_value, del_size, removed; | 1188 | int ret_value, del_size, removed; |
1189 | int depth; | ||
1189 | 1190 | ||
1190 | #ifdef CONFIG_REISERFS_CHECK | 1191 | #ifdef CONFIG_REISERFS_CHECK |
1191 | char mode; | 1192 | char mode; |
@@ -1295,7 +1296,9 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, | |||
1295 | "reiserquota delete_item(): freeing %u, id=%u type=%c", | 1296 | "reiserquota delete_item(): freeing %u, id=%u type=%c", |
1296 | quota_cut_bytes, inode->i_uid, head2type(&s_ih)); | 1297 | quota_cut_bytes, inode->i_uid, head2type(&s_ih)); |
1297 | #endif | 1298 | #endif |
1299 | depth = reiserfs_write_unlock_nested(inode->i_sb); | ||
1298 | dquot_free_space_nodirty(inode, quota_cut_bytes); | 1300 | dquot_free_space_nodirty(inode, quota_cut_bytes); |
1301 | reiserfs_write_lock_nested(inode->i_sb, depth); | ||
1299 | 1302 | ||
1300 | /* Return deleted body length */ | 1303 | /* Return deleted body length */ |
1301 | return ret_value; | 1304 | return ret_value; |
@@ -1321,6 +1324,7 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, | |||
1321 | void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th, | 1324 | void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th, |
1322 | struct inode *inode, struct reiserfs_key *key) | 1325 | struct inode *inode, struct reiserfs_key *key) |
1323 | { | 1326 | { |
1327 | struct super_block *sb = th->t_super; | ||
1324 | struct tree_balance tb; | 1328 | struct tree_balance tb; |
1325 | INITIALIZE_PATH(path); | 1329 | INITIALIZE_PATH(path); |
1326 | int item_len = 0; | 1330 | int item_len = 0; |
@@ -1373,14 +1377,17 @@ void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th, | |||
1373 | if (retval == CARRY_ON) { | 1377 | if (retval == CARRY_ON) { |
1374 | do_balance(&tb, NULL, NULL, M_DELETE); | 1378 | do_balance(&tb, NULL, NULL, M_DELETE); |
1375 | if (inode) { /* Should we count quota for item? (we don't count quotas for save-links) */ | 1379 | if (inode) { /* Should we count quota for item? (we don't count quotas for save-links) */ |
1380 | int depth; | ||
1376 | #ifdef REISERQUOTA_DEBUG | 1381 | #ifdef REISERQUOTA_DEBUG |
1377 | reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE, | 1382 | reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE, |
1378 | "reiserquota delete_solid_item(): freeing %u id=%u type=%c", | 1383 | "reiserquota delete_solid_item(): freeing %u id=%u type=%c", |
1379 | quota_cut_bytes, inode->i_uid, | 1384 | quota_cut_bytes, inode->i_uid, |
1380 | key2type(key)); | 1385 | key2type(key)); |
1381 | #endif | 1386 | #endif |
1387 | depth = reiserfs_write_unlock_nested(sb); | ||
1382 | dquot_free_space_nodirty(inode, | 1388 | dquot_free_space_nodirty(inode, |
1383 | quota_cut_bytes); | 1389 | quota_cut_bytes); |
1390 | reiserfs_write_lock_nested(sb, depth); | ||
1384 | } | 1391 | } |
1385 | break; | 1392 | break; |
1386 | } | 1393 | } |
@@ -1557,6 +1564,7 @@ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th, | |||
1557 | int retval2 = -1; | 1564 | int retval2 = -1; |
1558 | int quota_cut_bytes; | 1565 | int quota_cut_bytes; |
1559 | loff_t tail_pos = 0; | 1566 | loff_t tail_pos = 0; |
1567 | int depth; | ||
1560 | 1568 | ||
1561 | BUG_ON(!th->t_trans_id); | 1569 | BUG_ON(!th->t_trans_id); |
1562 | 1570 | ||
@@ -1729,7 +1737,9 @@ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th, | |||
1729 | "reiserquota cut_from_item(): freeing %u id=%u type=%c", | 1737 | "reiserquota cut_from_item(): freeing %u id=%u type=%c", |
1730 | quota_cut_bytes, inode->i_uid, '?'); | 1738 | quota_cut_bytes, inode->i_uid, '?'); |
1731 | #endif | 1739 | #endif |
1740 | depth = reiserfs_write_unlock_nested(sb); | ||
1732 | dquot_free_space_nodirty(inode, quota_cut_bytes); | 1741 | dquot_free_space_nodirty(inode, quota_cut_bytes); |
1742 | reiserfs_write_lock_nested(sb, depth); | ||
1733 | return ret_value; | 1743 | return ret_value; |
1734 | } | 1744 | } |
1735 | 1745 | ||
@@ -1949,9 +1959,11 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree | |||
1949 | const char *body, /* Pointer to the bytes to paste. */ | 1959 | const char *body, /* Pointer to the bytes to paste. */ |
1950 | int pasted_size) | 1960 | int pasted_size) |
1951 | { /* Size of pasted bytes. */ | 1961 | { /* Size of pasted bytes. */ |
1962 | struct super_block *sb = inode->i_sb; | ||
1952 | struct tree_balance s_paste_balance; | 1963 | struct tree_balance s_paste_balance; |
1953 | int retval; | 1964 | int retval; |
1954 | int fs_gen; | 1965 | int fs_gen; |
1966 | int depth; | ||
1955 | 1967 | ||
1956 | BUG_ON(!th->t_trans_id); | 1968 | BUG_ON(!th->t_trans_id); |
1957 | 1969 | ||
@@ -1964,9 +1976,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree | |||
1964 | key2type(&(key->on_disk_key))); | 1976 | key2type(&(key->on_disk_key))); |
1965 | #endif | 1977 | #endif |
1966 | 1978 | ||
1967 | reiserfs_write_unlock(inode->i_sb); | 1979 | depth = reiserfs_write_unlock_nested(sb); |
1968 | retval = dquot_alloc_space_nodirty(inode, pasted_size); | 1980 | retval = dquot_alloc_space_nodirty(inode, pasted_size); |
1969 | reiserfs_write_lock(inode->i_sb); | 1981 | reiserfs_write_lock_nested(sb, depth); |
1970 | if (retval) { | 1982 | if (retval) { |
1971 | pathrelse(search_path); | 1983 | pathrelse(search_path); |
1972 | return retval; | 1984 | return retval; |
@@ -2023,7 +2035,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree | |||
2023 | pasted_size, inode->i_uid, | 2035 | pasted_size, inode->i_uid, |
2024 | key2type(&(key->on_disk_key))); | 2036 | key2type(&(key->on_disk_key))); |
2025 | #endif | 2037 | #endif |
2038 | depth = reiserfs_write_unlock_nested(sb); | ||
2026 | dquot_free_space_nodirty(inode, pasted_size); | 2039 | dquot_free_space_nodirty(inode, pasted_size); |
2040 | reiserfs_write_lock_nested(sb, depth); | ||
2027 | return retval; | 2041 | return retval; |
2028 | } | 2042 | } |
2029 | 2043 | ||
@@ -2046,6 +2060,7 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, | |||
2046 | BUG_ON(!th->t_trans_id); | 2060 | BUG_ON(!th->t_trans_id); |
2047 | 2061 | ||
2048 | if (inode) { /* Do we count quotas for item? */ | 2062 | if (inode) { /* Do we count quotas for item? */ |
2063 | int depth; | ||
2049 | fs_gen = get_generation(inode->i_sb); | 2064 | fs_gen = get_generation(inode->i_sb); |
2050 | quota_bytes = ih_item_len(ih); | 2065 | quota_bytes = ih_item_len(ih); |
2051 | 2066 | ||
@@ -2059,11 +2074,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, | |||
2059 | "reiserquota insert_item(): allocating %u id=%u type=%c", | 2074 | "reiserquota insert_item(): allocating %u id=%u type=%c", |
2060 | quota_bytes, inode->i_uid, head2type(ih)); | 2075 | quota_bytes, inode->i_uid, head2type(ih)); |
2061 | #endif | 2076 | #endif |
2062 | reiserfs_write_unlock(inode->i_sb); | ||
2063 | /* We can't dirty inode here. It would be immediately written but | 2077 | /* We can't dirty inode here. It would be immediately written but |
2064 | * appropriate stat item isn't inserted yet... */ | 2078 | * appropriate stat item isn't inserted yet... */ |
2079 | depth = reiserfs_write_unlock_nested(inode->i_sb); | ||
2065 | retval = dquot_alloc_space_nodirty(inode, quota_bytes); | 2080 | retval = dquot_alloc_space_nodirty(inode, quota_bytes); |
2066 | reiserfs_write_lock(inode->i_sb); | 2081 | reiserfs_write_lock_nested(inode->i_sb, depth); |
2067 | if (retval) { | 2082 | if (retval) { |
2068 | pathrelse(path); | 2083 | pathrelse(path); |
2069 | return retval; | 2084 | return retval; |
@@ -2114,7 +2129,10 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, | |||
2114 | "reiserquota insert_item(): freeing %u id=%u type=%c", | 2129 | "reiserquota insert_item(): freeing %u id=%u type=%c", |
2115 | quota_bytes, inode->i_uid, head2type(ih)); | 2130 | quota_bytes, inode->i_uid, head2type(ih)); |
2116 | #endif | 2131 | #endif |
2117 | if (inode) | 2132 | if (inode) { |
2133 | int depth = reiserfs_write_unlock_nested(inode->i_sb); | ||
2118 | dquot_free_space_nodirty(inode, quota_bytes); | 2134 | dquot_free_space_nodirty(inode, quota_bytes); |
2135 | reiserfs_write_lock_nested(inode->i_sb, depth); | ||
2136 | } | ||
2119 | return retval; | 2137 | return retval; |
2120 | } | 2138 | } |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 60d09327e587..bb20d791bbdc 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -243,6 +243,7 @@ static int finish_unfinished(struct super_block *s) | |||
243 | done = 0; | 243 | done = 0; |
244 | REISERFS_SB(s)->s_is_unlinked_ok = 1; | 244 | REISERFS_SB(s)->s_is_unlinked_ok = 1; |
245 | while (!retval) { | 245 | while (!retval) { |
246 | int depth; | ||
246 | retval = search_item(s, &max_cpu_key, &path); | 247 | retval = search_item(s, &max_cpu_key, &path); |
247 | if (retval != ITEM_NOT_FOUND) { | 248 | if (retval != ITEM_NOT_FOUND) { |
248 | reiserfs_error(s, "vs-2140", | 249 | reiserfs_error(s, "vs-2140", |
@@ -298,9 +299,9 @@ static int finish_unfinished(struct super_block *s) | |||
298 | retval = remove_save_link_only(s, &save_link_key, 0); | 299 | retval = remove_save_link_only(s, &save_link_key, 0); |
299 | continue; | 300 | continue; |
300 | } | 301 | } |
301 | reiserfs_write_unlock(s); | 302 | depth = reiserfs_write_unlock_nested(inode->i_sb); |
302 | dquot_initialize(inode); | 303 | dquot_initialize(inode); |
303 | reiserfs_write_lock(s); | 304 | reiserfs_write_lock_nested(inode->i_sb, depth); |
304 | 305 | ||
305 | if (truncate && S_ISDIR(inode->i_mode)) { | 306 | if (truncate && S_ISDIR(inode->i_mode)) { |
306 | /* We got a truncate request for a dir which is impossible. | 307 | /* We got a truncate request for a dir which is impossible. |
@@ -356,10 +357,12 @@ static int finish_unfinished(struct super_block *s) | |||
356 | 357 | ||
357 | #ifdef CONFIG_QUOTA | 358 | #ifdef CONFIG_QUOTA |
358 | /* Turn quotas off */ | 359 | /* Turn quotas off */ |
360 | reiserfs_write_unlock(s); | ||
359 | for (i = 0; i < MAXQUOTAS; i++) { | 361 | for (i = 0; i < MAXQUOTAS; i++) { |
360 | if (sb_dqopt(s)->files[i] && quota_enabled[i]) | 362 | if (sb_dqopt(s)->files[i] && quota_enabled[i]) |
361 | dquot_quota_off(s, i); | 363 | dquot_quota_off(s, i); |
362 | } | 364 | } |
365 | reiserfs_write_lock(s); | ||
363 | if (ms_active_set) | 366 | if (ms_active_set) |
364 | /* Restore the flag back */ | 367 | /* Restore the flag back */ |
365 | s->s_flags &= ~MS_ACTIVE; | 368 | s->s_flags &= ~MS_ACTIVE; |
@@ -2098,6 +2101,7 @@ static int reiserfs_write_dquot(struct dquot *dquot) | |||
2098 | { | 2101 | { |
2099 | struct reiserfs_transaction_handle th; | 2102 | struct reiserfs_transaction_handle th; |
2100 | int ret, err; | 2103 | int ret, err; |
2104 | int depth; | ||
2101 | 2105 | ||
2102 | reiserfs_write_lock(dquot->dq_sb); | 2106 | reiserfs_write_lock(dquot->dq_sb); |
2103 | ret = | 2107 | ret = |
@@ -2105,9 +2109,9 @@ static int reiserfs_write_dquot(struct dquot *dquot) | |||
2105 | REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); | 2109 | REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); |
2106 | if (ret) | 2110 | if (ret) |
2107 | goto out; | 2111 | goto out; |
2108 | reiserfs_write_unlock(dquot->dq_sb); | 2112 | depth = reiserfs_write_unlock_nested(dquot->dq_sb); |
2109 | ret = dquot_commit(dquot); | 2113 | ret = dquot_commit(dquot); |
2110 | reiserfs_write_lock(dquot->dq_sb); | 2114 | reiserfs_write_lock_nested(dquot->dq_sb, depth); |
2111 | err = | 2115 | err = |
2112 | journal_end(&th, dquot->dq_sb, | 2116 | journal_end(&th, dquot->dq_sb, |
2113 | REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); | 2117 | REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); |
@@ -2122,6 +2126,7 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) | |||
2122 | { | 2126 | { |
2123 | struct reiserfs_transaction_handle th; | 2127 | struct reiserfs_transaction_handle th; |
2124 | int ret, err; | 2128 | int ret, err; |
2129 | int depth; | ||
2125 | 2130 | ||
2126 | reiserfs_write_lock(dquot->dq_sb); | 2131 | reiserfs_write_lock(dquot->dq_sb); |
2127 | ret = | 2132 | ret = |
@@ -2129,9 +2134,9 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) | |||
2129 | REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); | 2134 | REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); |
2130 | if (ret) | 2135 | if (ret) |
2131 | goto out; | 2136 | goto out; |
2132 | reiserfs_write_unlock(dquot->dq_sb); | 2137 | depth = reiserfs_write_unlock_nested(dquot->dq_sb); |
2133 | ret = dquot_acquire(dquot); | 2138 | ret = dquot_acquire(dquot); |
2134 | reiserfs_write_lock(dquot->dq_sb); | 2139 | reiserfs_write_lock_nested(dquot->dq_sb, depth); |
2135 | err = | 2140 | err = |
2136 | journal_end(&th, dquot->dq_sb, | 2141 | journal_end(&th, dquot->dq_sb, |
2137 | REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); | 2142 | REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); |
@@ -2184,15 +2189,16 @@ static int reiserfs_write_info(struct super_block *sb, int type) | |||
2184 | { | 2189 | { |
2185 | struct reiserfs_transaction_handle th; | 2190 | struct reiserfs_transaction_handle th; |
2186 | int ret, err; | 2191 | int ret, err; |
2192 | int depth; | ||
2187 | 2193 | ||
2188 | /* Data block + inode block */ | 2194 | /* Data block + inode block */ |
2189 | reiserfs_write_lock(sb); | 2195 | reiserfs_write_lock(sb); |
2190 | ret = journal_begin(&th, sb, 2); | 2196 | ret = journal_begin(&th, sb, 2); |
2191 | if (ret) | 2197 | if (ret) |
2192 | goto out; | 2198 | goto out; |
2193 | reiserfs_write_unlock(sb); | 2199 | depth = reiserfs_write_unlock_nested(sb); |
2194 | ret = dquot_commit_info(sb, type); | 2200 | ret = dquot_commit_info(sb, type); |
2195 | reiserfs_write_lock(sb); | 2201 | reiserfs_write_lock_nested(sb, depth); |
2196 | err = journal_end(&th, sb, 2); | 2202 | err = journal_end(&th, sb, 2); |
2197 | if (!ret && err) | 2203 | if (!ret && err) |
2198 | ret = err; | 2204 | ret = err; |