]> err.no Git - linux-2.6/blobdiff - fs/nfs/super.c
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[linux-2.6] / fs / nfs / super.c
index 041fe9e9b74d872587578c69f2198c265cc605de..7f4505f6ac6f55fd49c1a8c07bbb65ce63d41388 100644 (file)
@@ -448,7 +448,6 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                const char *nostr;
        } nfs_info[] = {
                { NFS_MOUNT_SOFT, ",soft", ",hard" },
-               { NFS_MOUNT_INTR, ",intr", ",nointr" },
                { NFS_MOUNT_NOCTO, ",nocto", "" },
                { NFS_MOUNT_NOAC, ",noac", "" },
                { NFS_MOUNT_NONLM, ",nolock", "" },
@@ -479,8 +478,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
        }
        seq_printf(m, ",proto=%s",
                   rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO));
-       seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ);
-       seq_printf(m, ",retrans=%u", clp->retrans_count);
+       seq_printf(m, ",timeo=%lu", 10U * nfss->client->cl_timeout->to_initval / HZ);
+       seq_printf(m, ",retrans=%u", nfss->client->cl_timeout->to_retries);
        seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
 }
 
@@ -649,15 +648,29 @@ static int nfs_verify_server_address(struct sockaddr *addr)
  * to punt the mount.
  */
 static void nfs_parse_server_address(char *value,
-                                    struct sockaddr *sap)
+                                    struct sockaddr *sap,
+                                    size_t *len)
 {
-       struct sockaddr_in *ap = (void *)sap;
+       if (strchr(value, ':')) {
+               struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
+               u8 *addr = (u8 *)&ap->sin6_addr.in6_u;
 
-       ap->sin_family = AF_INET;
-       if (in4_pton(value, -1, (u8 *)&ap->sin_addr.s_addr, '\0', NULL))
-               return;
+               ap->sin6_family = AF_INET6;
+               *len = sizeof(*ap);
+               if (in6_pton(value, -1, addr, '\0', NULL))
+                       return;
+       } else {
+               struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+               u8 *addr = (u8 *)&ap->sin_addr.s_addr;
+
+               ap->sin_family = AF_INET;
+               *len = sizeof(*ap);
+               if (in4_pton(value, -1, addr, '\0', NULL))
+                       return;
+       }
 
        sap->sa_family = AF_UNSPEC;
+       *len = 0;
 }
 
 /*
@@ -694,10 +707,7 @@ static int nfs_parse_mount_options(char *raw,
                        mnt->flags &= ~NFS_MOUNT_SOFT;
                        break;
                case Opt_intr:
-                       mnt->flags |= NFS_MOUNT_INTR;
-                       break;
                case Opt_nointr:
-                       mnt->flags &= ~NFS_MOUNT_INTR;
                        break;
                case Opt_posix:
                        mnt->flags |= NFS_MOUNT_POSIX;
@@ -984,19 +994,22 @@ static int nfs_parse_mount_options(char *raw,
                        if (string == NULL)
                                goto out_nomem;
                        nfs_parse_server_address(string, (struct sockaddr *)
-                                                &mnt->nfs_server.address);
+                                                &mnt->nfs_server.address,
+                                                &mnt->nfs_server.addrlen);
                        kfree(string);
                        break;
                case Opt_clientaddr:
                        string = match_strdup(args);
                        if (string == NULL)
                                goto out_nomem;
+                       kfree(mnt->client_address);
                        mnt->client_address = string;
                        break;
                case Opt_mounthost:
                        string = match_strdup(args);
                        if (string == NULL)
                                goto out_nomem;
+                       kfree(mnt->mount_server.hostname);
                        mnt->mount_server.hostname = string;
                        break;
                case Opt_mountaddr:
@@ -1004,7 +1017,8 @@ static int nfs_parse_mount_options(char *raw,
                        if (string == NULL)
                                goto out_nomem;
                        nfs_parse_server_address(string, (struct sockaddr *)
-                                                &mnt->mount_server.address);
+                                                &mnt->mount_server.address,
+                                                &mnt->mount_server.addrlen);
                        kfree(string);
                        break;
 
@@ -1049,9 +1063,9 @@ out_unknown:
 static int nfs_try_mount(struct nfs_parsed_mount_data *args,
                         struct nfs_fh *root_fh)
 {
-       struct sockaddr_in sin;
-       int status;
+       struct sockaddr *sap = (struct sockaddr *)&args->mount_server.address;
        char *hostname;
+       int status;
 
        if (args->mount_server.version == 0) {
                if (args->flags & NFS_MOUNT_VER3)
@@ -1068,21 +1082,23 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
        /*
         * Construct the mount server's address.
         */
-       if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY)
-               sin = args->mount_server.address;
-       else
-               sin = args->nfs_server.address;
+       if (args->mount_server.address.ss_family == AF_UNSPEC) {
+               memcpy(sap, &args->nfs_server.address,
+                      args->nfs_server.addrlen);
+               args->mount_server.addrlen = args->nfs_server.addrlen;
+       }
+
        /*
         * autobind will be used if mount_server.port == 0
         */
-       nfs_set_port((struct sockaddr *)&sin, args->mount_server.port);
+       nfs_set_port(sap, args->mount_server.port);
 
        /*
         * Now ask the mount server to map our export path
         * to a file handle.
         */
-       status = nfs_mount((struct sockaddr *) &sin,
-                          sizeof(sin),
+       status = nfs_mount(sap,
+                          args->mount_server.addrlen,
                           hostname,
                           args->nfs_server.export_path,
                           args->mount_server.version,
@@ -1165,9 +1181,6 @@ static int nfs_validate_mount_data(void *options,
                        memset(mntfh->data + mntfh->size, 0,
                               sizeof(mntfh->data) - mntfh->size);
 
-               if (!nfs_verify_server_address((struct sockaddr *) &data->addr))
-                       goto out_no_address;
-
                /*
                 * Translate to nfs_parsed_mount_data, which nfs_fill_super
                 * can deal with.
@@ -1182,7 +1195,14 @@ static int nfs_validate_mount_data(void *options,
                args->acregmax          = data->acregmax;
                args->acdirmin          = data->acdirmin;
                args->acdirmax          = data->acdirmax;
-               args->nfs_server.address = data->addr;
+
+               memcpy(&args->nfs_server.address, &data->addr,
+                      sizeof(data->addr));
+               args->nfs_server.addrlen = sizeof(data->addr);
+               if (!nfs_verify_server_address((struct sockaddr *)
+                                               &args->nfs_server.address))
+                       goto out_no_address;
+
                if (!(data->flags & NFS_MOUNT_TCP))
                        args->nfs_server.protocol = XPRT_TRANSPORT_UDP;
                /* N.B. caller will free nfs_server.hostname in all cases */
@@ -1655,6 +1675,7 @@ static int nfs4_validate_mount_data(void *options,
                                    struct nfs_parsed_mount_data *args,
                                    const char *dev_name)
 {
+       struct sockaddr_in *ap;
        struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
        char *c;
 
@@ -1675,11 +1696,13 @@ static int nfs4_validate_mount_data(void *options,
 
        switch (data->version) {
        case 1:
-               if (data->host_addrlen != sizeof(args->nfs_server.address))
+               ap = (struct sockaddr_in *)&args->nfs_server.address;
+               if (data->host_addrlen > sizeof(args->nfs_server.address))
+                       goto out_no_address;
+               if (data->host_addrlen == 0)
                        goto out_no_address;
-               if (copy_from_user(&args->nfs_server.address,
-                                  data->host_addr,
-                                  sizeof(args->nfs_server.address)))
+               args->nfs_server.addrlen = data->host_addrlen;
+               if (copy_from_user(ap, data->host_addr, data->host_addrlen))
                        return -EFAULT;
                if (!nfs_verify_server_address((struct sockaddr *)
                                                &args->nfs_server.address))