diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 23:34:49 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 23:34:49 -0400 |
| commit | c4755d16fce9a4cdbb316c17657444856821bd4b (patch) | |
| tree | 56060ddcdb8e1e3ddcc7970a2324cadb3e8e4e27 /fs/jbd2 | |
| parent | c15a2434ed4868cad99278ac4d4ae4de9de62e02 (diff) | |
| parent | f1fa3342e271029f93d323ca664809b94594fe04 (diff) | |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (48 commits)
ext4: fix hot spins in mballoc after err_freebuddy and err_freemeta
ext4: fix test ext_generic_write_end() copied return value
ext3: fix test ext_generic_write_end() copied return value
ext4: Move mballoc headers/structures to a seperate header file mballoc.h
ext4: cleanup for compiling mballoc with verification and debugging #defines
ext4: don't use ext4_error in ext4_check_descriptors
ext4: mark inode dirty after initializing the extent tree
ext4: update ctime and mtime for truncate with extents.
ext4: Don't do GFP_NOFS allocations after taking ext4_lock_group
ext4: move headers out of include/linux
ext4: fix wrong gfp type under transaction
ext4: Fix hang on umount with quotas when journal is aborted
ext4: Fix update of mtime and ctime on rename
jdb2: replace remaining __FUNCTION__ occurrences
ext4: replace remaining __FUNCTION__ occurrences
jbd2: only create debugfs and stats entries if init is successful
jbd2: fix kernel-doc notation
jbd2: replace potentially false assertion with if block
jbd2: eliminate duplicated code in revocation table init/destroy functions
jbd2: tidy up revoke cache initialisation and destruction
...
Diffstat (limited to 'fs/jbd2')
| -rw-r--r-- | fs/jbd2/commit.c | 19 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 38 | ||||
| -rw-r--r-- | fs/jbd2/revoke.c | 165 | ||||
| -rw-r--r-- | fs/jbd2/transaction.c | 41 |
4 files changed, 133 insertions, 130 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 eb7eb6c27bcb..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; |
| @@ -997,13 +997,14 @@ fail: | |||
| 997 | */ | 997 | */ |
| 998 | 998 | ||
| 999 | /** | 999 | /** |
| 1000 | * 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 |
| 1001 | * @bdev: Block device on which to create the journal | 1001 | * @bdev: Block device on which to create the journal |
| 1002 | * @fs_dev: Device which hold journalled filesystem for this journal. | 1002 | * @fs_dev: Device which hold journalled filesystem for this journal. |
| 1003 | * @start: Block nr Start of journal. | 1003 | * @start: Block nr Start of journal. |
| 1004 | * @len: Length of the journal in blocks. | 1004 | * @len: Length of the journal in blocks. |
| 1005 | * @blocksize: blocksize of journalling device | 1005 | * @blocksize: blocksize of journalling device |
| 1006 | * @returns: a newly created journal_t * | 1006 | * |
| 1007 | * Returns: a newly created journal_t * | ||
| 1007 | * | 1008 | * |
| 1008 | * 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 |
| 1009 | * range of blocks on an arbitrary block device. | 1010 | * range of blocks on an arbitrary block device. |
| @@ -1027,7 +1028,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
| 1027 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); | 1028 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); |
| 1028 | if (!journal->j_wbuf) { | 1029 | if (!journal->j_wbuf) { |
| 1029 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 1030 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
| 1030 | __FUNCTION__); | 1031 | __func__); |
| 1031 | kfree(journal); | 1032 | kfree(journal); |
| 1032 | journal = NULL; | 1033 | journal = NULL; |
| 1033 | goto out; | 1034 | goto out; |
| @@ -1083,7 +1084,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 1083 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); | 1084 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); |
| 1084 | if (!journal->j_wbuf) { | 1085 | if (!journal->j_wbuf) { |
| 1085 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 1086 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
| 1086 | __FUNCTION__); | 1087 | __func__); |
| 1087 | kfree(journal); | 1088 | kfree(journal); |
| 1088 | return NULL; | 1089 | return NULL; |
| 1089 | } | 1090 | } |
| @@ -1092,7 +1093,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 1092 | /* If that failed, give up */ | 1093 | /* If that failed, give up */ |
| 1093 | if (err) { | 1094 | if (err) { |
| 1094 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", | 1095 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", |
| 1095 | __FUNCTION__); | 1096 | __func__); |
| 1096 | kfree(journal); | 1097 | kfree(journal); |
| 1097 | return NULL; | 1098 | return NULL; |
| 1098 | } | 1099 | } |
| @@ -1178,7 +1179,7 @@ int jbd2_journal_create(journal_t *journal) | |||
| 1178 | */ | 1179 | */ |
| 1179 | printk(KERN_EMERG | 1180 | printk(KERN_EMERG |
| 1180 | "%s: creation of journal on external device!\n", | 1181 | "%s: creation of journal on external device!\n", |
| 1181 | __FUNCTION__); | 1182 | __func__); |
| 1182 | BUG(); | 1183 | BUG(); |
| 1183 | } | 1184 | } |
| 1184 | 1185 | ||
| @@ -1976,9 +1977,10 @@ static int journal_init_jbd2_journal_head_cache(void) | |||
| 1976 | 1977 | ||
| 1977 | static void jbd2_journal_destroy_jbd2_journal_head_cache(void) | 1978 | static void jbd2_journal_destroy_jbd2_journal_head_cache(void) |
| 1978 | { | 1979 | { |
| 1979 | J_ASSERT(jbd2_journal_head_cache != NULL); | 1980 | if (jbd2_journal_head_cache) { |
| 1980 | kmem_cache_destroy(jbd2_journal_head_cache); | 1981 | kmem_cache_destroy(jbd2_journal_head_cache); |
| 1981 | jbd2_journal_head_cache = NULL; | 1982 | jbd2_journal_head_cache = NULL; |
| 1983 | } | ||
| 1982 | } | 1984 | } |
| 1983 | 1985 | ||
| 1984 | /* | 1986 | /* |
| @@ -1997,7 +1999,7 @@ static struct journal_head *journal_alloc_journal_head(void) | |||
| 1997 | jbd_debug(1, "out of memory for journal_head\n"); | 1999 | jbd_debug(1, "out of memory for journal_head\n"); |
| 1998 | if (time_after(jiffies, last_warning + 5*HZ)) { | 2000 | if (time_after(jiffies, last_warning + 5*HZ)) { |
| 1999 | printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", | 2001 | printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", |
| 2000 | __FUNCTION__); | 2002 | __func__); |
| 2001 | last_warning = jiffies; | 2003 | last_warning = jiffies; |
| 2002 | } | 2004 | } |
| 2003 | while (!ret) { | 2005 | while (!ret) { |
| @@ -2134,13 +2136,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh) | |||
| 2134 | if (jh->b_frozen_data) { | 2136 | if (jh->b_frozen_data) { |
| 2135 | printk(KERN_WARNING "%s: freeing " | 2137 | printk(KERN_WARNING "%s: freeing " |
| 2136 | "b_frozen_data\n", | 2138 | "b_frozen_data\n", |
| 2137 | __FUNCTION__); | 2139 | __func__); |
| 2138 | jbd2_free(jh->b_frozen_data, bh->b_size); | 2140 | jbd2_free(jh->b_frozen_data, bh->b_size); |
| 2139 | } | 2141 | } |
| 2140 | if (jh->b_committed_data) { | 2142 | if (jh->b_committed_data) { |
| 2141 | printk(KERN_WARNING "%s: freeing " | 2143 | printk(KERN_WARNING "%s: freeing " |
| 2142 | "b_committed_data\n", | 2144 | "b_committed_data\n", |
| 2143 | __FUNCTION__); | 2145 | __func__); |
| 2144 | jbd2_free(jh->b_committed_data, bh->b_size); | 2146 | jbd2_free(jh->b_committed_data, bh->b_size); |
| 2145 | } | 2147 | } |
| 2146 | bh->b_private = NULL; | 2148 | bh->b_private = NULL; |
| @@ -2305,10 +2307,12 @@ static int __init journal_init(void) | |||
| 2305 | BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024); | 2307 | BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024); |
| 2306 | 2308 | ||
| 2307 | ret = journal_init_caches(); | 2309 | ret = journal_init_caches(); |
| 2308 | if (ret != 0) | 2310 | if (ret == 0) { |
| 2311 | jbd2_create_debugfs_entry(); | ||
| 2312 | jbd2_create_jbd_stats_proc_entry(); | ||
| 2313 | } else { | ||
| 2309 | jbd2_journal_destroy_caches(); | 2314 | jbd2_journal_destroy_caches(); |
| 2310 | jbd2_create_debugfs_entry(); | 2315 | } |
| 2311 | jbd2_create_jbd_stats_proc_entry(); | ||
| 2312 | return ret; | 2316 | return ret; |
| 2313 | } | 2317 | } |
| 2314 | 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) |
