diff options
Diffstat (limited to 'fs/jbd2')
-rw-r--r-- | fs/jbd2/commit.c | 19 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 55 | ||||
-rw-r--r-- | fs/jbd2/revoke.c | 165 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 41 |
4 files changed, 137 insertions, 143 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index a8173081f831..e0139786f717 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -520,22 +520,6 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
520 | jbd_debug (3, "JBD: commit phase 2\n"); | 520 | jbd_debug (3, "JBD: commit phase 2\n"); |
521 | 521 | ||
522 | /* | 522 | /* |
523 | * First, drop modified flag: all accesses to the buffers | ||
524 | * will be tracked for a new trasaction only -bzzz | ||
525 | */ | ||
526 | spin_lock(&journal->j_list_lock); | ||
527 | if (commit_transaction->t_buffers) { | ||
528 | new_jh = jh = commit_transaction->t_buffers->b_tnext; | ||
529 | do { | ||
530 | J_ASSERT_JH(new_jh, new_jh->b_modified == 1 || | ||
531 | new_jh->b_modified == 0); | ||
532 | new_jh->b_modified = 0; | ||
533 | new_jh = new_jh->b_tnext; | ||
534 | } while (new_jh != jh); | ||
535 | } | ||
536 | spin_unlock(&journal->j_list_lock); | ||
537 | |||
538 | /* | ||
539 | * Now start flushing things to disk, in the order they appear | 523 | * Now start flushing things to disk, in the order they appear |
540 | * on the transaction lists. Data blocks go first. | 524 | * on the transaction lists. Data blocks go first. |
541 | */ | 525 | */ |
@@ -584,6 +568,9 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
584 | stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits; | 568 | stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits; |
585 | stats.u.run.rs_blocks_logged = 0; | 569 | stats.u.run.rs_blocks_logged = 0; |
586 | 570 | ||
571 | J_ASSERT(commit_transaction->t_nr_buffers <= | ||
572 | commit_transaction->t_outstanding_credits); | ||
573 | |||
587 | descriptor = NULL; | 574 | descriptor = NULL; |
588 | bufs = 0; | 575 | bufs = 0; |
589 | while (commit_transaction->t_buffers) { | 576 | while (commit_transaction->t_buffers) { |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 954cff001df6..53632e3e8457 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -534,7 +534,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid) | |||
534 | if (!tid_geq(journal->j_commit_request, tid)) { | 534 | if (!tid_geq(journal->j_commit_request, tid)) { |
535 | printk(KERN_EMERG | 535 | printk(KERN_EMERG |
536 | "%s: error: j_commit_request=%d, tid=%d\n", | 536 | "%s: error: j_commit_request=%d, tid=%d\n", |
537 | __FUNCTION__, journal->j_commit_request, tid); | 537 | __func__, journal->j_commit_request, tid); |
538 | } | 538 | } |
539 | spin_unlock(&journal->j_state_lock); | 539 | spin_unlock(&journal->j_state_lock); |
540 | #endif | 540 | #endif |
@@ -599,7 +599,7 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, | |||
599 | 599 | ||
600 | printk(KERN_ALERT "%s: journal block not found " | 600 | printk(KERN_ALERT "%s: journal block not found " |
601 | "at offset %lu on %s\n", | 601 | "at offset %lu on %s\n", |
602 | __FUNCTION__, | 602 | __func__, |
603 | blocknr, | 603 | blocknr, |
604 | bdevname(journal->j_dev, b)); | 604 | bdevname(journal->j_dev, b)); |
605 | err = -EIO; | 605 | err = -EIO; |
@@ -904,19 +904,10 @@ static void jbd2_stats_proc_init(journal_t *journal) | |||
904 | snprintf(name, sizeof(name) - 1, "%s", bdevname(journal->j_dev, name)); | 904 | snprintf(name, sizeof(name) - 1, "%s", bdevname(journal->j_dev, name)); |
905 | journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats); | 905 | journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats); |
906 | if (journal->j_proc_entry) { | 906 | if (journal->j_proc_entry) { |
907 | struct proc_dir_entry *p; | 907 | proc_create_data("history", S_IRUGO, journal->j_proc_entry, |
908 | p = create_proc_entry("history", S_IRUGO, | 908 | &jbd2_seq_history_fops, journal); |
909 | journal->j_proc_entry); | 909 | proc_create_data("info", S_IRUGO, journal->j_proc_entry, |
910 | if (p) { | 910 | &jbd2_seq_info_fops, journal); |
911 | p->proc_fops = &jbd2_seq_history_fops; | ||
912 | p->data = journal; | ||
913 | p = create_proc_entry("info", S_IRUGO, | ||
914 | journal->j_proc_entry); | ||
915 | if (p) { | ||
916 | p->proc_fops = &jbd2_seq_info_fops; | ||
917 | p->data = journal; | ||
918 | } | ||
919 | } | ||
920 | } | 911 | } |
921 | } | 912 | } |
922 | 913 | ||
@@ -1006,13 +997,14 @@ fail: | |||
1006 | */ | 997 | */ |
1007 | 998 | ||
1008 | /** | 999 | /** |
1009 | * journal_t * jbd2_journal_init_dev() - creates an initialises a journal structure | 1000 | * journal_t * jbd2_journal_init_dev() - creates and initialises a journal structure |
1010 | * @bdev: Block device on which to create the journal | 1001 | * @bdev: Block device on which to create the journal |
1011 | * @fs_dev: Device which hold journalled filesystem for this journal. | 1002 | * @fs_dev: Device which hold journalled filesystem for this journal. |
1012 | * @start: Block nr Start of journal. | 1003 | * @start: Block nr Start of journal. |
1013 | * @len: Length of the journal in blocks. | 1004 | * @len: Length of the journal in blocks. |
1014 | * @blocksize: blocksize of journalling device | 1005 | * @blocksize: blocksize of journalling device |
1015 | * @returns: a newly created journal_t * | 1006 | * |
1007 | * Returns: a newly created journal_t * | ||
1016 | * | 1008 | * |
1017 | * jbd2_journal_init_dev creates a journal which maps a fixed contiguous | 1009 | * jbd2_journal_init_dev creates a journal which maps a fixed contiguous |
1018 | * range of blocks on an arbitrary block device. | 1010 | * range of blocks on an arbitrary block device. |
@@ -1036,7 +1028,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
1036 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); | 1028 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); |
1037 | if (!journal->j_wbuf) { | 1029 | if (!journal->j_wbuf) { |
1038 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 1030 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
1039 | __FUNCTION__); | 1031 | __func__); |
1040 | kfree(journal); | 1032 | kfree(journal); |
1041 | journal = NULL; | 1033 | journal = NULL; |
1042 | goto out; | 1034 | goto out; |
@@ -1092,7 +1084,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
1092 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); | 1084 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); |
1093 | if (!journal->j_wbuf) { | 1085 | if (!journal->j_wbuf) { |
1094 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 1086 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
1095 | __FUNCTION__); | 1087 | __func__); |
1096 | kfree(journal); | 1088 | kfree(journal); |
1097 | return NULL; | 1089 | return NULL; |
1098 | } | 1090 | } |
@@ -1101,7 +1093,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
1101 | /* If that failed, give up */ | 1093 | /* If that failed, give up */ |
1102 | if (err) { | 1094 | if (err) { |
1103 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", | 1095 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", |
1104 | __FUNCTION__); | 1096 | __func__); |
1105 | kfree(journal); | 1097 | kfree(journal); |
1106 | return NULL; | 1098 | return NULL; |
1107 | } | 1099 | } |
@@ -1187,7 +1179,7 @@ int jbd2_journal_create(journal_t *journal) | |||
1187 | */ | 1179 | */ |
1188 | printk(KERN_EMERG | 1180 | printk(KERN_EMERG |
1189 | "%s: creation of journal on external device!\n", | 1181 | "%s: creation of journal on external device!\n", |
1190 | __FUNCTION__); | 1182 | __func__); |
1191 | BUG(); | 1183 | BUG(); |
1192 | } | 1184 | } |
1193 | 1185 | ||
@@ -1985,9 +1977,10 @@ static int journal_init_jbd2_journal_head_cache(void) | |||
1985 | 1977 | ||
1986 | static void jbd2_journal_destroy_jbd2_journal_head_cache(void) | 1978 | static void jbd2_journal_destroy_jbd2_journal_head_cache(void) |
1987 | { | 1979 | { |
1988 | J_ASSERT(jbd2_journal_head_cache != NULL); | 1980 | if (jbd2_journal_head_cache) { |
1989 | kmem_cache_destroy(jbd2_journal_head_cache); | 1981 | kmem_cache_destroy(jbd2_journal_head_cache); |
1990 | jbd2_journal_head_cache = NULL; | 1982 | jbd2_journal_head_cache = NULL; |
1983 | } | ||
1991 | } | 1984 | } |
1992 | 1985 | ||
1993 | /* | 1986 | /* |
@@ -2006,7 +1999,7 @@ static struct journal_head *journal_alloc_journal_head(void) | |||
2006 | jbd_debug(1, "out of memory for journal_head\n"); | 1999 | jbd_debug(1, "out of memory for journal_head\n"); |
2007 | if (time_after(jiffies, last_warning + 5*HZ)) { | 2000 | if (time_after(jiffies, last_warning + 5*HZ)) { |
2008 | printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", | 2001 | printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", |
2009 | __FUNCTION__); | 2002 | __func__); |
2010 | last_warning = jiffies; | 2003 | last_warning = jiffies; |
2011 | } | 2004 | } |
2012 | while (!ret) { | 2005 | while (!ret) { |
@@ -2143,13 +2136,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh) | |||
2143 | if (jh->b_frozen_data) { | 2136 | if (jh->b_frozen_data) { |
2144 | printk(KERN_WARNING "%s: freeing " | 2137 | printk(KERN_WARNING "%s: freeing " |
2145 | "b_frozen_data\n", | 2138 | "b_frozen_data\n", |
2146 | __FUNCTION__); | 2139 | __func__); |
2147 | jbd2_free(jh->b_frozen_data, bh->b_size); | 2140 | jbd2_free(jh->b_frozen_data, bh->b_size); |
2148 | } | 2141 | } |
2149 | if (jh->b_committed_data) { | 2142 | if (jh->b_committed_data) { |
2150 | printk(KERN_WARNING "%s: freeing " | 2143 | printk(KERN_WARNING "%s: freeing " |
2151 | "b_committed_data\n", | 2144 | "b_committed_data\n", |
2152 | __FUNCTION__); | 2145 | __func__); |
2153 | jbd2_free(jh->b_committed_data, bh->b_size); | 2146 | jbd2_free(jh->b_committed_data, bh->b_size); |
2154 | } | 2147 | } |
2155 | bh->b_private = NULL; | 2148 | bh->b_private = NULL; |
@@ -2314,10 +2307,12 @@ static int __init journal_init(void) | |||
2314 | BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024); | 2307 | BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024); |
2315 | 2308 | ||
2316 | ret = journal_init_caches(); | 2309 | ret = journal_init_caches(); |
2317 | if (ret != 0) | 2310 | if (ret == 0) { |
2311 | jbd2_create_debugfs_entry(); | ||
2312 | jbd2_create_jbd_stats_proc_entry(); | ||
2313 | } else { | ||
2318 | jbd2_journal_destroy_caches(); | 2314 | jbd2_journal_destroy_caches(); |
2319 | jbd2_create_debugfs_entry(); | 2315 | } |
2320 | jbd2_create_jbd_stats_proc_entry(); | ||
2321 | return ret; | 2316 | return ret; |
2322 | } | 2317 | } |
2323 | 2318 | ||
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 2e1453a5e998..257ff2625765 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
@@ -139,7 +139,7 @@ repeat: | |||
139 | oom: | 139 | oom: |
140 | if (!journal_oom_retry) | 140 | if (!journal_oom_retry) |
141 | return -ENOMEM; | 141 | return -ENOMEM; |
142 | jbd_debug(1, "ENOMEM in %s, retrying\n", __FUNCTION__); | 142 | jbd_debug(1, "ENOMEM in %s, retrying\n", __func__); |
143 | yield(); | 143 | yield(); |
144 | goto repeat; | 144 | goto repeat; |
145 | } | 145 | } |
@@ -167,138 +167,121 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal, | |||
167 | return NULL; | 167 | return NULL; |
168 | } | 168 | } |
169 | 169 | ||
170 | void jbd2_journal_destroy_revoke_caches(void) | ||
171 | { | ||
172 | if (jbd2_revoke_record_cache) { | ||
173 | kmem_cache_destroy(jbd2_revoke_record_cache); | ||
174 | jbd2_revoke_record_cache = NULL; | ||
175 | } | ||
176 | if (jbd2_revoke_table_cache) { | ||
177 | kmem_cache_destroy(jbd2_revoke_table_cache); | ||
178 | jbd2_revoke_table_cache = NULL; | ||
179 | } | ||
180 | } | ||
181 | |||
170 | int __init jbd2_journal_init_revoke_caches(void) | 182 | int __init jbd2_journal_init_revoke_caches(void) |
171 | { | 183 | { |
184 | J_ASSERT(!jbd2_revoke_record_cache); | ||
185 | J_ASSERT(!jbd2_revoke_table_cache); | ||
186 | |||
172 | jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record", | 187 | jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record", |
173 | sizeof(struct jbd2_revoke_record_s), | 188 | sizeof(struct jbd2_revoke_record_s), |
174 | 0, | 189 | 0, |
175 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, | 190 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, |
176 | NULL); | 191 | NULL); |
177 | if (!jbd2_revoke_record_cache) | 192 | if (!jbd2_revoke_record_cache) |
178 | return -ENOMEM; | 193 | goto record_cache_failure; |
179 | 194 | ||
180 | jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", | 195 | jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", |
181 | sizeof(struct jbd2_revoke_table_s), | 196 | sizeof(struct jbd2_revoke_table_s), |
182 | 0, SLAB_TEMPORARY, NULL); | 197 | 0, SLAB_TEMPORARY, NULL); |
183 | if (!jbd2_revoke_table_cache) { | 198 | if (!jbd2_revoke_table_cache) |
184 | kmem_cache_destroy(jbd2_revoke_record_cache); | 199 | goto table_cache_failure; |
185 | jbd2_revoke_record_cache = NULL; | ||
186 | return -ENOMEM; | ||
187 | } | ||
188 | return 0; | 200 | return 0; |
201 | table_cache_failure: | ||
202 | jbd2_journal_destroy_revoke_caches(); | ||
203 | record_cache_failure: | ||
204 | return -ENOMEM; | ||
189 | } | 205 | } |
190 | 206 | ||
191 | void jbd2_journal_destroy_revoke_caches(void) | 207 | static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) |
192 | { | 208 | { |
193 | kmem_cache_destroy(jbd2_revoke_record_cache); | 209 | int shift = 0; |
194 | jbd2_revoke_record_cache = NULL; | 210 | int tmp = hash_size; |
195 | kmem_cache_destroy(jbd2_revoke_table_cache); | 211 | struct jbd2_revoke_table_s *table; |
196 | jbd2_revoke_table_cache = NULL; | ||
197 | } | ||
198 | |||
199 | /* Initialise the revoke table for a given journal to a given size. */ | ||
200 | |||
201 | int jbd2_journal_init_revoke(journal_t *journal, int hash_size) | ||
202 | { | ||
203 | int shift, tmp; | ||
204 | 212 | ||
205 | J_ASSERT (journal->j_revoke_table[0] == NULL); | 213 | table = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); |
214 | if (!table) | ||
215 | goto out; | ||
206 | 216 | ||
207 | shift = 0; | ||
208 | tmp = hash_size; | ||
209 | while((tmp >>= 1UL) != 0UL) | 217 | while((tmp >>= 1UL) != 0UL) |
210 | shift++; | 218 | shift++; |
211 | 219 | ||
212 | journal->j_revoke_table[0] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); | 220 | table->hash_size = hash_size; |
213 | if (!journal->j_revoke_table[0]) | 221 | table->hash_shift = shift; |
214 | return -ENOMEM; | 222 | table->hash_table = |
215 | journal->j_revoke = journal->j_revoke_table[0]; | ||
216 | |||
217 | /* Check that the hash_size is a power of two */ | ||
218 | J_ASSERT(is_power_of_2(hash_size)); | ||
219 | |||
220 | journal->j_revoke->hash_size = hash_size; | ||
221 | |||
222 | journal->j_revoke->hash_shift = shift; | ||
223 | |||
224 | journal->j_revoke->hash_table = | ||
225 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); | 223 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); |
226 | if (!journal->j_revoke->hash_table) { | 224 | if (!table->hash_table) { |
227 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | 225 | kmem_cache_free(jbd2_revoke_table_cache, table); |
228 | journal->j_revoke = NULL; | 226 | table = NULL; |
229 | return -ENOMEM; | 227 | goto out; |
230 | } | 228 | } |
231 | 229 | ||
232 | for (tmp = 0; tmp < hash_size; tmp++) | 230 | for (tmp = 0; tmp < hash_size; tmp++) |
233 | INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); | 231 | INIT_LIST_HEAD(&table->hash_table[tmp]); |
234 | 232 | ||
235 | journal->j_revoke_table[1] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); | 233 | out: |
236 | if (!journal->j_revoke_table[1]) { | 234 | return table; |
237 | kfree(journal->j_revoke_table[0]->hash_table); | 235 | } |
238 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | 236 | |
239 | return -ENOMEM; | 237 | static void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table) |
238 | { | ||
239 | int i; | ||
240 | struct list_head *hash_list; | ||
241 | |||
242 | for (i = 0; i < table->hash_size; i++) { | ||
243 | hash_list = &table->hash_table[i]; | ||
244 | J_ASSERT(list_empty(hash_list)); | ||
240 | } | 245 | } |
241 | 246 | ||
242 | journal->j_revoke = journal->j_revoke_table[1]; | 247 | kfree(table->hash_table); |
248 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
249 | } | ||
243 | 250 | ||
244 | /* Check that the hash_size is a power of two */ | 251 | /* Initialise the revoke table for a given journal to a given size. */ |
252 | int jbd2_journal_init_revoke(journal_t *journal, int hash_size) | ||
253 | { | ||
254 | J_ASSERT(journal->j_revoke_table[0] == NULL); | ||
245 | J_ASSERT(is_power_of_2(hash_size)); | 255 | J_ASSERT(is_power_of_2(hash_size)); |
246 | 256 | ||
247 | journal->j_revoke->hash_size = hash_size; | 257 | journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size); |
248 | 258 | if (!journal->j_revoke_table[0]) | |
249 | journal->j_revoke->hash_shift = shift; | 259 | goto fail0; |
250 | 260 | ||
251 | journal->j_revoke->hash_table = | 261 | journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size); |
252 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); | 262 | if (!journal->j_revoke_table[1]) |
253 | if (!journal->j_revoke->hash_table) { | 263 | goto fail1; |
254 | kfree(journal->j_revoke_table[0]->hash_table); | ||
255 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | ||
256 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[1]); | ||
257 | journal->j_revoke = NULL; | ||
258 | return -ENOMEM; | ||
259 | } | ||
260 | 264 | ||
261 | for (tmp = 0; tmp < hash_size; tmp++) | 265 | journal->j_revoke = journal->j_revoke_table[1]; |
262 | INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); | ||
263 | 266 | ||
264 | spin_lock_init(&journal->j_revoke_lock); | 267 | spin_lock_init(&journal->j_revoke_lock); |
265 | 268 | ||
266 | return 0; | 269 | return 0; |
267 | } | ||
268 | 270 | ||
269 | /* Destoy a journal's revoke table. The table must already be empty! */ | 271 | fail1: |
272 | jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); | ||
273 | fail0: | ||
274 | return -ENOMEM; | ||
275 | } | ||
270 | 276 | ||
277 | /* Destroy a journal's revoke table. The table must already be empty! */ | ||
271 | void jbd2_journal_destroy_revoke(journal_t *journal) | 278 | void jbd2_journal_destroy_revoke(journal_t *journal) |
272 | { | 279 | { |
273 | struct jbd2_revoke_table_s *table; | ||
274 | struct list_head *hash_list; | ||
275 | int i; | ||
276 | |||
277 | table = journal->j_revoke_table[0]; | ||
278 | if (!table) | ||
279 | return; | ||
280 | |||
281 | for (i=0; i<table->hash_size; i++) { | ||
282 | hash_list = &table->hash_table[i]; | ||
283 | J_ASSERT (list_empty(hash_list)); | ||
284 | } | ||
285 | |||
286 | kfree(table->hash_table); | ||
287 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
288 | journal->j_revoke = NULL; | ||
289 | |||
290 | table = journal->j_revoke_table[1]; | ||
291 | if (!table) | ||
292 | return; | ||
293 | |||
294 | for (i=0; i<table->hash_size; i++) { | ||
295 | hash_list = &table->hash_table[i]; | ||
296 | J_ASSERT (list_empty(hash_list)); | ||
297 | } | ||
298 | |||
299 | kfree(table->hash_table); | ||
300 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
301 | journal->j_revoke = NULL; | 280 | journal->j_revoke = NULL; |
281 | if (journal->j_revoke_table[0]) | ||
282 | jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); | ||
283 | if (journal->j_revoke_table[1]) | ||
284 | jbd2_journal_destroy_revoke_table(journal->j_revoke_table[1]); | ||
302 | } | 285 | } |
303 | 286 | ||
304 | 287 | ||
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index b9b0b6f899b9..d6e006e67804 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -618,6 +618,12 @@ repeat: | |||
618 | goto done; | 618 | goto done; |
619 | 619 | ||
620 | /* | 620 | /* |
621 | * this is the first time this transaction is touching this buffer, | ||
622 | * reset the modified flag | ||
623 | */ | ||
624 | jh->b_modified = 0; | ||
625 | |||
626 | /* | ||
621 | * If there is already a copy-out version of this buffer, then we don't | 627 | * If there is already a copy-out version of this buffer, then we don't |
622 | * need to make another one | 628 | * need to make another one |
623 | */ | 629 | */ |
@@ -690,7 +696,7 @@ repeat: | |||
690 | if (!frozen_buffer) { | 696 | if (!frozen_buffer) { |
691 | printk(KERN_EMERG | 697 | printk(KERN_EMERG |
692 | "%s: OOM for frozen_buffer\n", | 698 | "%s: OOM for frozen_buffer\n", |
693 | __FUNCTION__); | 699 | __func__); |
694 | JBUFFER_TRACE(jh, "oom!"); | 700 | JBUFFER_TRACE(jh, "oom!"); |
695 | error = -ENOMEM; | 701 | error = -ENOMEM; |
696 | jbd_lock_bh_state(bh); | 702 | jbd_lock_bh_state(bh); |
@@ -829,9 +835,16 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh) | |||
829 | 835 | ||
830 | if (jh->b_transaction == NULL) { | 836 | if (jh->b_transaction == NULL) { |
831 | jh->b_transaction = transaction; | 837 | jh->b_transaction = transaction; |
838 | |||
839 | /* first access by this transaction */ | ||
840 | jh->b_modified = 0; | ||
841 | |||
832 | JBUFFER_TRACE(jh, "file as BJ_Reserved"); | 842 | JBUFFER_TRACE(jh, "file as BJ_Reserved"); |
833 | __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved); | 843 | __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved); |
834 | } else if (jh->b_transaction == journal->j_committing_transaction) { | 844 | } else if (jh->b_transaction == journal->j_committing_transaction) { |
845 | /* first access by this transaction */ | ||
846 | jh->b_modified = 0; | ||
847 | |||
835 | JBUFFER_TRACE(jh, "set next transaction"); | 848 | JBUFFER_TRACE(jh, "set next transaction"); |
836 | jh->b_next_transaction = transaction; | 849 | jh->b_next_transaction = transaction; |
837 | } | 850 | } |
@@ -901,7 +914,7 @@ repeat: | |||
901 | committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS); | 914 | committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS); |
902 | if (!committed_data) { | 915 | if (!committed_data) { |
903 | printk(KERN_EMERG "%s: No memory for committed data\n", | 916 | printk(KERN_EMERG "%s: No memory for committed data\n", |
904 | __FUNCTION__); | 917 | __func__); |
905 | err = -ENOMEM; | 918 | err = -ENOMEM; |
906 | goto out; | 919 | goto out; |
907 | } | 920 | } |
@@ -1230,6 +1243,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) | |||
1230 | struct journal_head *jh; | 1243 | struct journal_head *jh; |
1231 | int drop_reserve = 0; | 1244 | int drop_reserve = 0; |
1232 | int err = 0; | 1245 | int err = 0; |
1246 | int was_modified = 0; | ||
1233 | 1247 | ||
1234 | BUFFER_TRACE(bh, "entry"); | 1248 | BUFFER_TRACE(bh, "entry"); |
1235 | 1249 | ||
@@ -1248,6 +1262,9 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) | |||
1248 | goto not_jbd; | 1262 | goto not_jbd; |
1249 | } | 1263 | } |
1250 | 1264 | ||
1265 | /* keep track of wether or not this transaction modified us */ | ||
1266 | was_modified = jh->b_modified; | ||
1267 | |||
1251 | /* | 1268 | /* |
1252 | * The buffer's going from the transaction, we must drop | 1269 | * The buffer's going from the transaction, we must drop |
1253 | * all references -bzzz | 1270 | * all references -bzzz |
@@ -1265,7 +1282,12 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) | |||
1265 | 1282 | ||
1266 | JBUFFER_TRACE(jh, "belongs to current transaction: unfile"); | 1283 | JBUFFER_TRACE(jh, "belongs to current transaction: unfile"); |
1267 | 1284 | ||
1268 | drop_reserve = 1; | 1285 | /* |
1286 | * we only want to drop a reference if this transaction | ||
1287 | * modified the buffer | ||
1288 | */ | ||
1289 | if (was_modified) | ||
1290 | drop_reserve = 1; | ||
1269 | 1291 | ||
1270 | /* | 1292 | /* |
1271 | * We are no longer going to journal this buffer. | 1293 | * We are no longer going to journal this buffer. |
@@ -1305,7 +1327,13 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) | |||
1305 | if (jh->b_next_transaction) { | 1327 | if (jh->b_next_transaction) { |
1306 | J_ASSERT(jh->b_next_transaction == transaction); | 1328 | J_ASSERT(jh->b_next_transaction == transaction); |
1307 | jh->b_next_transaction = NULL; | 1329 | jh->b_next_transaction = NULL; |
1308 | drop_reserve = 1; | 1330 | |
1331 | /* | ||
1332 | * only drop a reference if this transaction modified | ||
1333 | * the buffer | ||
1334 | */ | ||
1335 | if (was_modified) | ||
1336 | drop_reserve = 1; | ||
1309 | } | 1337 | } |
1310 | } | 1338 | } |
1311 | 1339 | ||
@@ -1434,7 +1462,8 @@ int jbd2_journal_stop(handle_t *handle) | |||
1434 | return err; | 1462 | return err; |
1435 | } | 1463 | } |
1436 | 1464 | ||
1437 | /**int jbd2_journal_force_commit() - force any uncommitted transactions | 1465 | /** |
1466 | * int jbd2_journal_force_commit() - force any uncommitted transactions | ||
1438 | * @journal: journal to force | 1467 | * @journal: journal to force |
1439 | * | 1468 | * |
1440 | * For synchronous operations: force any uncommitted transactions | 1469 | * For synchronous operations: force any uncommitted transactions |
@@ -2077,7 +2106,7 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh) | |||
2077 | jh->b_transaction = jh->b_next_transaction; | 2106 | jh->b_transaction = jh->b_next_transaction; |
2078 | jh->b_next_transaction = NULL; | 2107 | jh->b_next_transaction = NULL; |
2079 | __jbd2_journal_file_buffer(jh, jh->b_transaction, | 2108 | __jbd2_journal_file_buffer(jh, jh->b_transaction, |
2080 | was_dirty ? BJ_Metadata : BJ_Reserved); | 2109 | jh->b_modified ? BJ_Metadata : BJ_Reserved); |
2081 | J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); | 2110 | J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); |
2082 | 2111 | ||
2083 | if (was_dirty) | 2112 | if (was_dirty) |