Re: [PATCH - nfs-utils] Make sure statd gets started when 'string options' are in use.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On May 7, 2008, at 10:48 PM, Neil Brown wrote:
On Tuesday May 6, chuck.lever@xxxxxxxxxx wrote:
On May 6, 2008, at 12:38 AM, Neil Brown wrote:
The code for checking and starting statd was only in the binary-
options
branch of the code.
This moves it into common code.
---
utils/mount/mount.c    |   22 ++++++++++++++++++++--
utils/mount/nfsmount.c |   11 -----------
2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/utils/mount/mount.c b/utils/mount/mount.c
index 5076468..0036caa 100644
--- a/utils/mount/mount.c
+++ b/utils/mount/mount.c
@@ -334,7 +334,8 @@ static void parse_opt(const char *opt, int
*mask, char *extra_opts, int len)
* standard options (indicated by MS_ bits), and output parameter
* "@extra_opts" gets all the filesystem-specific options.
*/
-static void parse_opts(const char *options, int *flags, char
**extra_opts)
+static void parse_opts(const char *options, int *flags, char
**extra_opts,
+		       int *lock)
{
	if (options != NULL) {
		char *opts = xstrdup(options);
@@ -358,6 +359,10 @@ static void parse_opts(const char *options, int
*flags, char **extra_opts)
			/* end of option item or last item */
			if (*p == '\0' || *(p + 1) == '\0') {
				parse_opt(opt, flags, *extra_opts, len);
+				if (strcmp(opt, "lock") == 0)
+					*lock = 1;
+				if (strcmp(opt, "nolock") == 0)
+					*lock = 0;
				opt = NULL;
			}
		}
@@ -421,6 +426,7 @@ int main(int argc, char *argv[])
	char *spec, *mount_point, *fs_type = "nfs";
	char *extra_opts = NULL, *mount_opts = NULL;
	uid_t uid = getuid();
+	int lock = 1;

	progname = basename(argv[0]);

@@ -531,7 +537,7 @@ int main(int argc, char *argv[])
		goto out;
	}

-	parse_opts(mount_opts, &flags, &extra_opts);
+	parse_opts(mount_opts, &flags, &extra_opts, &lock);

	if (uid != 0) {
		if (!(flags & (MS_USERS|MS_USER))) {
@@ -546,6 +552,18 @@ int main(int argc, char *argv[])
		goto out;
	}

+	if (!fake && lock) {
+		if (!start_statd()) {
+			nfs_error(_("%s: rpc.statd is not running but is "
+				"required for remote locking.\n"
+				"   Either use '-o nolock' to keep "
+				"locks local, or start statd."),
+					progname);
+			mnt_err = EX_FAIL;
+			goto out;
+		}
+	}
+

You probably want to gate this based on NFS version (ie do the
checking only for NFSv2/v3 mounts, and not for NFSv4 mounts)

Yes, of course :-(
I remember think about that but must have forgotten when I actually
cut the patch.


There is already a function in stropts.c (called
set_mandatory_options) that might be a better place to put the special option parsing, as you can use the nice po_* calls, and it already has
a switch for detecting which NFS version is being requested.

I cannot bring myself to put code in a function called
"set_mandatory_options" which does not, in fact, set any options,
whether mandatory or not.

/me makes the Scooby noise... (or is it the Tim Allen noise?)

Huh? set_mandatory_options sets up both "addr=" and "clientaddr=". Both of these are required by the kernel, thus they are mandatory options. So I don't understand your objection.

That function is the designated place to do specific option processing, and even has a specific check for which type of file system is being mounted. Your fix would be simpler (it would add less redundant logic) if it were added in set_mandatory_options().

It's easy enough to change the name of the function if you think that would help make it more clear.

Since the common part of this code (start_statd) is already in a
helper, I would leave the existing logic in nfsmount.c, and just add a handful of lines in stropts.c:set_mandatory_options that worries about
"lock/nolock" for NFSv2/v3 mounts.

So how about the following?

Thanks for the feedback.

NeilBrown

diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index cdd610e..be77d17 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -694,6 +694,17 @@ int nfsmount_string(const char *spec, const char *node, const char *type,
	if (!set_mandatory_options(type, &saddr, options))
		goto out;

+	if (!fake && strcmp(type, "nfs4") != 0 &&
+	    po_rightmost(options, "nolock", "lock") != PO_KEY1_RIGHTMOST)
+		if (!start_statd()) {
+			nfs_error(_("%s: rpc.statd is not running but is "
+				    "required for remote locking.\n"
+				    "   Either use '-o nolock' to keep "
+				    "locks local, or start statd."),
+				  progname);
+			goto out;
+		}
+
	if (po_rightmost(options, "bg", "fg") == PO_KEY1_RIGHTMOST)
		retval = nfsmount_bg(spec, node, type, hostname, flags,
					options, fake, child, extra_opts);

That's much closer to what I was thinking of. But again, this belongs in set_mandatory_options() (or whatever we want to call the function).

It may seem like I'm splitting hairs, but the whole point of nfsmount_string() is to split the incoming mount option string into an easy-to-parse data structure, then pass the data structure to helpers to do the actual work. The nfsmount_string() function is meant to be free of logic that is specific to a file system type or specific to a particular mount option (even fg/bg should be moved to a helper... I think I will construct a patch to do that right now).

The point is to keep each of these functions simple; they should all operate at the same level of detail, and encapsulate just a few important decisions at that level.

nfsmount_string() is meant to be the "35,000 foot" entry point. Other functions, like parse_devname(), are meant to handle simple string manipulation. Combining dissimilar levels of detail is like a layering violation, and then over time we end up with unmaintainable logic such as today's nfsmount.c, which attempts to do nearly everything in a single giant function.

NFS mounting is so subtle and exception filled it is worth taking a few moments to factor this correctly.

--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux