summaryrefslogtreecommitdiff
path: root/fs/jfs/super.c
diff options
context:
space:
mode:
authorTino Reichardt <milky-kernel@mcmilk.de>2012-09-17 11:58:19 -0500
committerDave Kleikamp <dave.kleikamp@oracle.com>2012-09-17 11:58:19 -0500
commitb40c2e665cd552eae5fbdbb878bc29a34357668e (patch)
tree23714e5773a77abf1daf71ca7958dcd8dfa688ea /fs/jfs/super.c
parentfbcbe2b3c92ee1c930dcfcf8bb764074c100fd63 (diff)
downloadlinux-b40c2e665cd552eae5fbdbb878bc29a34357668e.tar.gz
fs/jfs: TRIM support for JFS Filesystem
This patch adds support for the two linux interfaces of the discard/TRIM command for SSD devices and sparse/thinly-provisioned LUNs. JFS will support batched discard via FITRIM ioctl and online discard with the discard mount option. Signed-off-by: Tino Reichardt <list-jfs@mcmilk.de> Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
Diffstat (limited to 'fs/jfs/super.c')
-rw-r--r--fs/jfs/super.c71
1 files changed, 56 insertions, 15 deletions
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index c55c7452d285..6f4ac1c070f0 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -33,6 +33,7 @@
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/seq_file.h>
+#include <linux/blkdev.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
@@ -100,7 +101,7 @@ void jfs_error(struct super_block *sb, const char * function, ...)
vsnprintf(error_buf, sizeof(error_buf), function, args);
va_end(args);
- printk(KERN_ERR "ERROR: (device %s): %s\n", sb->s_id, error_buf);
+ pr_err("ERROR: (device %s): %s\n", sb->s_id, error_buf);
jfs_handle_error(sb);
}
@@ -197,7 +198,8 @@ static void jfs_put_super(struct super_block *sb)
enum {
Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
- Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask
+ Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask,
+ Opt_discard, Opt_nodiscard, Opt_discard_minblk
};
static const match_table_t tokens = {
@@ -214,6 +216,9 @@ static const match_table_t tokens = {
{Opt_uid, "uid=%u"},
{Opt_gid, "gid=%u"},
{Opt_umask, "umask=%u"},
+ {Opt_discard, "discard"},
+ {Opt_nodiscard, "nodiscard"},
+ {Opt_discard_minblk, "discard=%u"},
{Opt_err, NULL}
};
@@ -255,8 +260,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
else {
nls_map = load_nls(args[0].from);
if (!nls_map) {
- printk(KERN_ERR
- "JFS: charset not found\n");
+ pr_err("JFS: charset not found\n");
goto cleanup;
}
}
@@ -272,8 +276,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
*newLVSize = sb->s_bdev->bd_inode->i_size >>
sb->s_blocksize_bits;
if (*newLVSize == 0)
- printk(KERN_ERR
- "JFS: Cannot determine volume size\n");
+ pr_err("JFS: Cannot determine volume size\n");
break;
}
case Opt_errors:
@@ -294,8 +297,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
*flag &= ~JFS_ERR_REMOUNT_RO;
*flag |= JFS_ERR_PANIC;
} else {
- printk(KERN_ERR
- "JFS: %s is an invalid error handler\n",
+ pr_err("JFS: %s is an invalid error handler\n",
errors);
goto cleanup;
}
@@ -314,8 +316,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
case Opt_usrquota:
case Opt_grpquota:
case Opt_quota:
- printk(KERN_ERR
- "JFS: quota operations not supported\n");
+ pr_err("JFS: quota operations not supported\n");
break;
#endif
case Opt_uid:
@@ -324,23 +325,61 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
sbi->uid = simple_strtoul(uid, &uid, 0);
break;
}
+
case Opt_gid:
{
char *gid = args[0].from;
sbi->gid = simple_strtoul(gid, &gid, 0);
break;
}
+
case Opt_umask:
{
char *umask = args[0].from;
sbi->umask = simple_strtoul(umask, &umask, 8);
if (sbi->umask & ~0777) {
- printk(KERN_ERR
- "JFS: Invalid value of umask\n");
+ pr_err("JFS: Invalid value of umask\n");
goto cleanup;
}
break;
}
+
+ case Opt_discard:
+ {
+ struct request_queue *q = bdev_get_queue(sb->s_bdev);
+ /* if set to 1, even copying files will cause
+ * trimming :O
+ * -> user has more control over the online trimming
+ */
+ sbi->minblks_trim = 64;
+ if (blk_queue_discard(q)) {
+ *flag |= JFS_DISCARD;
+ } else {
+ pr_err("JFS: discard option " \
+ "not supported on device\n");
+ }
+ break;
+ }
+
+ case Opt_nodiscard:
+ *flag &= ~JFS_DISCARD;
+ break;
+
+ case Opt_discard_minblk:
+ {
+ struct request_queue *q = bdev_get_queue(sb->s_bdev);
+ char *minblks_trim = args[0].from;
+ if (blk_queue_discard(q)) {
+ *flag |= JFS_DISCARD;
+ sbi->minblks_trim = simple_strtoull(
+ minblks_trim, &minblks_trim, 0);
+ } else {
+ pr_err("JFS: discard option " \
+ "not supported on device\n");
+ }
+ break;
+ }
+
default:
printk("jfs: Unrecognized mount option \"%s\" "
" or missing value\n", p);
@@ -374,8 +413,8 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data)
if (newLVSize) {
if (sb->s_flags & MS_RDONLY) {
- printk(KERN_ERR
- "JFS: resize requires volume to be mounted read-write\n");
+ pr_err("JFS: resize requires volume" \
+ " to be mounted read-write\n");
return -EROFS;
}
rc = jfs_extendfs(sb, newLVSize, 0);
@@ -457,7 +496,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
#endif
if (newLVSize) {
- printk(KERN_ERR "resize option for remount only\n");
+ pr_err("resize option for remount only\n");
goto out_kfree;
}
@@ -625,6 +664,8 @@ static int jfs_show_options(struct seq_file *seq, struct dentry *root)
seq_printf(seq, ",umask=%03o", sbi->umask);
if (sbi->flag & JFS_NOINTEGRITY)
seq_puts(seq, ",nointegrity");
+ if (sbi->flag & JFS_DISCARD)
+ seq_printf(seq, ",discard=%u", sbi->minblks_trim);
if (sbi->nls_tab)
seq_printf(seq, ",iocharset=%s", sbi->nls_tab->charset);
if (sbi->flag & JFS_ERR_CONTINUE)