2012/11/16 Jeff Layton <[email protected]>:
> This should fix a regression that was introduced when the new mount
> option parser went in. Also, when the unc= and prefixpath= options
> are provided, check their values against the ones we parsed from
> the device string. If they differ, then throw a warning that tells
> the user that we're using the values from the unc= option for now,
> but that that will change in 3.10.
>
> Signed-off-by: Jeff Layton <[email protected]>
> ---
> fs/cifs/connect.c | 95
> +++++++++++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 88 insertions(+), 7 deletions(-)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index b1f352a..b9f3dd7 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -1090,6 +1090,52 @@ cifs_parse_smb_version(char *value, struct smb_vol
> *vol)
> return 0;
> }
>
> +/*
> + * Parse a devname into substrings and populate the vol->UNC and vol->prepath
> + * fields with the result. Returns 0 on success and an error otherwise.
> + */
> +static int
> +cifs_parse_devname(const char *devname, struct smb_vol *vol)
> +{
> + char *pos;
> + const char *delims = "/\\";
> + size_t len;
> +
> + /* make sure we have a valid UNC double delimiter prefix */
> + len = strspn(devname, delims);
> + if (len != 2)
> + return -EINVAL;
> +
> + /* find delimiter between host and sharename */
> + pos = strpbrk(devname + 2, delims);
> + if (!pos)
> + return -EINVAL;
> +
> + /* skip past delimiter */
> + ++pos;
> +
> + /* now go until next delimiter or end of string */
> + len = strcspn(pos, delims);
> +
> + /* move "pos" up to delimiter or NULL */
> + pos += len;
> + vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
> + if (!vol->UNC)
> + return -ENOMEM;
> +
> + convert_delimiter(vol->UNC, '\\');
> +
> + /* If pos is NULL, or is a bogus trailing delimiter then no prepath */
> + if (!*pos++ || !*pos)
> + return 0;
> +
> + vol->prepath = kstrdup(pos, GFP_KERNEL);
> + if (!vol->prepath)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> static int
> cifs_parse_mount_options(const char *mountdata, const char *devname,
> struct smb_vol *vol)
> @@ -1172,6 +1218,16 @@ cifs_parse_mount_options(const char *mountdata, const
> char *devname,
> vol->backupuid_specified = false; /* no backup intent for a user */
> vol->backupgid_specified = false; /* no backup intent for a group */
>
> + /*
> + * For now, we ignore -EINVAL errors under the assumption that the
> + * unc= and prefixpath= options will be usable.
> + */
> + if (cifs_parse_devname(devname, vol) == -ENOMEM) {
> + printk(KERN_ERR "CIFS: Unable to allocate memory to parse "
> + "device string.\n");
> + goto out_nomem;
> + }
> +
> while ((data = strsep(&options, separator)) != NULL) {
> substring_t args[MAX_OPT_ARGS];
> unsigned long option;
> @@ -1557,18 +1613,31 @@ cifs_parse_mount_options(const char *mountdata, const
> char *devname,
> got_ip = true;
> break;
> case Opt_unc:
> - kfree(vol->UNC);
> + string = vol->UNC;
> vol->UNC = match_strdup(args);
> - if (vol->UNC == NULL)
> + if (vol->UNC == NULL) {
> + kfree(string);
> goto out_nomem;
> + }
>
> convert_delimiter(vol->UNC, '\\');
> if (vol->UNC[0] != '\\' || vol->UNC[1] != '\\') {
> - printk(KERN_WARNING "CIFS: UNC Path does not "
> + kfree(string);
> + printk(KERN_ERR "CIFS: UNC Path does not "
> "begin with // or \\\\\n");
> goto cifs_parse_mount_err;
> }
>
> + /* Compare old unc= option to new one */
> + if (!string || strcmp(string, vol->UNC))
> + printk(KERN_WARNING "CIFS: the value of the "
> + "unc= mount option does not match the
> "
> + "device string. Using the unc= option
> "
> + "for now. In 3.10, that option will "
> + "be ignored and the contents of the "
> + "device string will be used "
> + "instead. (%s != %s)\n", string,
> + vol->UNC);
If someone specifies a devname and two unc= options (all are
different) so, it will see this message twice?
> break;
> case Opt_domain:
> string = match_strdup(args);
> @@ -1607,10 +1676,22 @@ cifs_parse_mount_options(const char *mountdata, const
> char *devname,
> if (*args[0].from == '/' || *args[0].from == '\\')
> args[0].from++;
>
> - kfree(vol->prepath);
> + string = vol->prepath;
> vol->prepath = match_strdup(args);
> - if (vol->prepath == NULL)
> + if (vol->prepath == NULL) {
> + kfree(string);
> goto out_nomem;
> + }
> + /* Compare old prefixpath= option to new one */
> + if (!string || strcmp(string, vol->prepath))
> + printk(KERN_WARNING "CIFS: the value of the "
> + "prefixpath= mount option does not "
> + "match the device string. Using the "
> + "prefixpath= option for now. In 3.10,
> "
> + "that option will be ignored and the "
> + "contents of the device string will
> be "
> + "used instead.(%s != %s)\n", string,
> + vol->prepath);
> break;
> case Opt_iocharset:
> string = match_strdup(args);
> @@ -1768,8 +1849,8 @@ cifs_parse_mount_options(const char *mountdata, const
> char *devname,
> }
> #endif
> if (!vol->UNC) {
> - cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
> - "unc=\\\\192.168.1.100\\public) specified");
> + cERROR(1, "CIFS mount error: No usable UNC path provided in "
> + "device string or in unc= option!");
> goto cifs_parse_mount_err;
> }
>
> --
> 1.7.11.7
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html