Commit 146bca72c7e6ba52de82a63b1fce7934dc103dbc

Authored by Jan Kara
1 parent 4034600516

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>

Showing 5 changed files with 52 additions and 47 deletions Side-by-side Diff

... ... @@ -140,17 +140,17 @@
140 140 return slot;
141 141 }
142 142  
143   -static bool udf_add_free_space(struct udf_sb_info *sbi,
144   - u16 partition, u32 cnt)
  143 +static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt)
145 144 {
  145 + struct udf_sb_info *sbi = UDF_SB(sb);
146 146 struct logicalVolIntegrityDesc *lvid;
147 147  
148   - if (sbi->s_lvid_bh == NULL)
149   - return false;
  148 + if (!sbi->s_lvid_bh)
  149 + return;
150 150  
151 151 lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
152 152 le32_add_cpu(&lvid->freeSpaceTable[partition], cnt);
153   - return true;
  153 + udf_updated_lvid(sb);
154 154 }
155 155  
156 156 static void udf_bitmap_free_blocks(struct super_block *sb,
... ... @@ -209,7 +209,7 @@
209 209 } else {
210 210 if (inode)
211 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 215 mark_buffer_dirty(bh);
... ... @@ -220,9 +220,6 @@
220 220 } while (overflow);
221 221  
222 222 error_return:
223   - sb->s_dirt = 1;
224   - if (sbi->s_lvid_bh)
225   - mark_buffer_dirty(sbi->s_lvid_bh);
226 223 mutex_unlock(&sbi->s_alloc_mutex);
227 224 }
228 225  
... ... @@ -279,9 +276,7 @@
279 276 } while (block_count > 0);
280 277  
281 278 out:
282   - if (udf_add_free_space(sbi, partition, -alloc_count))
283   - mark_buffer_dirty(sbi->s_lvid_bh);
284   - sb->s_dirt = 1;
  279 + udf_add_free_space(sb, partition, -alloc_count);
285 280 mutex_unlock(&sbi->s_alloc_mutex);
286 281 return alloc_count;
287 282 }
... ... @@ -411,9 +406,7 @@
411 406  
412 407 mark_buffer_dirty(bh);
413 408  
414   - if (udf_add_free_space(sbi, partition, -1))
415   - mark_buffer_dirty(sbi->s_lvid_bh);
416   - sb->s_dirt = 1;
  409 + udf_add_free_space(sb, partition, -1);
417 410 mutex_unlock(&sbi->s_alloc_mutex);
418 411 *err = 0;
419 412 return newblock;
... ... @@ -457,8 +450,7 @@
457 450 could occure, but.. oh well */
458 451 if (inode)
459 452 vfs_dq_free_block(inode, count);
460   - if (udf_add_free_space(sbi, sbi->s_partition, count))
461   - mark_buffer_dirty(sbi->s_lvid_bh);
  453 + udf_add_free_space(sb, sbi->s_partition, count);
462 454  
463 455 start = bloc->logicalBlockNum + offset;
464 456 end = bloc->logicalBlockNum + offset + count - 1;
... ... @@ -657,7 +649,6 @@
657 649 brelse(oepos.bh);
658 650  
659 651 error_return:
660   - sb->s_dirt = 1;
661 652 mutex_unlock(&sbi->s_alloc_mutex);
662 653 return;
663 654 }
... ... @@ -722,10 +713,8 @@
722 713  
723 714 brelse(epos.bh);
724 715  
725   - if (alloc_count && udf_add_free_space(sbi, partition, -alloc_count)) {
726   - mark_buffer_dirty(sbi->s_lvid_bh);
727   - sb->s_dirt = 1;
728   - }
  716 + if (alloc_count)
  717 + udf_add_free_space(sb, partition, -alloc_count);
729 718 mutex_unlock(&sbi->s_alloc_mutex);
730 719 return alloc_count;
731 720 }
732 721  
... ... @@ -823,10 +812,8 @@
823 812 udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);
824 813 brelse(goal_epos.bh);
825 814  
826   - if (udf_add_free_space(sbi, partition, -1))
827   - mark_buffer_dirty(sbi->s_lvid_bh);
  815 + udf_add_free_space(sb, partition, -1);
828 816  
829   - sb->s_dirt = 1;
830 817 mutex_unlock(&sbi->s_alloc_mutex);
831 818 *err = 0;
832 819 return newblock;
... ... @@ -49,8 +49,7 @@
49 49 le32_add_cpu(&lvidiu->numDirs, -1);
50 50 else
51 51 le32_add_cpu(&lvidiu->numFiles, -1);
52   -
53   - mark_buffer_dirty(sbi->s_lvid_bh);
  52 + udf_updated_lvid(sb);
54 53 }
55 54 mutex_unlock(&sbi->s_alloc_mutex);
56 55  
... ... @@ -122,7 +121,7 @@
122 121 if (!(++uniqueID & 0x00000000FFFFFFFFUL))
123 122 uniqueID += 16;
124 123 lvhd->uniqueID = cpu_to_le64(uniqueID);
125   - mark_buffer_dirty(sbi->s_lvid_bh);
  124 + udf_updated_lvid(sb);
126 125 }
127 126 mutex_unlock(&sbi->s_alloc_mutex);
128 127 inode->i_mode = mode;
... ... @@ -81,7 +81,7 @@
81 81 /* These are the "meat" - everything else is stuffing */
82 82 static int udf_fill_super(struct super_block *, void *, int);
83 83 static void udf_put_super(struct super_block *);
84   -static void udf_write_super(struct super_block *);
  84 +static int udf_sync_fs(struct super_block *, int);
85 85 static int udf_remount_fs(struct super_block *, int *, char *);
86 86 static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad);
87 87 static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *,
... ... @@ -178,7 +178,7 @@
178 178 .delete_inode = udf_delete_inode,
179 179 .clear_inode = udf_clear_inode,
180 180 .put_super = udf_put_super,
181   - .write_super = udf_write_super,
  181 + .sync_fs = udf_sync_fs,
182 182 .statfs = udf_statfs,
183 183 .remount_fs = udf_remount_fs,
184 184 .show_options = udf_show_options,
... ... @@ -553,17 +553,6 @@
553 553 return 1;
554 554 }
555 555  
556   -static void udf_write_super(struct super_block *sb)
557   -{
558   - lock_kernel();
559   -
560   - if (!(sb->s_flags & MS_RDONLY))
561   - udf_open_lvid(sb);
562   - sb->s_dirt = 0;
563   -
564   - unlock_kernel();
565   -}
566   -
567 556 static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
568 557 {
569 558 struct udf_options uopt;
570 559  
... ... @@ -1753,9 +1742,9 @@
1753 1742 struct buffer_head *bh = sbi->s_lvid_bh;
1754 1743 struct logicalVolIntegrityDesc *lvid;
1755 1744 struct logicalVolIntegrityDescImpUse *lvidiu;
  1745 +
1756 1746 if (!bh)
1757 1747 return;
1758   -
1759 1748 lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
1760 1749 lvidiu = udf_sb_lvidiu(sbi);
1761 1750  
... ... @@ -1763,7 +1752,7 @@
1763 1752 lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
1764 1753 udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
1765 1754 CURRENT_TIME);
1766   - lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
  1755 + lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
1767 1756  
1768 1757 lvid->descTag.descCRC = cpu_to_le16(
1769 1758 crc_itu_t(0, (char *)lvid + sizeof(struct tag),
... ... @@ -1771,6 +1760,7 @@
1771 1760  
1772 1761 lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
1773 1762 mark_buffer_dirty(bh);
  1763 + sbi->s_lvid_dirty = 0;
1774 1764 }
1775 1765  
1776 1766 static void udf_close_lvid(struct super_block *sb)
... ... @@ -1784,10 +1774,6 @@
1784 1774 return;
1785 1775  
1786 1776 lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
1787   -
1788   - if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN)
1789   - return;
1790   -
1791 1777 lvidiu = udf_sb_lvidiu(sbi);
1792 1778 lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
1793 1779 lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
... ... @@ -1806,6 +1792,7 @@
1806 1792  
1807 1793 lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
1808 1794 mark_buffer_dirty(bh);
  1795 + sbi->s_lvid_dirty = 0;
1809 1796 }
1810 1797  
1811 1798 static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
... ... @@ -2090,6 +2077,25 @@
2090 2077 kfree(sbi->s_partmaps);
2091 2078 kfree(sb->s_fs_info);
2092 2079 sb->s_fs_info = NULL;
  2080 +}
  2081 +
  2082 +static int udf_sync_fs(struct super_block *sb, int wait)
  2083 +{
  2084 + struct udf_sb_info *sbi = UDF_SB(sb);
  2085 +
  2086 + mutex_lock(&sbi->s_alloc_mutex);
  2087 + if (sbi->s_lvid_dirty) {
  2088 + /*
  2089 + * Blockdevice will be synced later so we don't have to submit
  2090 + * the buffer for IO
  2091 + */
  2092 + mark_buffer_dirty(sbi->s_lvid_bh);
  2093 + sb->s_dirt = 0;
  2094 + sbi->s_lvid_dirty = 0;
  2095 + }
  2096 + mutex_unlock(&sbi->s_alloc_mutex);
  2097 +
  2098 + return 0;
2093 2099 }
2094 2100  
2095 2101 static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
... ... @@ -148,6 +148,8 @@
148 148 struct inode *s_vat_inode;
149 149  
150 150 struct mutex s_alloc_mutex;
  151 + /* Protected by s_alloc_mutex */
  152 + unsigned int s_lvid_dirty;
151 153 };
152 154  
153 155 static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
... ... @@ -111,6 +111,17 @@
111 111  
112 112 /* super.c */
113 113 extern void udf_warning(struct super_block *, const char *, const char *, ...);
  114 +static inline void udf_updated_lvid(struct super_block *sb)
  115 +{
  116 + struct buffer_head *bh = UDF_SB(sb)->s_lvid_bh;
  117 +
  118 + BUG_ON(!bh);
  119 + WARN_ON_ONCE(((struct logicalVolIntegrityDesc *)
  120 + bh->b_data)->integrityType !=
  121 + cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN));
  122 + sb->s_dirt = 1;
  123 + UDF_SB(sb)->s_lvid_dirty = 1;
  124 +}
114 125  
115 126 /* namei.c */
116 127 extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,