fat: make discard a mount option
Christoph Hellwig [Sat, 21 Nov 2009 11:28:52 +0000 (20:28 +0900)]
Currently shipping discard capable SSDs and arrays have rather sub-optimal
implementations of the command and can the use of it can cause massive
slowdowns.  Make issueing these commands option as it's already in btrfs
and gfs2.

Signed-off-by: Christoph Hellwig <hch@lst.de>
[hirofumi@mail.parknet.co.jp: tweaks, and add "discard" to fat_show_options]
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

fs/fat/fat.h
fs/fat/fatent.c
fs/fat/inode.c

index 7db0979..e6efdfa 100644 (file)
@@ -44,7 +44,8 @@ struct fat_mount_options {
                 nocase:1,        /* Does this need case conversion? 0=need case conversion*/
                 usefree:1,       /* Use free_clusters for FAT32 */
                 tz_utc:1,        /* Filesystem timestamps are in UTC */
-                rodir:1;         /* allow ATTR_RO for directory */
+                rodir:1,         /* allow ATTR_RO for directory */
+                discard:1;       /* Issue discard requests on deletions */
 };
 
 #define FAT_HASH_BITS  8
index a810377..81184d3 100644 (file)
@@ -566,16 +566,21 @@ int fat_free_clusters(struct inode *inode, int cluster)
                        goto error;
                }
 
-               /* 
-                * Issue discard for the sectors we no longer care about,
-                * batching contiguous clusters into one request
-                */
-               if (cluster != fatent.entry + 1) {
-                       int nr_clus = fatent.entry - first_cl + 1;
-
-                       sb_issue_discard(sb, fat_clus_to_blknr(sbi, first_cl),
-                                        nr_clus * sbi->sec_per_clus);
-                       first_cl = cluster;
+               if (sbi->options.discard) {
+                       /*
+                        * Issue discard for the sectors we no longer
+                        * care about, batching contiguous clusters
+                        * into one request
+                        */
+                       if (cluster != fatent.entry + 1) {
+                               int nr_clus = fatent.entry - first_cl + 1;
+
+                               sb_issue_discard(sb,
+                                       fat_clus_to_blknr(sbi, first_cl),
+                                       nr_clus * sbi->sec_per_clus);
+
+                               first_cl = cluster;
+                       }
                }
 
                ops->ent_put(&fatent, FAT_ENT_FREE);
index 76b7961..14da530 100644 (file)
@@ -858,6 +858,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
                seq_puts(m, ",errors=panic");
        else
                seq_puts(m, ",errors=remount-ro");
+       if (opts->discard)
+               seq_puts(m, ",discard");
 
        return 0;
 }
@@ -871,7 +873,7 @@ enum {
        Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
        Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
        Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
-       Opt_err_panic, Opt_err_ro, Opt_err,
+       Opt_err_panic, Opt_err_ro, Opt_discard, Opt_err,
 };
 
 static const match_table_t fat_tokens = {
@@ -899,6 +901,7 @@ static const match_table_t fat_tokens = {
        {Opt_err_cont, "errors=continue"},
        {Opt_err_panic, "errors=panic"},
        {Opt_err_ro, "errors=remount-ro"},
+       {Opt_discard, "discard"},
        {Opt_obsolate, "conv=binary"},
        {Opt_obsolate, "conv=text"},
        {Opt_obsolate, "conv=auto"},
@@ -1136,6 +1139,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                case Opt_rodir:
                        opts->rodir = 1;
                        break;
+               case Opt_discard:
+                       opts->discard = 1;
+                       break;
 
                /* obsolete mount options */
                case Opt_obsolate: