Skip to contentSkip to conversation

Allow passing fine resolution timing options to mount

PATCH In review Amit Gud 2 participants 2 messages Aug 12, 2009

Subsystems (2)
lore
Share & tools
lore

Amit Gud

author
#0 lore raw

PATCH 1/1 Allow passing fine resolution timing options to mount

This patch modifies parsing of mount options to allows passing units along with the options. Valid units are "se" for seconds and "ms" for milliseconds. When not specified, the unit defaults to seconds.

For example, "-o acdirmin=20ms" can be specified for 20 milliseconds, and "-o acdirmin=3se" or just "-o acdirmin=3" for 3 seconds.

This code also changes the display of options in /proc/<pid>/mountstats from seconds to milliseconds to reflect the accuracy.

fs/nfs/client.c +4 -4
Index: linux-2.6/fs/nfs/client.c
===================================================================
@@ -1295,10 +1295,10 @@
 	if (data->wsize)
 		server->wsize = nfs_block_size(data->wsize, NULL);
 
-	server->acregmin = data->acregmin * HZ;
-	server->acregmax = data->acregmax * HZ;
-	server->acdirmin = data->acdirmin * HZ;
-	server->acdirmax = data->acdirmax * HZ;
+	server->acregmin = (data->acregmin * HZ) / 1000;
+	server->acregmax = (data->acregmax * HZ) / 1000;
+	server->acdirmin = (data->acdirmin * HZ) / 1000;
+	server->acdirmax = (data->acdirmax * HZ) / 1000;
 
 	server->port = data->nfs_server.port;
 
fs/nfs/super.c +65 -21

169 lines not on this page · raw message

include/linux/nfs_fs.h +4 -4
Index: linux-2.6/include/linux/nfs_fs.h
===================================================================
@@ -20,10 +20,10 @@
 #define NFS_MAX_UDP_TIMEOUT	(60*HZ)
 #define NFS_MAX_TCP_TIMEOUT	(600*HZ)
 
-#define NFS_DEF_ACREGMIN	(3)
-#define NFS_DEF_ACREGMAX	(60)
-#define NFS_DEF_ACDIRMIN	(30)
-#define NFS_DEF_ACDIRMAX	(60)
+#define NFS_DEF_ACREGMIN	(3000)
+#define NFS_DEF_ACREGMAX	(60000)
+#define NFS_DEF_ACDIRMIN	(30000)
+#define NFS_DEF_ACDIRMAX	(60000)
 
 /*
  * When flushing a cluster of dirty pages, there can be different
Signature · 2 lines
May the source be with you.
http://cis.ksu.edu~/gud
#1 lore raw
Quoted 82 lines · On Tue, 11 Aug 2009 18:58:38 -0700 Amit Gud <[email protected]> wrote:

This patch modifies parsing of mount options to allows passing units along with the options. Valid units are "se" for seconds and "ms" for milliseconds. When not specified, the unit defaults to seconds.

For example, "-o acdirmin=20ms" can be specified for 20 milliseconds, and "-o acdirmin=3se" or just "-o acdirmin=3" for 3 seconds.

This code also changes the display of options in /proc/<pid>/mountstats from seconds to milliseconds to reflect the accuracy.

Index: linux-2.6/fs/nfs/client.c
===================================================================

fs/nfs/client.c +4 -4
@@ -1295,10 +1295,10 @@
 	if (data->wsize)
 		server->wsize = nfs_block_size(data->wsize, NULL);
 
-	server->acregmin = data->acregmin * HZ;
-	server->acregmax = data->acregmax * HZ;
-	server->acdirmin = data->acdirmin * HZ;
-	server->acdirmax = data->acdirmax * HZ;
+	server->acregmin = (data->acregmin * HZ) / 1000;
+	server->acregmax = (data->acregmax * HZ) / 1000;
+	server->acdirmin = (data->acdirmin * HZ) / 1000;
+	server->acdirmax = (data->acdirmax * HZ) / 1000;
 
 	server->port = data->nfs_server.port;
 

Index: linux-2.6/fs/nfs/super.c
===================================================================

fs/nfs/super.c +20 -8
@@ -53,6 +53,7 @@
 #include <linux/nfs_xdr.h>
 #include <linux/magic.h>
 #include <linux/parser.h>
+#include <linux/ctype.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -558,14 +559,14 @@
 	if (nfss->bsize != 0)
 		seq_printf(m, ",bsize=%u", nfss->bsize);
 	seq_printf(m, ",namlen=%u", nfss->namelen);
-	if (nfss->acregmin != NFS_DEF_ACREGMIN*HZ || showdefaults)
-		seq_printf(m, ",acregmin=%u", nfss->acregmin/HZ);
-	if (nfss->acregmax != NFS_DEF_ACREGMAX*HZ || showdefaults)
-		seq_printf(m, ",acregmax=%u", nfss->acregmax/HZ);
-	if (nfss->acdirmin != NFS_DEF_ACDIRMIN*HZ || showdefaults)
-		seq_printf(m, ",acdirmin=%u", nfss->acdirmin/HZ);
-	if (nfss->acdirmax != NFS_DEF_ACDIRMAX*HZ || showdefaults)
-		seq_printf(m, ",acdirmax=%u", nfss->acdirmax/HZ);
+	if (nfss->acregmin != (NFS_DEF_ACREGMIN * HZ) / 1000 || showdefaults)
+		seq_printf(m, ",acregmin=%u", (nfss->acregmin * 1000) / HZ);
+	if (nfss->acregmax != (NFS_DEF_ACREGMAX * HZ) / 1000 || showdefaults)
+		seq_printf(m, ",acregmax=%u", (nfss->acregmax * 1000) / HZ);
+	if (nfss->acdirmin != (NFS_DEF_ACDIRMIN * HZ) / 1000 || showdefaults)
+		seq_printf(m, ",acdirmin=%u", (nfss->acdirmin * 1000) / HZ);
+	if (nfss->acdirmax != (NFS_DEF_ACDIRMAX * HZ) / 1000 || showdefaults)
+		seq_printf(m, ",acdirmax=%u", (nfss->acdirmax * 1000) / HZ);
 	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
 		if (nfss->flags & nfs_infop->flag)
 			seq_puts(m, nfs_infop->str);
@@ -967,6 +968,43 @@
 }
 
 /*
+ * Parse the input string for unit. Return the value which when
+ * multiplied with the user input yields millisecond resolution.
+ *
+ * If user does not specify any unit, it is defaulted to seconds.
+ */
+static unsigned int nfs_match_unit(char *string)
+{
+	unsigned int len = strlen(string);
+
+	if (len < 3)
+		return 1000;

fs/nfs/super.c line 991

Quoted 10 lines
fs/nfs/super.c +10 -0
+
+	string = string + len - 2;
+
+	if (isdigit(*string))
+		return 1000;
+
+	if (!strcmp(string, "se")) {
+		*string = '\0';
+		return 1000;
+	}

"se" isn't a very common notation for seconds. It would probably be better to drop the "e" and allow people to specify "3s" instead.

Quoted 140 lines
fs/nfs/super.c +35 -13
+	if (!strcmp(string, "ms")) {
+		*string = '\0';
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * This converts the user value in millisecond resolution.
+ */
+static inline unsigned long nfs_convert_unit(unsigned int unit, unsigned long option)
+{
+	return unit * option;
+}
+
+/*
  * Error-check and convert a string of mount options from user space into
  * a data structure.  The whole mount string is processed; bad options are
  * skipped as they are encountered.  If there were no errors, return 1;
@@ -1003,6 +1041,7 @@
 		unsigned long option;
 		int int_option;
 		int token;
+		unsigned int unit;
 
 		if (!*p)
 			continue;
@@ -1174,52 +1213,57 @@
 			string = match_strdup(args);
 			if (string == NULL)
 				goto out_nomem;
+			unit = nfs_match_unit(string);
 			rc = strict_strtoul(string, 10, &option);
 			kfree(string);
 			if (rc != 0)
 				goto out_invalid_value;
-			mnt->acregmin = option;
+			mnt->acregmin = nfs_convert_unit(option, unit);
 			break;
 		case Opt_acregmax:
 			string = match_strdup(args);
 			if (string == NULL)
 				goto out_nomem;
+			unit = nfs_match_unit(string);
 			rc = strict_strtoul(string, 10, &option);
 			kfree(string);
 			if (rc != 0)
 				goto out_invalid_value;
-			mnt->acregmax = option;
+			mnt->acregmax = nfs_convert_unit(option, unit);
 			break;
 		case Opt_acdirmin:
 			string = match_strdup(args);
 			if (string == NULL)
 				goto out_nomem;
+			unit = nfs_match_unit(string);
 			rc = strict_strtoul(string, 10, &option);
 			kfree(string);
 			if (rc != 0)
 				goto out_invalid_value;
-			mnt->acdirmin = option;
+			mnt->acdirmin = nfs_convert_unit(option, unit);
 			break;
 		case Opt_acdirmax:
 			string = match_strdup(args);
 			if (string == NULL)
 				goto out_nomem;
+			unit = nfs_match_unit(string);
 			rc = strict_strtoul(string, 10, &option);
 			kfree(string);
 			if (rc != 0)
 				goto out_invalid_value;
-			mnt->acdirmax = option;
+			mnt->acdirmax = nfs_convert_unit(option, unit);
 			break;
 		case Opt_actimeo:
 			string = match_strdup(args);
 			if (string == NULL)
 				goto out_nomem;
+			unit = nfs_match_unit(string);
 			rc = strict_strtoul(string, 10, &option);
 			kfree(string);
 			if (rc != 0)
 				goto out_invalid_value;
 			mnt->acregmin = mnt->acregmax =
-			mnt->acdirmin = mnt->acdirmax = option;
+			mnt->acdirmin = mnt->acdirmax = nfs_convert_unit(option, unit);
 			break;
 		case Opt_namelen:
 			string = match_strdup(args);
@@ -1715,10 +1759,10 @@
 		args->wsize		= data->wsize;
 		args->timeo		= data->timeo;
 		args->retrans		= data->retrans;
-		args->acregmin		= data->acregmin;
-		args->acregmax		= data->acregmax;
-		args->acdirmin		= data->acdirmin;
-		args->acdirmax		= data->acdirmax;
+		args->acregmin		= data->acregmin * 1000;
+		args->acregmax		= data->acregmax * 1000;
+		args->acdirmin		= data->acdirmin * 1000;
+		args->acdirmax		= data->acdirmax * 1000;
 
 		memcpy(&args->nfs_server.address, &data->addr,
 		       sizeof(data->addr));
@@ -2391,10 +2435,10 @@
 		args->wsize	= data->wsize;
 		args->timeo	= data->timeo;
 		args->retrans	= data->retrans;
-		args->acregmin	= data->acregmin;
-		args->acregmax	= data->acregmax;
-		args->acdirmin	= data->acdirmin;
-		args->acdirmax	= data->acdirmax;
+		args->acregmin	= data->acregmin * 1000;
+		args->acregmax	= data->acregmax * 1000;
+		args->acdirmin	= data->acdirmin * 1000;
+		args->acdirmax	= data->acdirmax * 1000;
 		args->nfs_server.protocol = data->proto;
 		nfs_validate_transport_protocol(args);
 

Index: linux-2.6/include/linux/nfs_fs.h
===================================================================

include/linux/nfs_fs.h +4 -4
@@ -20,10 +20,10 @@
 #define NFS_MAX_UDP_TIMEOUT	(60*HZ)
 #define NFS_MAX_TCP_TIMEOUT	(600*HZ)
 
-#define NFS_DEF_ACREGMIN	(3)
-#define NFS_DEF_ACREGMAX	(60)
-#define NFS_DEF_ACDIRMIN	(30)
-#define NFS_DEF_ACDIRMAX	(60)
+#define NFS_DEF_ACREGMIN	(3000)
+#define NFS_DEF_ACREGMAX	(60000)
+#define NFS_DEF_ACDIRMIN	(30000)
+#define NFS_DEF_ACDIRMAX	(60000)
 
 /*
  * When flushing a cluster of dirty pages, there can be different
Signature · 1 line
Jeff Layton <[email protected]>