]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'nfs-for-3.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Apr 2013 18:28:08 +0000 (11:28 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Apr 2013 18:28:08 +0000 (11:28 -0700)
Pull NFS client bugfixes and cleanups from Trond Myklebust:

 - NLM: stable fix for NFSv2/v3 blocking locks

 - NFSv4.x: stable fixes for the delegation recall error handling code

 - NFSv4.x: Security flavour negotiation fixes and cleanups by Chuck
   Lever

 - SUNRPC: A number of RPCSEC_GSS fixes and cleanups also from Chuck

 - NFSv4.x assorted state management and reboot recovery bugfixes

 - NFSv4.1: In cases where we have already looked up a file, and hold a
   valid filehandle, use the new open-by-filehandle operation instead of
   opening by name.

 - Allow the NFSv4.1 callback thread to freeze

 - NFSv4.x: ensure that file unlock waits for readahead to complete

 - NFSv4.1: ensure that the RPC layer doesn't override the NFS session
   table size negotiation by limiting the number of slots.

 - NFSv4.x: Fix SETATTR spec compatibility issues

* tag 'nfs-for-3.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (67 commits)
  NFSv4: Warn once about servers that incorrectly apply open mode to setattr
  NFSv4: Servers should only check SETATTR stateid open mode on size change
  NFSv4: Don't recheck permissions on open in case of recovery cached open
  NFSv4.1: Don't do a delegated open for NFS4_OPEN_CLAIM_DELEG_CUR_FH modes
  NFSv4.1: Use the more efficient open_noattr call for open-by-filehandle
  NFS: Retry SETCLIENTID with AUTH_SYS instead of AUTH_NONE
  NFSv4: Ensure that we clear the NFS_OPEN_STATE flag when appropriate
  LOCKD: Ensure that nlmclnt_block resets block->b_status after a server reboot
  NFSv4: Ensure the LOCK call cannot use the delegation stateid
  NFSv4: Use the open stateid if the delegation has the wrong mode
  nfs: Send atime and mtime as a 64bit value
  NFSv4: Record the OPEN create mode used in the nfs4_opendata structure
  NFSv4.1: Set the RPC_CLNT_CREATE_INFINITE_SLOTS flag for NFSv4.1 transports
  SUNRPC: Allow rpc_create() to request that TCP slots be unlimited
  SUNRPC: Fix a livelock problem in the xprt->backlog queue
  NFSv4: Fix handling of revoked delegations by setattr
  NFSv4 release the sequence id in the return on close case
  nfs: remove unnecessary check for NULL inode->i_flock from nfs_delegation_claim_locks
  NFS: Ensure that NFS file unlock waits for readahead to complete
  NFS: Add functionality to allow waiting on all outstanding reads to complete
  ...

1  2 
fs/nfs/super.c
fs/nfsd/nfs4xdr.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/xprtsock.c

diff --combined fs/nfs/super.c
index 2f8a29db0f1bed59a8300d64038ebe4404d611a6,3bb8318f6d0c21c9864266ebc0506147d7492f2f..eb494f6a4c6bcf3671cbd87df52c68776a94b2ab
@@@ -294,7 -294,6 +294,7 @@@ struct file_system_type nfs_fs_type = 
        .kill_sb        = nfs_kill_super,
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
  };
 +MODULE_ALIAS_FS("nfs");
  EXPORT_SYMBOL_GPL(nfs_fs_type);
  
  struct file_system_type nfs_xdev_fs_type = {
@@@ -334,8 -333,6 +334,8 @@@ struct file_system_type nfs4_fs_type = 
        .kill_sb        = nfs_kill_super,
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
  };
 +MODULE_ALIAS_FS("nfs4");
 +MODULE_ALIAS("nfs4");
  EXPORT_SYMBOL_GPL(nfs4_fs_type);
  
  static int __init register_nfs4_fs(void)
@@@ -920,7 -917,7 +920,7 @@@ static struct nfs_parsed_mount_data *nf
                data->mount_server.port = NFS_UNSPEC_PORT;
                data->nfs_server.port   = NFS_UNSPEC_PORT;
                data->nfs_server.protocol = XPRT_TRANSPORT_TCP;
-               data->auth_flavors[0]   = RPC_AUTH_UNIX;
+               data->auth_flavors[0]   = RPC_AUTH_MAXFLAVOR;
                data->auth_flavor_len   = 1;
                data->minorversion      = 0;
                data->need_mount        = true;
@@@ -1608,49 -1605,57 +1608,57 @@@ out_security_failure
  }
  
  /*
-  * Match the requested auth flavors with the list returned by
-  * the server.  Returns zero and sets the mount's authentication
-  * flavor on success; returns -EACCES if server does not support
-  * the requested flavor.
+  * Select a security flavor for this mount.  The selected flavor
+  * is planted in args->auth_flavors[0].
   */
- static int nfs_walk_authlist(struct nfs_parsed_mount_data *args,
-                            struct nfs_mount_request *request)
+ static void nfs_select_flavor(struct nfs_parsed_mount_data *args,
+                             struct nfs_mount_request *request)
  {
-       unsigned int i, j, server_authlist_len = *(request->auth_flav_len);
+       unsigned int i, count = *(request->auth_flav_len);
+       rpc_authflavor_t flavor;
+       if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR)
+               goto out;
+       /*
+        * The NFSv2 MNT operation does not return a flavor list.
+        */
+       if (args->mount_server.version != NFS_MNT3_VERSION)
+               goto out_default;
  
        /*
         * Certain releases of Linux's mountd return an empty
-        * flavor list.  To prevent behavioral regression with
-        * these servers (ie. rejecting mounts that used to
-        * succeed), revert to pre-2.6.32 behavior (no checking)
-        * if the returned flavor list is empty.
+        * flavor list in some cases.
         */
-       if (server_authlist_len == 0)
-               return 0;
+       if (count == 0)
+               goto out_default;
  
        /*
-        * We avoid sophisticated negotiating here, as there are
-        * plenty of cases where we can get it wrong, providing
-        * either too little or too much security.
-        *
         * RFC 2623, section 2.7 suggests we SHOULD prefer the
         * flavor listed first.  However, some servers list
-        * AUTH_NULL first.  Our caller plants AUTH_SYS, the
-        * preferred default, in args->auth_flavors[0] if user
-        * didn't specify sec= mount option.
+        * AUTH_NULL first.  Avoid ever choosing AUTH_NULL.
         */
-       for (i = 0; i < args->auth_flavor_len; i++)
-               for (j = 0; j < server_authlist_len; j++)
-                       if (args->auth_flavors[i] == request->auth_flavs[j]) {
-                               dfprintk(MOUNT, "NFS: using auth flavor %d\n",
-                                       request->auth_flavs[j]);
-                               args->auth_flavors[0] = request->auth_flavs[j];
-                               return 0;
-                       }
+       for (i = 0; i < count; i++) {
+               struct rpcsec_gss_info info;
+               flavor = request->auth_flavs[i];
+               switch (flavor) {
+               case RPC_AUTH_UNIX:
+                       goto out_set;
+               case RPC_AUTH_NULL:
+                       continue;
+               default:
+                       if (rpcauth_get_gssinfo(flavor, &info) == 0)
+                               goto out_set;
+               }
+       }
  
-       dfprintk(MOUNT, "NFS: server does not support requested auth flavor\n");
-       nfs_umount(request);
-       return -EACCES;
+ out_default:
+       flavor = RPC_AUTH_UNIX;
+ out_set:
+       args->auth_flavors[0] = flavor;
+ out:
+       dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]);
  }
  
  /*
@@@ -1713,12 -1718,8 +1721,8 @@@ static int nfs_request_mount(struct nfs
                return status;
        }
  
-       /*
-        * MNTv1 (NFSv2) does not support auth flavor negotiation.
-        */
-       if (args->mount_server.version != NFS_MNT3_VERSION)
-               return 0;
-       return nfs_walk_authlist(args, &request);
+       nfs_select_flavor(args, &request);
+       return 0;
  }
  
  struct dentry *nfs_try_mount(int flags, const char *dev_name,
@@@ -2720,5 -2721,6 +2724,5 @@@ module_param(send_implementation_id, us
  MODULE_PARM_DESC(send_implementation_id,
                "Send implementation ID with NFSv4.1 exchange_id");
  MODULE_PARM_DESC(nfs4_unique_id, "nfs_client_id4 uniquifier string");
 -MODULE_ALIAS("nfs4");
  
  #endif /* CONFIG_NFS_V4 */
diff --combined fs/nfsd/nfs4xdr.c
index a2720071f282f7607f13d63af8d6e9d6cf18bce6,2a2745615b42622d39aa6532e03ce47198e68298..2502951714b1d5826727b37f7566462d4bda6840
@@@ -264,7 -264,7 +264,7 @@@ nfsd4_decode_fattr(struct nfsd4_compoun
                iattr->ia_valid |= ATTR_SIZE;
        }
        if (bmval[0] & FATTR4_WORD0_ACL) {
 -              int nace;
 +              u32 nace;
                struct nfs4_ace *ace;
  
                READ_BUF(4); len += 4;
@@@ -3138,10 -3138,9 +3138,9 @@@ nfsd4_encode_rename(struct nfsd4_compou
  
  static __be32
  nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp,
-                        __be32 nfserr,struct svc_export *exp)
+                        __be32 nfserr, struct svc_export *exp)
  {
-       int i = 0;
-       u32 nflavs;
+       u32 i, nflavs;
        struct exp_flavor_info *flavs;
        struct exp_flavor_info def_flavs[2];
        __be32 *p;
        WRITE32(nflavs);
        ADJUST_ARGS();
        for (i = 0; i < nflavs; i++) {
-               u32 flav = flavs[i].pseudoflavor;
-               struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
+               struct rpcsec_gss_info info;
  
-               if (gm) {
+               if (rpcauth_get_gssinfo(flavs[i].pseudoflavor, &info) == 0) {
                        RESERVE_SPACE(4);
                        WRITE32(RPC_AUTH_GSS);
                        ADJUST_ARGS();
-                       RESERVE_SPACE(4 + gm->gm_oid.len);
-                       WRITE32(gm->gm_oid.len);
-                       WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
+                       RESERVE_SPACE(4 + info.oid.len);
+                       WRITE32(info.oid.len);
+                       WRITEMEM(info.oid.data, info.oid.len);
                        ADJUST_ARGS();
                        RESERVE_SPACE(4);
-                       WRITE32(0); /* qop */
+                       WRITE32(info.qop);
                        ADJUST_ARGS();
                        RESERVE_SPACE(4);
-                       WRITE32(gss_pseudoflavor_to_service(gm, flav));
+                       WRITE32(info.service);
                        ADJUST_ARGS();
-                       gss_mech_put(gm);
                } else {
                        RESERVE_SPACE(4);
-                       WRITE32(flav);
+                       WRITE32(flavs[i].pseudoflavor);
                        ADJUST_ARGS();
                }
        }
  out:
        if (exp)
                exp_put(exp);
index 5ead60550895f848ba2348bba3bbbfc50ddea7ea,74f6d30f5ded099ab2e7aff2aded244cf0c30e26..c3ba570222dcbdeff872dc099ac3e6c38ea17ab5
@@@ -447,21 -447,17 +447,21 @@@ static int rsc_parse(struct cache_detai
        else {
                int N, i;
  
 +              /*
 +               * NOTE: we skip uid_valid()/gid_valid() checks here:
 +               * instead, * -1 id's are later mapped to the
 +               * (export-specific) anonymous id by nfsd_setuser.
 +               *
 +               * (But supplementary gid's get no such special
 +               * treatment so are checked for validity here.)
 +               */
                /* uid */
                rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
 -              if (!uid_valid(rsci.cred.cr_uid))
 -                      goto out;
  
                /* gid */
                if (get_int(&mesg, &id))
                        goto out;
                rsci.cred.cr_gid = make_kgid(&init_user_ns, id);
 -              if (!gid_valid(rsci.cred.cr_gid))
 -                      goto out;
  
                /* number of additional gid's */
                if (get_int(&mesg, &N))
@@@ -1220,7 -1216,9 +1220,9 @@@ svcauth_gss_accept(struct svc_rqst *rqs
                svcdata->rsci = rsci;
                cache_get(&rsci->h);
                rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor(
-                                       rsci->mechctx->mech_type, gc->gc_svc);
+                                       rsci->mechctx->mech_type,
+                                       GSS_C_QOP_DEFAULT,
+                                       gc->gc_svc);
                ret = SVC_OK;
                goto out;
        }
diff --combined net/sunrpc/xprtsock.c
index 3d02130828da671066b40aa7dd769cf6a7bd4a74,726e702b7a2935265b5f0c70378229f26c6f5c38..9c2825827decfb1a0b6fd2f4a80c0cd66fe36eb7
@@@ -849,14 -849,6 +849,14 @@@ static void xs_tcp_close(struct rpc_xpr
                xs_tcp_shutdown(xprt);
  }
  
 +static void xs_local_destroy(struct rpc_xprt *xprt)
 +{
 +      xs_close(xprt);
 +      xs_free_peer_addresses(xprt);
 +      xprt_free(xprt);
 +      module_put(THIS_MODULE);
 +}
 +
  /**
   * xs_destroy - prepare to shutdown a transport
   * @xprt: doomed transport
@@@ -870,7 -862,10 +870,7 @@@ static void xs_destroy(struct rpc_xprt 
  
        cancel_delayed_work_sync(&transport->connect_worker);
  
 -      xs_close(xprt);
 -      xs_free_peer_addresses(xprt);
 -      xprt_free(xprt);
 -      module_put(THIS_MODULE);
 +      xs_local_destroy(xprt);
  }
  
  static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
@@@ -2207,10 -2202,6 +2207,6 @@@ static void xs_tcp_setup_socket(struct 
                 */
                xs_tcp_force_close(xprt);
                break;
-       case -ECONNREFUSED:
-       case -ECONNRESET:
-       case -ENETUNREACH:
-               /* retry with existing socket, after a delay */
        case 0:
        case -EINPROGRESS:
        case -EALREADY:
                /* Happens, for instance, if the user specified a link
                 * local IPv6 address without a scope-id.
                 */
+       case -ECONNREFUSED:
+       case -ECONNRESET:
+       case -ENETUNREACH:
+               /* retry with existing socket, after a delay */
                goto out;
        }
  out_eagain:
@@@ -2487,7 -2482,7 +2487,7 @@@ static struct rpc_xprt_ops xs_local_op
        .send_request           = xs_local_send_request,
        .set_retrans_timeout    = xprt_set_retrans_timeout_def,
        .close                  = xs_close,
 -      .destroy                = xs_destroy,
 +      .destroy                = xs_local_destroy,
        .print_stats            = xs_local_print_stats,
  };
  
@@@ -2767,9 -2762,13 +2767,13 @@@ static struct rpc_xprt *xs_setup_tcp(st
        struct rpc_xprt *xprt;
        struct sock_xprt *transport;
        struct rpc_xprt *ret;
+       unsigned int max_slot_table_size = xprt_max_tcp_slot_table_entries;
+       if (args->flags & XPRT_CREATE_INFINITE_SLOTS)
+               max_slot_table_size = RPC_MAX_SLOT_TABLE_LIMIT;
  
        xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
-                       xprt_max_tcp_slot_table_entries);
+                       max_slot_table_size);
        if (IS_ERR(xprt))
                return xprt;
        transport = container_of(xprt, struct sock_xprt, xprt);