]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-3.14' of git://linux-nfs.org/~bfields/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 30 Jan 2014 18:18:43 +0000 (10:18 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 30 Jan 2014 18:18:43 +0000 (10:18 -0800)
Pull nfsd updates from Bruce Fields:
 - Handle some loose ends from the vfs read delegation support.
   (For example nfsd can stop breaking leases on its own in a
    fewer places where it can now depend on the vfs to.)
 - Make life a little easier for NFSv4-only configurations
   (thanks to Kinglong Mee).
 - Fix some gss-proxy problems (thanks Jeff Layton).
 - miscellaneous bug fixes and cleanup

* 'for-3.14' of git://linux-nfs.org/~bfields/linux: (38 commits)
  nfsd: consider CLAIM_FH when handing out delegation
  nfsd4: fix delegation-unlink/rename race
  nfsd4: delay setting current_fh in open
  nfsd4: minor nfs4_setlease cleanup
  gss_krb5: use lcm from kernel lib
  nfsd4: decrease nfsd4_encode_fattr stack usage
  nfsd: fix encode_entryplus_baggage stack usage
  nfsd4: simplify xdr encoding of nfsv4 names
  nfsd4: encode_rdattr_error cleanup
  nfsd4: nfsd4_encode_fattr cleanup
  minor svcauth_gss.c cleanup
  nfsd4: better VERIFY comment
  nfsd4: break only delegations when appropriate
  NFSD: Fix a memory leak in nfsd4_create_session
  sunrpc: get rid of use_gssp_lock
  sunrpc: fix potential race between setting use_gss_proxy and the upcall rpc_clnt
  sunrpc: don't wait for write before allowing reads from use-gss-proxy file
  nfsd: get rid of unused function definition
  Define op_iattr for nfsd4_open instead using macro
  NFSD: fix compile warning without CONFIG_NFSD_V3
  ...

1  2 
fs/nfsd/acl.h
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4proc.c
fs/nfsd/vfs.c
fs/nfsd/vfs.h
net/sunrpc/cache.c
net/sunrpc/netns.h
net/sunrpc/xprtsock.c

diff --combined fs/nfsd/acl.h
index 8b68218e2c1c25c188f7585966dd9f694807e096,afd3e0eae642b903e6046b3b61e153b4ccba62bc..a812fd1b92a4593fc744606e5ae15ff128c8e2c7
@@@ -35,9 -35,7 +35,9 @@@
  #ifndef LINUX_NFS4_ACL_H
  #define LINUX_NFS4_ACL_H
  
 -#include <linux/posix_acl.h>
 +struct nfs4_acl;
 +struct svc_fh;
 +struct svc_rqst;
  
  /* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to
   * fit in a page: */
  
  struct nfs4_acl *nfs4_acl_new(int);
  int nfs4_acl_get_whotype(char *, u32);
int nfs4_acl_write_who(int who, char *p);
__be32 nfs4_acl_write_who(int who, __be32 **p, int *len);
  
 -#define NFS4_ACL_TYPE_DEFAULT 0x01
 -#define NFS4_ACL_DIR          0x02
 -#define NFS4_ACL_OWNER                0x04
 -
 -struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *,
 -                              struct posix_acl *, unsigned int flags);
 -int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *, struct posix_acl **,
 -                              struct posix_acl **, unsigned int flags);
 +int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
 +              struct nfs4_acl **acl);
 +__be32 nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
 +              struct nfs4_acl *acl);
  
  #endif /* LINUX_NFS4_ACL_H */
diff --combined fs/nfsd/nfs4acl.c
index 649ad7cf22044bb10bd6cb64527cba7295226a97,eea24c9a561d95b7dbc641b262b066c4098e2226..d3a587144222b56becd0ce82597fb95bc8767592
  #include <linux/slab.h>
  #include <linux/nfs_fs.h>
  #include <linux/export.h>
 +#include "nfsfh.h"
+ #include "nfsd.h"
  #include "acl.h"
 +#include "vfs.h"
  
 +#define NFS4_ACL_TYPE_DEFAULT 0x01
 +#define NFS4_ACL_DIR          0x02
 +#define NFS4_ACL_OWNER                0x04
  
  /* mode bit translations: */
  #define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
@@@ -135,50 -131,36 +136,50 @@@ static short ace2type(struct nfs4_ace *
  static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
                                unsigned int);
  
 -struct nfs4_acl *
 -nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
 -                      unsigned int flags)
 +int
 +nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
 +              struct nfs4_acl **acl)
  {
 -      struct nfs4_acl *acl;
 +      struct inode *inode = dentry->d_inode;
 +      int error = 0;
 +      struct posix_acl *pacl = NULL, *dpacl = NULL;
 +      unsigned int flags = 0;
        int size = 0;
  
 -      if (pacl) {
 -              if (posix_acl_valid(pacl) < 0)
 -                      return ERR_PTR(-EINVAL);
 -              size += 2*pacl->a_count;
 +      pacl = get_acl(inode, ACL_TYPE_ACCESS);
 +      if (!pacl) {
 +              pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
 +              if (IS_ERR(pacl))
 +                      return PTR_ERR(pacl);
 +              /* allocate for worst case: one (deny, allow) pair each: */
 +              size += 2 * pacl->a_count;
        }
 -      if (dpacl) {
 -              if (posix_acl_valid(dpacl) < 0)
 -                      return ERR_PTR(-EINVAL);
 -              size += 2*dpacl->a_count;
 +
 +      if (S_ISDIR(inode->i_mode)) {
 +              flags = NFS4_ACL_DIR;
 +              dpacl = get_acl(inode, ACL_TYPE_DEFAULT);
 +              if (dpacl)
 +                      size += 2 * dpacl->a_count;
 +      } else {
 +              dpacl = NULL;
        }
  
 -      /* Allocate for worst case: one (deny, allow) pair each: */
 -      acl = nfs4_acl_new(size);
 -      if (acl == NULL)
 -              return ERR_PTR(-ENOMEM);
 +      *acl = nfs4_acl_new(size);
 +      if (*acl == NULL) {
 +              error = -ENOMEM;
 +              goto out;
 +      }
  
        if (pacl)
 -              _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
 +              _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
  
        if (dpacl)
 -              _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
 +              _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT);
  
 -      return acl;
 + out:
 +      posix_acl_release(pacl);
 +      posix_acl_release(dpacl);
 +      return error;
  }
  
  struct posix_acl_summary {
@@@ -738,9 -720,8 +739,9 @@@ static void process_one_v4_ace(struct p
        }
  }
  
 -int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
 -                          struct posix_acl **dpacl, unsigned int flags)
 +static int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl,
 +              struct posix_acl **pacl, struct posix_acl **dpacl,
 +              unsigned int flags)
  {
        struct posix_acl_state effective_acl_state, default_acl_state;
        struct nfs4_ace *ace;
@@@ -800,57 -781,6 +801,57 @@@ out_estate
        return ret;
  }
  
 +__be32
 +nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
 +              struct nfs4_acl *acl)
 +{
 +      __be32 error;
 +      int host_error;
 +      struct dentry *dentry;
 +      struct inode *inode;
 +      struct posix_acl *pacl = NULL, *dpacl = NULL;
 +      unsigned int flags = 0;
 +
 +      /* Get inode */
 +      error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
 +      if (error)
 +              return error;
 +
 +      dentry = fhp->fh_dentry;
 +      inode = dentry->d_inode;
 +
 +      if (!inode->i_op->set_acl || !IS_POSIXACL(inode))
 +              return nfserr_attrnotsupp;
 +
 +      if (S_ISDIR(inode->i_mode))
 +              flags = NFS4_ACL_DIR;
 +
 +      host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
 +      if (host_error == -EINVAL)
 +              return nfserr_attrnotsupp;
 +      if (host_error < 0)
 +              goto out_nfserr;
 +
 +      host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS);
 +      if (host_error < 0)
 +              goto out_release;
 +
 +      if (S_ISDIR(inode->i_mode)) {
 +              host_error = inode->i_op->set_acl(inode, dpacl,
 +                                                ACL_TYPE_DEFAULT);
 +      }
 +
 +out_release:
 +      posix_acl_release(pacl);
 +      posix_acl_release(dpacl);
 +out_nfserr:
 +      if (host_error == -EOPNOTSUPP)
 +              return nfserr_attrnotsupp;
 +      else
 +              return nfserrno(host_error);
 +}
 +
 +
  static short
  ace2type(struct nfs4_ace *ace)
  {
        return -1;
  }
  
 -EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
 -EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
 -
  struct nfs4_acl *
  nfs4_acl_new(int n)
  {
@@@ -916,17 -849,26 +917,22 @@@ nfs4_acl_get_whotype(char *p, u32 len
        return NFS4_ACL_WHO_NAMED;
  }
  
- int
- nfs4_acl_write_who(int who, char *p)
+ __be32 nfs4_acl_write_who(int who, __be32 **p, int *len)
  {
        int i;
+       int bytes;
  
        for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
-               if (s2t_map[i].type == who) {
-                       memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);
-                       return s2t_map[i].stringlen;
-               }
+               if (s2t_map[i].type != who)
+                       continue;
+               bytes = 4 + (XDR_QUADLEN(s2t_map[i].stringlen) << 2);
+               if (bytes > *len)
+                       return nfserr_resource;
+               *p = xdr_encode_opaque(*p, s2t_map[i].string,
+                                       s2t_map[i].stringlen);
+               *len -= bytes;
+               return 0;
        }
-       BUG();
+       WARN_ON_ONCE(1);
        return -1;
  }
 -
 -EXPORT_SYMBOL(nfs4_acl_new);
 -EXPORT_SYMBOL(nfs4_acl_get_whotype);
 -EXPORT_SYMBOL(nfs4_acl_write_who);
diff --combined fs/nfsd/nfs4proc.c
index 825b8a99b99b42aaf1675518ea979a77b67c1955,ef76ba6323871d9b86764d78046ea98a512d7a33..82189b208af31700418217e62d8339f13dce6565
@@@ -41,7 -41,6 +41,7 @@@
  #include "vfs.h"
  #include "current_stateid.h"
  #include "netns.h"
 +#include "acl.h"
  
  #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
  #include <linux/security.h>
@@@ -231,17 -230,16 +231,16 @@@ static void nfsd4_set_open_owner_reply_
  }
  
  static __be32
- do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
+ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh **resfh)
  {
        struct svc_fh *current_fh = &cstate->current_fh;
-       struct svc_fh *resfh;
        int accmode;
        __be32 status;
  
-       resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
-       if (!resfh)
+       *resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
+       if (!*resfh)
                return nfserr_jukebox;
-       fh_init(resfh, NFS4_FHSIZE);
+       fh_init(*resfh, NFS4_FHSIZE);
        open->op_truncate = 0;
  
        if (open->op_create) {
                 */
                status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
                                        open->op_fname.len, &open->op_iattr,
-                                       resfh, open->op_createmode,
+                                       *resfh, open->op_createmode,
                                        (u32 *)open->op_verf.data,
                                        &open->op_truncate, &open->op_created);
  
                if (!status && open->op_label.len)
-                       nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval);
+                       nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval);
  
                /*
                 * Following rfc 3530 14.2.16, use the returned bitmask
                if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
                        open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
                                                        FATTR4_WORD1_TIME_MODIFY);
-       } else {
+       } else
+               /*
+                * Note this may exit with the parent still locked.
+                * We will hold the lock until nfsd4_open's final
+                * lookup, to prevent renames or unlinks until we've had
+                * a chance to an acquire a delegation if appropriate.
+                */
                status = nfsd_lookup(rqstp, current_fh,
-                                    open->op_fname.data, open->op_fname.len, resfh);
-               fh_unlock(current_fh);
-       }
+                                    open->op_fname.data, open->op_fname.len, *resfh);
        if (status)
                goto out;
-       status = nfsd_check_obj_isreg(resfh);
+       status = nfsd_check_obj_isreg(*resfh);
        if (status)
                goto out;
  
        if (is_create_with_attrs(open) && open->op_acl != NULL)
-               do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
+               do_set_nfs4_acl(rqstp, *resfh, open->op_acl, open->op_bmval);
  
-       nfsd4_set_open_owner_reply_cache(cstate, open, resfh);
+       nfsd4_set_open_owner_reply_cache(cstate, open, *resfh);
        accmode = NFSD_MAY_NOP;
        if (open->op_created ||
                        open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
                accmode |= NFSD_MAY_OWNER_OVERRIDE;
-       status = do_open_permission(rqstp, resfh, open, accmode);
+       status = do_open_permission(rqstp, *resfh, open, accmode);
        set_change_info(&open->op_cinfo, current_fh);
-       fh_dup2(current_fh, resfh);
  out:
-       fh_put(resfh);
-       kfree(resfh);
        return status;
  }
  
@@@ -358,6 -357,7 +358,7 @@@ nfsd4_open(struct svc_rqst *rqstp, stru
           struct nfsd4_open *open)
  {
        __be32 status;
+       struct svc_fh *resfh = NULL;
        struct nfsd4_compoundres *resp;
        struct net *net = SVC_NET(rqstp);
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        switch (open->op_claim_type) {
                case NFS4_OPEN_CLAIM_DELEGATE_CUR:
                case NFS4_OPEN_CLAIM_NULL:
-                       status = do_open_lookup(rqstp, cstate, open);
+                       status = do_open_lookup(rqstp, cstate, open, &resfh);
                        if (status)
                                goto out;
                        break;
                        status = do_open_fhandle(rqstp, cstate, open);
                        if (status)
                                goto out;
+                       resfh = &cstate->current_fh;
                        break;
                case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
                case NFS4_OPEN_CLAIM_DELEGATE_PREV:
         * successful, it (1) truncates the file if open->op_truncate was
         * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
         */
-       status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
+       status = nfsd4_process_open2(rqstp, resfh, open);
        WARN_ON(status && open->op_created);
  out:
+       if (resfh && resfh != &cstate->current_fh) {
+               fh_dup2(&cstate->current_fh, resfh);
+               fh_put(resfh);
+               kfree(resfh);
+       }
        nfsd4_cleanup_open_state(open, status);
        if (open->op_openowner && !nfsd4_has_session(cstate))
                cstate->replay_owner = &open->op_openowner->oo_owner;
@@@ -1070,8 -1076,10 +1077,10 @@@ _nfsd4_verify(struct svc_rqst *rqstp, s
                                    cstate->current_fh.fh_dentry, &p,
                                    count, verify->ve_bmval,
                                    rqstp, 0);
-       /* this means that nfsd4_encode_fattr() ran out of space */
+       /*
+        * If nfsd4_encode_fattr() ran out of space, assume that's because
+        * the attributes are longer (hence different) than those given:
+        */
        if (status == nfserr_resource)
                status = nfserr_not_same;
        if (status)
@@@ -1525,7 -1533,8 +1534,8 @@@ static inline u32 nfsd4_write_rsize(str
  static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
        return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\
-               1 + 1 + 2 + /* eir_flags, spr_how, spo_must_enforce & _allow */\
+               1 + 1 + /* eir_flags, spr_how */\
+               4 + /* spo_must_enforce & _allow with bitmap */\
                2 + /*eir_server_owner.so_minor_id */\
                /* eir_server_owner.so_major_id<> */\
                XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\
@@@ -1882,6 -1891,7 +1892,7 @@@ struct svc_version      nfsd_version4 = 
                .vs_proc        = nfsd_procedures4,
                .vs_dispatch    = nfsd_dispatch,
                .vs_xdrsize     = NFS4_SVC_XDRSIZE,
+               .vs_rpcb_optnl  = 1,
  };
  
  /*
diff --combined fs/nfsd/vfs.c
index 1426eb66c8c699cf4104bde226986dda77ccc4c8,a41302a00650ea274dc3605afefa4779baa9aa88..017d3cb5e99b4391027fe37b7c56c23966754e2d
@@@ -207,7 -207,12 +207,12 @@@ nfsd_lookup_dentry(struct svc_rqst *rqs
                                goto out_nfserr;
                }
        } else {
-               fh_lock(fhp);
+               /*
+                * In the nfsd4_open() case, this may be held across
+                * subsequent open and delegation acquisition which may
+                * need to take the child's i_mutex:
+                */
+               fh_lock_nested(fhp, I_MUTEX_PARENT);
                dentry = lookup_one_len(name, dparent, len);
                host_err = PTR_ERR(dentry);
                if (IS_ERR(dentry))
@@@ -273,13 -278,6 +278,6 @@@ out
        return err;
  }
  
- static int nfsd_break_lease(struct inode *inode)
- {
-       if (!S_ISREG(inode->i_mode))
-               return 0;
-       return break_lease(inode, O_WRONLY | O_NONBLOCK);
- }
  /*
   * Commit metadata changes to stable storage.
   */
@@@ -348,8 -346,7 +346,7 @@@ nfsd_sanitize_attrs(struct inode *inode
  
        /* Revoke setuid/setgid on chown */
        if (!S_ISDIR(inode->i_mode) &&
-           (((iap->ia_valid & ATTR_UID) && !uid_eq(iap->ia_uid, inode->i_uid)) ||
-            ((iap->ia_valid & ATTR_GID) && !gid_eq(iap->ia_gid, inode->i_gid)))) {
+           ((iap->ia_valid & ATTR_UID) || (iap->ia_valid & ATTR_GID))) {
                iap->ia_valid |= ATTR_KILL_PRIV;
                if (iap->ia_valid & ATTR_MODE) {
                        /* we're setting mode too, just clear the s*id bits */
@@@ -449,16 -446,10 +446,10 @@@ nfsd_setattr(struct svc_rqst *rqstp, st
                goto out_put_write_access;
        }
  
-       host_err = nfsd_break_lease(inode);
-       if (host_err)
-               goto out_put_write_access_nfserror;
        fh_lock(fhp);
        host_err = notify_change(dentry, iap, NULL);
        fh_unlock(fhp);
  
- out_put_write_access_nfserror:
-       err = nfserrno(host_err);
  out_put_write_access:
        if (size_change)
                put_write_access(inode);
@@@ -468,7 -459,158 +459,7 @@@ out
        return err;
  }
  
 -#if defined(CONFIG_NFSD_V2_ACL) || \
 -    defined(CONFIG_NFSD_V3_ACL) || \
 -    defined(CONFIG_NFSD_V4)
 -static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
 -{
 -      ssize_t buflen;
 -      ssize_t ret;
 -
 -      buflen = vfs_getxattr(dentry, key, NULL, 0);
 -      if (buflen <= 0)
 -              return buflen;
 -
 -      *buf = kmalloc(buflen, GFP_KERNEL);
 -      if (!*buf)
 -              return -ENOMEM;
 -
 -      ret = vfs_getxattr(dentry, key, *buf, buflen);
 -      if (ret < 0)
 -              kfree(*buf);
 -      return ret;
 -}
 -#endif
 -
  #if defined(CONFIG_NFSD_V4)
 -static int
 -set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
 -{
 -      int len;
 -      size_t buflen;
 -      char *buf = NULL;
 -      int error = 0;
 -
 -      buflen = posix_acl_xattr_size(pacl->a_count);
 -      buf = kmalloc(buflen, GFP_KERNEL);
 -      error = -ENOMEM;
 -      if (buf == NULL)
 -              goto out;
 -
 -      len = posix_acl_to_xattr(&init_user_ns, pacl, buf, buflen);
 -      if (len < 0) {
 -              error = len;
 -              goto out;
 -      }
 -
 -      error = vfs_setxattr(dentry, key, buf, len, 0);
 -out:
 -      kfree(buf);
 -      return error;
 -}
 -
 -__be32
 -nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
 -    struct nfs4_acl *acl)
 -{
 -      __be32 error;
 -      int host_error;
 -      struct dentry *dentry;
 -      struct inode *inode;
 -      struct posix_acl *pacl = NULL, *dpacl = NULL;
 -      unsigned int flags = 0;
 -
 -      /* Get inode */
 -      error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
 -      if (error)
 -              return error;
 -
 -      dentry = fhp->fh_dentry;
 -      inode = dentry->d_inode;
 -      if (S_ISDIR(inode->i_mode))
 -              flags = NFS4_ACL_DIR;
 -
 -      host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
 -      if (host_error == -EINVAL) {
 -              return nfserr_attrnotsupp;
 -      } else if (host_error < 0)
 -              goto out_nfserr;
 -
 -      host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
 -      if (host_error < 0)
 -              goto out_release;
 -
 -      if (S_ISDIR(inode->i_mode))
 -              host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
 -
 -out_release:
 -      posix_acl_release(pacl);
 -      posix_acl_release(dpacl);
 -out_nfserr:
 -      if (host_error == -EOPNOTSUPP)
 -              return nfserr_attrnotsupp;
 -      else
 -              return nfserrno(host_error);
 -}
 -
 -static struct posix_acl *
 -_get_posix_acl(struct dentry *dentry, char *key)
 -{
 -      void *buf = NULL;
 -      struct posix_acl *pacl = NULL;
 -      int buflen;
 -
 -      buflen = nfsd_getxattr(dentry, key, &buf);
 -      if (!buflen)
 -              buflen = -ENODATA;
 -      if (buflen <= 0)
 -              return ERR_PTR(buflen);
 -
 -      pacl = posix_acl_from_xattr(&init_user_ns, buf, buflen);
 -      kfree(buf);
 -      return pacl;
 -}
 -
 -int
 -nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
 -{
 -      struct inode *inode = dentry->d_inode;
 -      int error = 0;
 -      struct posix_acl *pacl = NULL, *dpacl = NULL;
 -      unsigned int flags = 0;
 -
 -      pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
 -      if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
 -              pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
 -      if (IS_ERR(pacl)) {
 -              error = PTR_ERR(pacl);
 -              pacl = NULL;
 -              goto out;
 -      }
 -
 -      if (S_ISDIR(inode->i_mode)) {
 -              dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
 -              if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
 -                      dpacl = NULL;
 -              else if (IS_ERR(dpacl)) {
 -                      error = PTR_ERR(dpacl);
 -                      dpacl = NULL;
 -                      goto out;
 -              }
 -              flags = NFS4_ACL_DIR;
 -      }
 -
 -      *acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
 -      if (IS_ERR(*acl)) {
 -              error = PTR_ERR(*acl);
 -              *acl = NULL;
 -      }
 - out:
 -      posix_acl_release(pacl);
 -      posix_acl_release(dpacl);
 -      return error;
 -}
 -
  /*
   * NFS junction information is stored in an extended attribute.
   */
@@@ -1609,11 -1751,6 +1600,6 @@@ nfsd_link(struct svc_rqst *rqstp, struc
        err = nfserr_noent;
        if (!dold->d_inode)
                goto out_dput;
-       host_err = nfsd_break_lease(dold->d_inode);
-       if (host_err) {
-               err = nfserrno(host_err);
-               goto out_dput;
-       }
        host_err = vfs_link(dold, dirp, dnew, NULL);
        if (!host_err) {
                err = nfserrno(commit_metadata(ffhp));
@@@ -1707,14 -1844,6 +1693,6 @@@ nfsd_rename(struct svc_rqst *rqstp, str
        if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry)
                goto out_dput_new;
  
-       host_err = nfsd_break_lease(odentry->d_inode);
-       if (host_err)
-               goto out_dput_new;
-       if (ndentry->d_inode) {
-               host_err = nfsd_break_lease(ndentry->d_inode);
-               if (host_err)
-                       goto out_dput_new;
-       }
        host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
        if (!host_err) {
                host_err = commit_metadata(tfhp);
@@@ -1784,16 -1913,12 +1762,12 @@@ nfsd_unlink(struct svc_rqst *rqstp, str
        if (!type)
                type = rdentry->d_inode->i_mode & S_IFMT;
  
-       host_err = nfsd_break_lease(rdentry->d_inode);
-       if (host_err)
-               goto out_put;
        if (type != S_IFDIR)
                host_err = vfs_unlink(dirp, rdentry, NULL);
        else
                host_err = vfs_rmdir(dirp, rdentry);
        if (!host_err)
                host_err = commit_metadata(fhp);
- out_put:
        dput(rdentry);
  
  out_nfserr:
@@@ -2133,3 -2258,93 +2107,3 @@@ out_nomem
        nfsd_racache_shutdown();
        return -ENOMEM;
  }
 -
 -#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 -struct posix_acl *
 -nfsd_get_posix_acl(struct svc_fh *fhp, int type)
 -{
 -      struct inode *inode = fhp->fh_dentry->d_inode;
 -      char *name;
 -      void *value = NULL;
 -      ssize_t size;
 -      struct posix_acl *acl;
 -
 -      if (!IS_POSIXACL(inode))
 -              return ERR_PTR(-EOPNOTSUPP);
 -
 -      switch (type) {
 -      case ACL_TYPE_ACCESS:
 -              name = POSIX_ACL_XATTR_ACCESS;
 -              break;
 -      case ACL_TYPE_DEFAULT:
 -              name = POSIX_ACL_XATTR_DEFAULT;
 -              break;
 -      default:
 -              return ERR_PTR(-EOPNOTSUPP);
 -      }
 -
 -      size = nfsd_getxattr(fhp->fh_dentry, name, &value);
 -      if (size < 0)
 -              return ERR_PTR(size);
 -
 -      acl = posix_acl_from_xattr(&init_user_ns, value, size);
 -      kfree(value);
 -      return acl;
 -}
 -
 -int
 -nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
 -{
 -      struct inode *inode = fhp->fh_dentry->d_inode;
 -      char *name;
 -      void *value = NULL;
 -      size_t size;
 -      int error;
 -
 -      if (!IS_POSIXACL(inode) ||
 -          !inode->i_op->setxattr || !inode->i_op->removexattr)
 -              return -EOPNOTSUPP;
 -      switch(type) {
 -              case ACL_TYPE_ACCESS:
 -                      name = POSIX_ACL_XATTR_ACCESS;
 -                      break;
 -              case ACL_TYPE_DEFAULT:
 -                      name = POSIX_ACL_XATTR_DEFAULT;
 -                      break;
 -              default:
 -                      return -EOPNOTSUPP;
 -      }
 -
 -      if (acl && acl->a_count) {
 -              size = posix_acl_xattr_size(acl->a_count);
 -              value = kmalloc(size, GFP_KERNEL);
 -              if (!value)
 -                      return -ENOMEM;
 -              error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
 -              if (error < 0)
 -                      goto getout;
 -              size = error;
 -      } else
 -              size = 0;
 -
 -      error = fh_want_write(fhp);
 -      if (error)
 -              goto getout;
 -      if (size)
 -              error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
 -      else {
 -              if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
 -                      error = 0;
 -              else {
 -                      error = vfs_removexattr(fhp->fh_dentry, name);
 -                      if (error == -ENODATA)
 -                              error = 0;
 -              }
 -      }
 -      fh_drop_write(fhp);
 -
 -getout:
 -      kfree(value);
 -      return error;
 -}
 -#endif  /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
diff --combined fs/nfsd/vfs.h
index 1bc1d440a1a5677899a7d85d6b5926bb2f3f7900,fd8c0cc9c25db24fd7bf0f8f4b1622e2bddabaf1..fbe90bdb2214e976fa49b50ee8903d25089c2177
@@@ -52,6 -52,9 +52,6 @@@ __be32                nfsd_setattr(struct svc_rqst *
                                struct iattr *, int, time_t);
  int nfsd_mountpoint(struct dentry *, struct svc_export *);
  #ifdef CONFIG_NFSD_V4
 -__be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
 -                    struct nfs4_acl *);
 -int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
  __be32          nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
                    struct xdr_netobj *);
  #endif /* CONFIG_NFSD_V4 */
@@@ -86,8 -89,6 +86,6 @@@ __be32                nfsd_link(struct svc_rqst *, st
  __be32                nfsd_rename(struct svc_rqst *,
                                struct svc_fh *, char *, int,
                                struct svc_fh *, char *, int);
- __be32                nfsd_remove(struct svc_rqst *,
-                               struct svc_fh *, char *, int);
  __be32                nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
                                char *name, int len);
  __be32                nfsd_readdir(struct svc_rqst *, struct svc_fh *,
@@@ -98,6 -99,11 +96,6 @@@ __be32               nfsd_statfs(struct svc_rqst *, 
  __be32                nfsd_permission(struct svc_rqst *, struct svc_export *,
                                struct dentry *, int);
  
 -#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 -struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
 -int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
 -#endif
 -
  static inline int fh_want_write(struct svc_fh *fh)
  {
        int ret = mnt_want_write(fh->fh_export->ex_path.mnt);
diff --combined net/sunrpc/cache.c
index e521d20e19701d917953e49033ce85fac8a96c8d,0877db0787b104e51a40ca0649dd4f9a76a44899..ae333c1845bb42f28198cdfb957cd03e7412c14c
@@@ -619,7 -619,7 +619,7 @@@ static void cache_limit_defers(void
  
        /* Consider removing either the first or the last */
        if (cache_defer_cnt > DFR_MAX) {
 -              if (net_random() & 1)
 +              if (prandom_u32() & 1)
                        discard = list_entry(cache_defer_list.next,
                                             struct cache_deferred_req, recent);
                else
@@@ -1111,9 -1111,7 +1111,7 @@@ void qword_addhex(char **bpp, int *lp, 
                *bp++ = 'x';
                len -= 2;
                while (blen && len >= 2) {
-                       unsigned char c = *buf++;
-                       *bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
-                       *bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
+                       bp = hex_byte_pack(bp, *buf++);
                        len -= 2;
                        blen--;
                }
diff --combined net/sunrpc/netns.h
index 94e506f9d72bb62440d923360753c98ecf5f6725,3a260e47fad2cd32cdb67ae5fed57a7368a2716a..df58268765351ebd1b4376f7504915cd1b9fff6b
@@@ -14,7 -14,6 +14,7 @@@ struct sunrpc_net 
        struct cache_detail *rsi_cache;
  
        struct super_block *pipefs_sb;
 +      struct rpc_pipe *gssd_dummy;
        struct mutex pipefs_sb_lock;
  
        struct list_head all_clients;
        unsigned int rpcb_is_af_local : 1;
  
        struct mutex gssp_lock;
-       wait_queue_head_t gssp_wq;
        struct rpc_clnt *gssp_clnt;
        int use_gss_proxy;
        int pipe_version;
        atomic_t pipe_users;
        struct proc_dir_entry *use_gssp_proc;
 -
 -      unsigned int gssd_running;
  };
  
  extern int sunrpc_net_id;
diff --combined net/sunrpc/xprtsock.c
index 2a7ca8ffe83a9ad47576959b30f9664cc3996b0a,0f4f39174a708929e4dabf90cab063fd303ee8ba..817a1e5239692e9fb3f5117f36eb0895d426ea5f
@@@ -257,7 -257,6 +257,7 @@@ struct sock_xprt 
        void                    (*old_data_ready)(struct sock *, int);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
 +      void                    (*old_error_report)(struct sock *);
  };
  
  /*
   */
  #define TCP_RPC_REPLY         (1UL << 6)
  
 +static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
 +{
 +      return (struct rpc_xprt *) sk->sk_user_data;
 +}
 +
  static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
  {
        return (struct sockaddr *) &xprt->addr;
@@@ -805,7 -799,6 +805,7 @@@ static void xs_save_old_callbacks(struc
        transport->old_data_ready = sk->sk_data_ready;
        transport->old_state_change = sk->sk_state_change;
        transport->old_write_space = sk->sk_write_space;
 +      transport->old_error_report = sk->sk_error_report;
  }
  
  static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
        sk->sk_data_ready = transport->old_data_ready;
        sk->sk_state_change = transport->old_state_change;
        sk->sk_write_space = transport->old_write_space;
 +      sk->sk_error_report = transport->old_error_report;
 +}
 +
 +/**
 + * xs_error_report - callback to handle TCP socket state errors
 + * @sk: socket
 + *
 + * Note: we don't call sock_error() since there may be a rpc_task
 + * using the socket, and so we don't want to clear sk->sk_err.
 + */
 +static void xs_error_report(struct sock *sk)
 +{
 +      struct rpc_xprt *xprt;
 +      int err;
 +
 +      read_lock_bh(&sk->sk_callback_lock);
 +      if (!(xprt = xprt_from_sock(sk)))
 +              goto out;
 +
 +      err = -sk->sk_err;
 +      if (err == 0)
 +              goto out;
 +      dprintk("RPC:       xs_error_report client %p, error=%d...\n",
 +                      xprt, -err);
 +      trace_rpc_socket_error(xprt, sk->sk_socket, err);
 +      xprt_wake_pending_tasks(xprt, err);
 + out:
 +      read_unlock_bh(&sk->sk_callback_lock);
  }
  
  static void xs_reset_transport(struct sock_xprt *transport)
@@@ -920,6 -885,11 +920,6 @@@ static void xs_destroy(struct rpc_xprt 
        module_put(THIS_MODULE);
  }
  
 -static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
 -{
 -      return (struct rpc_xprt *) sk->sk_user_data;
 -}
 -
  static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
  {
        struct xdr_skb_reader desc = {
@@@ -1704,7 -1674,7 +1704,7 @@@ static void xs_udp_timer(struct rpc_xpr
  static unsigned short xs_get_random_port(void)
  {
        unsigned short range = xprt_max_resvport - xprt_min_resvport;
 -      unsigned short rand = (unsigned short) net_random() % range;
 +      unsigned short rand = (unsigned short) prandom_u32() % range;
        return rand + xprt_min_resvport;
  }
  
@@@ -1899,7 -1869,6 +1899,7 @@@ static int xs_local_finish_connecting(s
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_local_data_ready;
                sk->sk_write_space = xs_udp_write_space;
 +              sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
  
                xprt_clear_connected(xprt);
@@@ -2177,7 -2146,6 +2177,7 @@@ static int xs_tcp_finish_connecting(str
                sk->sk_data_ready = xs_tcp_data_ready;
                sk->sk_state_change = xs_tcp_state_change;
                sk->sk_write_space = xs_tcp_write_space;
 +              sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
  
                /* socket options */
@@@ -2964,10 -2932,9 +2964,9 @@@ static struct rpc_xprt *xs_setup_bc_tcp
  
        /*
         * Once we've associated a backchannel xprt with a connection,
-        * we want to keep it around as long as long as the connection
-        * lasts, in case we need to start using it for a backchannel
-        * again; this reference won't be dropped until bc_xprt is
-        * destroyed.
+        * we want to keep it around as long as the connection lasts,
+        * in case we need to start using it for a backchannel again;
+        * this reference won't be dropped until bc_xprt is destroyed.
         */
        xprt_get(xprt);
        args->bc_xprt->xpt_bc_xprt = xprt;