ext4: Track lifetime disk writes
authorTheodore Ts'o <tytso@mit.edu>
Sun, 1 Mar 2009 00:39:58 +0000 (19:39 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 1 Mar 2009 00:39:58 +0000 (19:39 -0500)
Add a new superblock value which tracks the lifetime amount of writes
to the filesystem.  This is useful in estimating the amount of wear on
solid state drives (SSD's) caused by writes to the filesystem.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/ext4_sb.h
fs/ext4/super.c

index 1b0c17364631ae465875061eb2a8046d00e55c17..0bd39188531cbf7b31fae9dfd975235de7e6e592 100644 (file)
@@ -683,7 +683,8 @@ struct ext4_super_block {
        __u8    s_log_groups_per_flex;  /* FLEX_BG group size */
        __u8    s_reserved_char_pad2;
        __le16  s_reserved_pad;
-       __u32   s_reserved[162];        /* Padding to the end of the block */
+       __le64  s_kbytes_written;       /* nr of lifetime kilobytes written */
+       __u32   s_reserved[160];        /* Padding to the end of the block */
 };
 
 #ifdef __KERNEL__
index 4e4d9cc3f40d855a0bcb3b98edb0c4ac8963cc62..50ab1169c378bbcc2e8e5b746fc2a6064a51e4ce 100644 (file)
@@ -142,6 +142,10 @@ struct ext4_sb_info {
        /* locality groups */
        struct ext4_locality_group *s_locality_groups;
 
+       /* for write statistics */
+       unsigned long s_sectors_written_start;
+       u64 s_kbytes_written;
+
        unsigned int s_log_groups_per_flex;
        struct flex_groups *s_flex_groups;
 };
index a3768709ce05f109ef749b421a3cc1a2a727bac4..30fc27cdf8fc90673414e0e11bc946128a6b6faa 100644 (file)
@@ -2035,6 +2035,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_resgid = EXT4_DEF_RESGID;
        sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
        sbi->s_sb_block = sb_block;
+       sbi->s_sectors_written_start = part_stat_read(sb->s_bdev->bd_part,
+                                                     sectors[1]);
 
        unlock_kernel();
 
@@ -2072,6 +2074,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_magic = le16_to_cpu(es->s_magic);
        if (sb->s_magic != EXT4_SUPER_MAGIC)
                goto cantfind_ext4;
+       sbi->s_kbytes_written = le64_to_cpu(es->s_kbytes_written);
 
        /* Set defaults before we parse the mount options */
        def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
@@ -2921,6 +2924,10 @@ static int ext4_commit_super(struct super_block *sb,
                set_buffer_uptodate(sbh);
        }
        es->s_wtime = cpu_to_le32(get_seconds());
+       es->s_kbytes_written =
+               cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + 
+                           ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
+                             EXT4_SB(sb)->s_sectors_written_start) >> 1));
        ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
                                        &EXT4_SB(sb)->s_freeblocks_counter));
        es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive(