diff options
Diffstat (limited to 'fs/jbd/transaction.c')
-rw-r--r-- | fs/jbd/transaction.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 2c9e8f5d13aa..67ff2024c23c 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -609,6 +609,12 @@ repeat: | |||
609 | goto done; | 609 | goto done; |
610 | 610 | ||
611 | /* | 611 | /* |
612 | * this is the first time this transaction is touching this buffer, | ||
613 | * reset the modified flag | ||
614 | */ | ||
615 | jh->b_modified = 0; | ||
616 | |||
617 | /* | ||
612 | * If there is already a copy-out version of this buffer, then we don't | 618 | * If there is already a copy-out version of this buffer, then we don't |
613 | * need to make another one | 619 | * need to make another one |
614 | */ | 620 | */ |
@@ -681,7 +687,7 @@ repeat: | |||
681 | if (!frozen_buffer) { | 687 | if (!frozen_buffer) { |
682 | printk(KERN_EMERG | 688 | printk(KERN_EMERG |
683 | "%s: OOM for frozen_buffer\n", | 689 | "%s: OOM for frozen_buffer\n", |
684 | __FUNCTION__); | 690 | __func__); |
685 | JBUFFER_TRACE(jh, "oom!"); | 691 | JBUFFER_TRACE(jh, "oom!"); |
686 | error = -ENOMEM; | 692 | error = -ENOMEM; |
687 | jbd_lock_bh_state(bh); | 693 | jbd_lock_bh_state(bh); |
@@ -820,9 +826,16 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh) | |||
820 | 826 | ||
821 | if (jh->b_transaction == NULL) { | 827 | if (jh->b_transaction == NULL) { |
822 | jh->b_transaction = transaction; | 828 | jh->b_transaction = transaction; |
829 | |||
830 | /* first access by this transaction */ | ||
831 | jh->b_modified = 0; | ||
832 | |||
823 | JBUFFER_TRACE(jh, "file as BJ_Reserved"); | 833 | JBUFFER_TRACE(jh, "file as BJ_Reserved"); |
824 | __journal_file_buffer(jh, transaction, BJ_Reserved); | 834 | __journal_file_buffer(jh, transaction, BJ_Reserved); |
825 | } else if (jh->b_transaction == journal->j_committing_transaction) { | 835 | } else if (jh->b_transaction == journal->j_committing_transaction) { |
836 | /* first access by this transaction */ | ||
837 | jh->b_modified = 0; | ||
838 | |||
826 | JBUFFER_TRACE(jh, "set next transaction"); | 839 | JBUFFER_TRACE(jh, "set next transaction"); |
827 | jh->b_next_transaction = transaction; | 840 | jh->b_next_transaction = transaction; |
828 | } | 841 | } |
@@ -891,7 +904,7 @@ repeat: | |||
891 | committed_data = jbd_alloc(jh2bh(jh)->b_size, GFP_NOFS); | 904 | committed_data = jbd_alloc(jh2bh(jh)->b_size, GFP_NOFS); |
892 | if (!committed_data) { | 905 | if (!committed_data) { |
893 | printk(KERN_EMERG "%s: No memory for committed data\n", | 906 | printk(KERN_EMERG "%s: No memory for committed data\n", |
894 | __FUNCTION__); | 907 | __func__); |
895 | err = -ENOMEM; | 908 | err = -ENOMEM; |
896 | goto out; | 909 | goto out; |
897 | } | 910 | } |
@@ -1222,6 +1235,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) | |||
1222 | struct journal_head *jh; | 1235 | struct journal_head *jh; |
1223 | int drop_reserve = 0; | 1236 | int drop_reserve = 0; |
1224 | int err = 0; | 1237 | int err = 0; |
1238 | int was_modified = 0; | ||
1225 | 1239 | ||
1226 | BUFFER_TRACE(bh, "entry"); | 1240 | BUFFER_TRACE(bh, "entry"); |
1227 | 1241 | ||
@@ -1240,6 +1254,9 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) | |||
1240 | goto not_jbd; | 1254 | goto not_jbd; |
1241 | } | 1255 | } |
1242 | 1256 | ||
1257 | /* keep track of wether or not this transaction modified us */ | ||
1258 | was_modified = jh->b_modified; | ||
1259 | |||
1243 | /* | 1260 | /* |
1244 | * The buffer's going from the transaction, we must drop | 1261 | * The buffer's going from the transaction, we must drop |
1245 | * all references -bzzz | 1262 | * all references -bzzz |
@@ -1257,7 +1274,12 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) | |||
1257 | 1274 | ||
1258 | JBUFFER_TRACE(jh, "belongs to current transaction: unfile"); | 1275 | JBUFFER_TRACE(jh, "belongs to current transaction: unfile"); |
1259 | 1276 | ||
1260 | drop_reserve = 1; | 1277 | /* |
1278 | * we only want to drop a reference if this transaction | ||
1279 | * modified the buffer | ||
1280 | */ | ||
1281 | if (was_modified) | ||
1282 | drop_reserve = 1; | ||
1261 | 1283 | ||
1262 | /* | 1284 | /* |
1263 | * We are no longer going to journal this buffer. | 1285 | * We are no longer going to journal this buffer. |
@@ -1297,7 +1319,13 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) | |||
1297 | if (jh->b_next_transaction) { | 1319 | if (jh->b_next_transaction) { |
1298 | J_ASSERT(jh->b_next_transaction == transaction); | 1320 | J_ASSERT(jh->b_next_transaction == transaction); |
1299 | jh->b_next_transaction = NULL; | 1321 | jh->b_next_transaction = NULL; |
1300 | drop_reserve = 1; | 1322 | |
1323 | /* | ||
1324 | * only drop a reference if this transaction modified | ||
1325 | * the buffer | ||
1326 | */ | ||
1327 | if (was_modified) | ||
1328 | drop_reserve = 1; | ||
1301 | } | 1329 | } |
1302 | } | 1330 | } |
1303 | 1331 | ||
@@ -2069,7 +2097,7 @@ void __journal_refile_buffer(struct journal_head *jh) | |||
2069 | jh->b_transaction = jh->b_next_transaction; | 2097 | jh->b_transaction = jh->b_next_transaction; |
2070 | jh->b_next_transaction = NULL; | 2098 | jh->b_next_transaction = NULL; |
2071 | __journal_file_buffer(jh, jh->b_transaction, | 2099 | __journal_file_buffer(jh, jh->b_transaction, |
2072 | was_dirty ? BJ_Metadata : BJ_Reserved); | 2100 | jh->b_modified ? BJ_Metadata : BJ_Reserved); |
2073 | J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); | 2101 | J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); |
2074 | 2102 | ||
2075 | if (was_dirty) | 2103 | if (was_dirty) |