aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/super.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2009-03-16 13:27:37 -0400
committerJan Kara <jack@suse.cz>2009-04-02 07:36:28 -0400
commit146bca72c7e6ba52de82a63b1fce7934dc103dbc (patch)
treefee0aff001a5d5226518f0b67232f083f0931209 /fs/udf/super.c
parent40346005166329bc4b53e0c564aff3968c1ddaa0 (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/super.c')
-rw-r--r--fs/udf/super.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index cae079eb5dd9..72348cc855a4 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -81,7 +81,7 @@ static char error_buf[1024];
81/* These are the "meat" - everything else is stuffing */ 81/* These are the "meat" - everything else is stuffing */
82static int udf_fill_super(struct super_block *, void *, int); 82static int udf_fill_super(struct super_block *, void *, int);
83static void udf_put_super(struct super_block *); 83static void udf_put_super(struct super_block *);
84static void udf_write_super(struct super_block *); 84static int udf_sync_fs(struct super_block *, int);
85static int udf_remount_fs(struct super_block *, int *, char *); 85static int udf_remount_fs(struct super_block *, int *, char *);
86static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad); 86static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad);
87static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *, 87static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *,
@@ -178,7 +178,7 @@ static const struct super_operations udf_sb_ops = {
178 .delete_inode = udf_delete_inode, 178 .delete_inode = udf_delete_inode,
179 .clear_inode = udf_clear_inode, 179 .clear_inode = udf_clear_inode,
180 .put_super = udf_put_super, 180 .put_super = udf_put_super,
181 .write_super = udf_write_super, 181 .sync_fs = udf_sync_fs,
182 .statfs = udf_statfs, 182 .statfs = udf_statfs,
183 .remount_fs = udf_remount_fs, 183 .remount_fs = udf_remount_fs,
184 .show_options = udf_show_options, 184 .show_options = udf_show_options,
@@ -553,17 +553,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
553 return 1; 553 return 1;
554} 554}
555 555
556static 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
567static int udf_remount_fs(struct super_block *sb, int *flags, char *options) 556static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
568{ 557{
569 struct udf_options uopt; 558 struct udf_options uopt;
@@ -1753,9 +1742,9 @@ static void udf_open_lvid(struct super_block *sb)
1753 struct buffer_head *bh = sbi->s_lvid_bh; 1742 struct buffer_head *bh = sbi->s_lvid_bh;
1754 struct logicalVolIntegrityDesc *lvid; 1743 struct logicalVolIntegrityDesc *lvid;
1755 struct logicalVolIntegrityDescImpUse *lvidiu; 1744 struct logicalVolIntegrityDescImpUse *lvidiu;
1745
1756 if (!bh) 1746 if (!bh)
1757 return; 1747 return;
1758
1759 lvid = (struct logicalVolIntegrityDesc *)bh->b_data; 1748 lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
1760 lvidiu = udf_sb_lvidiu(sbi); 1749 lvidiu = udf_sb_lvidiu(sbi);
1761 1750
@@ -1763,7 +1752,7 @@ static void udf_open_lvid(struct super_block *sb)
1763 lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; 1752 lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
1764 udf_time_to_disk_stamp(&lvid->recordingDateAndTime, 1753 udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
1765 CURRENT_TIME); 1754 CURRENT_TIME);
1766 lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN; 1755 lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
1767 1756
1768 lvid->descTag.descCRC = cpu_to_le16( 1757 lvid->descTag.descCRC = cpu_to_le16(
1769 crc_itu_t(0, (char *)lvid + sizeof(struct tag), 1758 crc_itu_t(0, (char *)lvid + sizeof(struct tag),
@@ -1771,6 +1760,7 @@ static void udf_open_lvid(struct super_block *sb)
1771 1760
1772 lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); 1761 lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
1773 mark_buffer_dirty(bh); 1762 mark_buffer_dirty(bh);
1763 sbi->s_lvid_dirty = 0;
1774} 1764}
1775 1765
1776static void udf_close_lvid(struct super_block *sb) 1766static void udf_close_lvid(struct super_block *sb)
@@ -1784,10 +1774,6 @@ static void udf_close_lvid(struct super_block *sb)
1784 return; 1774 return;
1785 1775
1786 lvid = (struct logicalVolIntegrityDesc *)bh->b_data; 1776 lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
1787
1788 if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN)
1789 return;
1790
1791 lvidiu = udf_sb_lvidiu(sbi); 1777 lvidiu = udf_sb_lvidiu(sbi);
1792 lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; 1778 lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
1793 lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; 1779 lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
@@ -1806,6 +1792,7 @@ static void udf_close_lvid(struct super_block *sb)
1806 1792
1807 lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); 1793 lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
1808 mark_buffer_dirty(bh); 1794 mark_buffer_dirty(bh);
1795 sbi->s_lvid_dirty = 0;
1809} 1796}
1810 1797
1811static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) 1798static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
@@ -2092,6 +2079,25 @@ static void udf_put_super(struct super_block *sb)
2092 sb->s_fs_info = NULL; 2079 sb->s_fs_info = NULL;
2093} 2080}
2094 2081
2082static 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;
2099}
2100
2095static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) 2101static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
2096{ 2102{
2097 struct super_block *sb = dentry->d_sb; 2103 struct super_block *sb = dentry->d_sb;