diff options
author | Jan Kara <jack@suse.cz> | 2009-03-16 13:27:37 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2009-04-02 07:36:28 -0400 |
commit | 146bca72c7e6ba52de82a63b1fce7934dc103dbc (patch) | |
tree | fee0aff001a5d5226518f0b67232f083f0931209 /fs/udf/balloc.c | |
parent | 40346005166329bc4b53e0c564aff3968c1ddaa0 (diff) |
udf: Don't write integrity descriptor too often
We update information in logical volume integrity descriptor after each
allocation (as LVID contains free space, number of directories and files on
disk etc.). If the filesystem is on some phase change media, this leads to its
quick degradation as such media is able to handle only 10000 overwrites or so.
We solve the problem by writing new information into LVID only on umount,
remount-ro and sync. This solves the problem at the price of longer media
inconsistency (previously media became consistent after pdflush flushed dirty
LVID buffer) but that should be acceptable.
Report by and patch written in cooperation with
Rich Coe <Richard.Coe@med.ge.com>.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/balloc.c')
-rw-r--r-- | fs/udf/balloc.c | 37 |
1 files changed, 12 insertions, 25 deletions
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 58be702cb42d..e48e9a3af763 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c | |||
@@ -140,17 +140,17 @@ static inline int load_block_bitmap(struct super_block *sb, | |||
140 | return slot; | 140 | return slot; |
141 | } | 141 | } |
142 | 142 | ||
143 | static bool udf_add_free_space(struct udf_sb_info *sbi, | 143 | static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt) |
144 | u16 partition, u32 cnt) | ||
145 | { | 144 | { |
145 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
146 | struct logicalVolIntegrityDesc *lvid; | 146 | struct logicalVolIntegrityDesc *lvid; |
147 | 147 | ||
148 | if (sbi->s_lvid_bh == NULL) | 148 | if (!sbi->s_lvid_bh) |
149 | return false; | 149 | return; |
150 | 150 | ||
151 | lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; | 151 | lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; |
152 | le32_add_cpu(&lvid->freeSpaceTable[partition], cnt); | 152 | le32_add_cpu(&lvid->freeSpaceTable[partition], cnt); |
153 | return true; | 153 | udf_updated_lvid(sb); |
154 | } | 154 | } |
155 | 155 | ||
156 | static void udf_bitmap_free_blocks(struct super_block *sb, | 156 | static void udf_bitmap_free_blocks(struct super_block *sb, |
@@ -209,7 +209,7 @@ static void udf_bitmap_free_blocks(struct super_block *sb, | |||
209 | } else { | 209 | } else { |
210 | if (inode) | 210 | if (inode) |
211 | vfs_dq_free_block(inode, 1); | 211 | vfs_dq_free_block(inode, 1); |
212 | udf_add_free_space(sbi, sbi->s_partition, 1); | 212 | udf_add_free_space(sb, sbi->s_partition, 1); |
213 | } | 213 | } |
214 | } | 214 | } |
215 | mark_buffer_dirty(bh); | 215 | mark_buffer_dirty(bh); |
@@ -220,9 +220,6 @@ static void udf_bitmap_free_blocks(struct super_block *sb, | |||
220 | } while (overflow); | 220 | } while (overflow); |
221 | 221 | ||
222 | error_return: | 222 | error_return: |
223 | sb->s_dirt = 1; | ||
224 | if (sbi->s_lvid_bh) | ||
225 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
226 | mutex_unlock(&sbi->s_alloc_mutex); | 223 | mutex_unlock(&sbi->s_alloc_mutex); |
227 | } | 224 | } |
228 | 225 | ||
@@ -279,9 +276,7 @@ static int udf_bitmap_prealloc_blocks(struct super_block *sb, | |||
279 | } while (block_count > 0); | 276 | } while (block_count > 0); |
280 | 277 | ||
281 | out: | 278 | out: |
282 | if (udf_add_free_space(sbi, partition, -alloc_count)) | 279 | udf_add_free_space(sb, partition, -alloc_count); |
283 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
284 | sb->s_dirt = 1; | ||
285 | mutex_unlock(&sbi->s_alloc_mutex); | 280 | mutex_unlock(&sbi->s_alloc_mutex); |
286 | return alloc_count; | 281 | return alloc_count; |
287 | } | 282 | } |
@@ -411,9 +406,7 @@ got_block: | |||
411 | 406 | ||
412 | mark_buffer_dirty(bh); | 407 | mark_buffer_dirty(bh); |
413 | 408 | ||
414 | if (udf_add_free_space(sbi, partition, -1)) | 409 | udf_add_free_space(sb, partition, -1); |
415 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
416 | sb->s_dirt = 1; | ||
417 | mutex_unlock(&sbi->s_alloc_mutex); | 410 | mutex_unlock(&sbi->s_alloc_mutex); |
418 | *err = 0; | 411 | *err = 0; |
419 | return newblock; | 412 | return newblock; |
@@ -457,8 +450,7 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
457 | could occure, but.. oh well */ | 450 | could occure, but.. oh well */ |
458 | if (inode) | 451 | if (inode) |
459 | vfs_dq_free_block(inode, count); | 452 | vfs_dq_free_block(inode, count); |
460 | if (udf_add_free_space(sbi, sbi->s_partition, count)) | 453 | udf_add_free_space(sb, sbi->s_partition, count); |
461 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
462 | 454 | ||
463 | start = bloc->logicalBlockNum + offset; | 455 | start = bloc->logicalBlockNum + offset; |
464 | end = bloc->logicalBlockNum + offset + count - 1; | 456 | end = bloc->logicalBlockNum + offset + count - 1; |
@@ -657,7 +649,6 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
657 | brelse(oepos.bh); | 649 | brelse(oepos.bh); |
658 | 650 | ||
659 | error_return: | 651 | error_return: |
660 | sb->s_dirt = 1; | ||
661 | mutex_unlock(&sbi->s_alloc_mutex); | 652 | mutex_unlock(&sbi->s_alloc_mutex); |
662 | return; | 653 | return; |
663 | } | 654 | } |
@@ -722,10 +713,8 @@ static int udf_table_prealloc_blocks(struct super_block *sb, | |||
722 | 713 | ||
723 | brelse(epos.bh); | 714 | brelse(epos.bh); |
724 | 715 | ||
725 | if (alloc_count && udf_add_free_space(sbi, partition, -alloc_count)) { | 716 | if (alloc_count) |
726 | mark_buffer_dirty(sbi->s_lvid_bh); | 717 | udf_add_free_space(sb, partition, -alloc_count); |
727 | sb->s_dirt = 1; | ||
728 | } | ||
729 | mutex_unlock(&sbi->s_alloc_mutex); | 718 | mutex_unlock(&sbi->s_alloc_mutex); |
730 | return alloc_count; | 719 | return alloc_count; |
731 | } | 720 | } |
@@ -823,10 +812,8 @@ static int udf_table_new_block(struct super_block *sb, | |||
823 | udf_delete_aext(table, goal_epos, goal_eloc, goal_elen); | 812 | udf_delete_aext(table, goal_epos, goal_eloc, goal_elen); |
824 | brelse(goal_epos.bh); | 813 | brelse(goal_epos.bh); |
825 | 814 | ||
826 | if (udf_add_free_space(sbi, partition, -1)) | 815 | udf_add_free_space(sb, partition, -1); |
827 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
828 | 816 | ||
829 | sb->s_dirt = 1; | ||
830 | mutex_unlock(&sbi->s_alloc_mutex); | 817 | mutex_unlock(&sbi->s_alloc_mutex); |
831 | *err = 0; | 818 | *err = 0; |
832 | return newblock; | 819 | return newblock; |