Merge branch 'bugfixes' into nfs-for-next
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 11 Dec 2012 14:16:26 +0000 (09:16 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 11 Dec 2012 14:16:26 +0000 (09:16 -0500)
1  2 
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/write.c
net/sunrpc/rpc_pipe.c

diff --combined fs/nfs/nfs4_fs.h
index 4635bf51b3e6ae451bb84c974a74fcb0ac97d07e,ea4e36241044e8bd8007b006bc784211190af5a4..a3f488b074a2f0d55d561de8f2e529c7d4614b34
@@@ -11,8 -11,6 +11,8 @@@
  
  #if IS_ENABLED(CONFIG_NFS_V4)
  
 +#define NFS4_MAX_LOOP_ON_RECOVER (10)
 +
  struct idmap;
  
  enum nfs4_client_state {
        NFS4CLNT_RECLAIM_NOGRACE,
        NFS4CLNT_DELEGRETURN,
        NFS4CLNT_SESSION_RESET,
 -      NFS4CLNT_RECALL_SLOT,
        NFS4CLNT_LEASE_CONFIRM,
        NFS4CLNT_SERVER_SCOPE_MISMATCH,
        NFS4CLNT_PURGE_STATE,
        NFS4CLNT_BIND_CONN_TO_SESSION,
  };
  
 -enum nfs4_session_state {
 -      NFS4_SESSION_INITING,
 -      NFS4_SESSION_DRAINING,
 -};
 -
  #define NFS4_RENEW_TIMEOUT            0x01
  #define NFS4_RENEW_DELEGATION_CB      0x02
  
@@@ -39,7 -43,8 +39,7 @@@ struct nfs4_minor_version_ops 
                        struct nfs_server *server,
                        struct rpc_message *msg,
                        struct nfs4_sequence_args *args,
 -                      struct nfs4_sequence_res *res,
 -                      int cache_reply);
 +                      struct nfs4_sequence_res *res);
        bool    (*match_stateid)(const nfs4_stateid *,
                        const nfs4_stateid *);
        int     (*find_root_sec)(struct nfs_server *, struct nfs_fh *,
@@@ -236,14 -241,18 +236,14 @@@ static inline struct nfs4_session *nfs4
        return server->nfs_client->cl_session;
  }
  
 -extern bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy);
  extern int nfs4_setup_sequence(const struct nfs_server *server,
                struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
                struct rpc_task *task);
  extern int nfs41_setup_sequence(struct nfs4_session *session,
                struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
                struct rpc_task *task);
 -extern void nfs4_destroy_session(struct nfs4_session *session);
 -extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
  extern int nfs4_proc_create_session(struct nfs_client *, struct rpc_cred *);
  extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_cred *);
 -extern int nfs4_init_session(struct nfs_server *server);
  extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
                struct nfs_fsinfo *fsinfo);
  extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data,
@@@ -271,7 -280,11 +271,7 @@@ static inline int nfs4_setup_sequence(c
                struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
                struct rpc_task *task)
  {
 -      return 0;
 -}
 -
 -static inline int nfs4_init_session(struct nfs_server *server)
 -{
 +      rpc_call_start(task);
        return 0;
  }
  
@@@ -308,20 -321,17 +308,20 @@@ extern void nfs4_renew_state(struct wor
  
  /* nfs4state.c */
  struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
+ struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
  struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
  int nfs4_discover_server_trunking(struct nfs_client *clp,
                        struct nfs_client **);
  int nfs40_discover_server_trunking(struct nfs_client *clp,
                        struct nfs_client **, struct rpc_cred *);
  #if defined(CONFIG_NFS_V4_1)
- struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
  struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
  int nfs41_discover_server_trunking(struct nfs_client *clp,
                        struct nfs_client **, struct rpc_cred *);
  extern void nfs4_schedule_session_recovery(struct nfs4_session *, int);
 +extern void nfs41_server_notify_target_slotid_update(struct nfs_client *clp);
 +extern void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp);
 +
  #else
  static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
  {
@@@ -339,12 -349,11 +339,12 @@@ extern void nfs4_state_set_mode_locked(
  extern void nfs_inode_find_state_and_recover(struct inode *inode,
                const nfs4_stateid *stateid);
  extern void nfs4_schedule_lease_recovery(struct nfs_client *);
 +extern int nfs4_wait_clnt_recover(struct nfs_client *clp);
 +extern int nfs4_client_recover_expired_lease(struct nfs_client *clp);
  extern void nfs4_schedule_state_manager(struct nfs_client *);
  extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
  extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
  extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
 -extern void nfs41_handle_recall_slot(struct nfs_client *clp);
  extern void nfs41_handle_server_scope(struct nfs_client *,
                                      struct nfs41_server_scope **);
  extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
diff --combined fs/nfs/nfs4proc.c
index 992233561dbd3cc6c6c1a47481998000bacf798c,05e5f6f9f2b80b22fa306d33fcdd06c6540725f3..92bd799eee012bf3eab59105a28816e631c6f58e
@@@ -52,6 -52,7 +52,6 @@@
  #include <linux/mount.h>
  #include <linux/module.h>
  #include <linux/nfs_idmap.h>
 -#include <linux/sunrpc/bc_xprt.h>
  #include <linux/xattr.h>
  #include <linux/utsname.h>
  #include <linux/freezer.h>
  #include "callback.h"
  #include "pnfs.h"
  #include "netns.h"
 +#include "nfs4session.h"
 +
  
  #define NFSDBG_FACILITY               NFSDBG_PROC
  
  #define NFS4_POLL_RETRY_MIN   (HZ/10)
  #define NFS4_POLL_RETRY_MAX   (15*HZ)
  
 -#define NFS4_MAX_LOOP_ON_RECOVER (10)
 -
  struct nfs4_opendata;
  static int _nfs4_proc_open(struct nfs4_opendata *data);
  static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
@@@ -205,6 -206,7 +205,6 @@@ static void nfs4_setup_readdir(u64 cook
  {
        __be32 *start, *p;
  
 -      BUG_ON(readdir->count < 80);
        if (cookie > 2) {
                readdir->cookie = cookie;
                memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
        kunmap_atomic(start);
  }
  
 -static int nfs4_wait_clnt_recover(struct nfs_client *clp)
 -{
 -      int res;
 -
 -      might_sleep();
 -
 -      res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING,
 -                      nfs_wait_bit_killable, TASK_KILLABLE);
 -      if (res)
 -              return res;
 -
 -      if (clp->cl_cons_state < 0)
 -              return clp->cl_cons_state;
 -      return 0;
 -}
 -
  static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
  {
        int res = 0;
@@@ -379,47 -397,97 +379,47 @@@ static void renew_lease(const struct nf
  
  #if defined(CONFIG_NFS_V4_1)
  
 -/*
 - * nfs4_free_slot - free a slot and efficiently update slot table.
 - *
 - * freeing a slot is trivially done by clearing its respective bit
 - * in the bitmap.
 - * If the freed slotid equals highest_used_slotid we want to update it
 - * so that the server would be able to size down the slot table if needed,
 - * otherwise we know that the highest_used_slotid is still in use.
 - * When updating highest_used_slotid there may be "holes" in the bitmap
 - * so we need to scan down from highest_used_slotid to 0 looking for the now
 - * highest slotid in use.
 - * If none found, highest_used_slotid is set to NFS4_NO_SLOT.
 - *
 - * Must be called while holding tbl->slot_tbl_lock
 - */
 -static void
 -nfs4_free_slot(struct nfs4_slot_table *tbl, u32 slotid)
 -{
 -      BUG_ON(slotid >= NFS4_MAX_SLOT_TABLE);
 -      /* clear used bit in bitmap */
 -      __clear_bit(slotid, tbl->used_slots);
 -
 -      /* update highest_used_slotid when it is freed */
 -      if (slotid == tbl->highest_used_slotid) {
 -              slotid = find_last_bit(tbl->used_slots, tbl->max_slots);
 -              if (slotid < tbl->max_slots)
 -                      tbl->highest_used_slotid = slotid;
 -              else
 -                      tbl->highest_used_slotid = NFS4_NO_SLOT;
 -      }
 -      dprintk("%s: slotid %u highest_used_slotid %d\n", __func__,
 -              slotid, tbl->highest_used_slotid);
 -}
 -
 -bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy)
 -{
 -      rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
 -      return true;
 -}
 -
 -/*
 - * Signal state manager thread if session fore channel is drained
 - */
 -static void nfs4_check_drain_fc_complete(struct nfs4_session *ses)
 -{
 -      if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state)) {
 -              rpc_wake_up_first(&ses->fc_slot_table.slot_tbl_waitq,
 -                              nfs4_set_task_privileged, NULL);
 -              return;
 -      }
 -
 -      if (ses->fc_slot_table.highest_used_slotid != NFS4_NO_SLOT)
 -              return;
 -
 -      dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__);
 -      complete(&ses->fc_slot_table.complete);
 -}
 -
 -/*
 - * Signal state manager thread if session back channel is drained
 - */
 -void nfs4_check_drain_bc_complete(struct nfs4_session *ses)
 -{
 -      if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) ||
 -          ses->bc_slot_table.highest_used_slotid != NFS4_NO_SLOT)
 -              return;
 -      dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__);
 -      complete(&ses->bc_slot_table.complete);
 -}
 -
  static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
  {
 +      struct nfs4_session *session;
        struct nfs4_slot_table *tbl;
 +      bool send_new_highest_used_slotid = false;
  
 -      tbl = &res->sr_session->fc_slot_table;
        if (!res->sr_slot) {
                /* just wake up the next guy waiting since
                 * we may have not consumed a slot after all */
                dprintk("%s: No slot\n", __func__);
                return;
        }
 +      tbl = res->sr_slot->table;
 +      session = tbl->session;
  
        spin_lock(&tbl->slot_tbl_lock);
 -      nfs4_free_slot(tbl, res->sr_slot - tbl->slots);
 -      nfs4_check_drain_fc_complete(res->sr_session);
 +      /* Be nice to the server: try to ensure that the last transmitted
 +       * value for highest_user_slotid <= target_highest_slotid
 +       */
 +      if (tbl->highest_used_slotid > tbl->target_highest_slotid)
 +              send_new_highest_used_slotid = true;
 +
 +      if (nfs41_wake_and_assign_slot(tbl, res->sr_slot)) {
 +              send_new_highest_used_slotid = false;
 +              goto out_unlock;
 +      }
 +      nfs4_free_slot(tbl, res->sr_slot);
 +
 +      if (tbl->highest_used_slotid != NFS4_NO_SLOT)
 +              send_new_highest_used_slotid = false;
 +out_unlock:
        spin_unlock(&tbl->slot_tbl_lock);
        res->sr_slot = NULL;
 +      if (send_new_highest_used_slotid)
 +              nfs41_server_notify_highest_slotid_update(session->clp);
  }
  
  static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
  {
 +      struct nfs4_session *session;
 +      struct nfs4_slot *slot;
        unsigned long timestamp;
        struct nfs_client *clp;
  
        if (!RPC_WAS_SENT(task))
                goto out;
  
 +      slot = res->sr_slot;
 +      session = slot->table->session;
 +
        /* Check the SEQUENCE operation status */
        switch (res->sr_status) {
        case 0:
                /* Update the slot's sequence and clientid lease timer */
 -              ++res->sr_slot->seq_nr;
 -              timestamp = res->sr_renewal_time;
 -              clp = res->sr_session->clp;
 +              ++slot->seq_nr;
 +              timestamp = slot->renewal_time;
 +              clp = session->clp;
                do_renew_lease(clp, timestamp);
                /* Check sequence flags */
                if (res->sr_status_flags != 0)
                        nfs4_schedule_lease_recovery(clp);
 +              nfs41_update_target_slotid(slot->table, slot, res);
                break;
        case -NFS4ERR_DELAY:
                /* The server detected a resend of the RPC call and
                 * returned NFS4ERR_DELAY as per Section 2.10.6.2
                 * of RFC5661.
                 */
 -              dprintk("%s: slot=%td seq=%d: Operation in progress\n",
 +              dprintk("%s: slot=%u seq=%u: Operation in progress\n",
                        __func__,
 -                      res->sr_slot - res->sr_session->fc_slot_table.slots,
 -                      res->sr_slot->seq_nr);
 +                      slot->slot_nr,
 +                      slot->seq_nr);
                goto out_retry;
        default:
                /* Just update the slot sequence no. */
 -              ++res->sr_slot->seq_nr;
 +              ++slot->seq_nr;
        }
  out:
        /* The session may be reset by one of the error handlers. */
@@@ -481,27 -545,55 +481,27 @@@ out_retry
  static int nfs4_sequence_done(struct rpc_task *task,
                               struct nfs4_sequence_res *res)
  {
 -      if (res->sr_session == NULL)
 +      if (res->sr_slot == NULL)
                return 1;
        return nfs41_sequence_done(task, res);
  }
  
 -/*
 - * nfs4_find_slot - efficiently look for a free slot
 - *
 - * nfs4_find_slot looks for an unset bit in the used_slots bitmap.
 - * If found, we mark the slot as used, update the highest_used_slotid,
 - * and respectively set up the sequence operation args.
 - * The slot number is returned if found, or NFS4_NO_SLOT otherwise.
 - *
 - * Note: must be called with under the slot_tbl_lock.
 - */
 -static u32
 -nfs4_find_slot(struct nfs4_slot_table *tbl)
 -{
 -      u32 slotid;
 -      u32 ret_id = NFS4_NO_SLOT;
 -
 -      dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n",
 -              __func__, tbl->used_slots[0], tbl->highest_used_slotid,
 -              tbl->max_slots);
 -      slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots);
 -      if (slotid >= tbl->max_slots)
 -              goto out;
 -      __set_bit(slotid, tbl->used_slots);
 -      if (slotid > tbl->highest_used_slotid ||
 -                      tbl->highest_used_slotid == NFS4_NO_SLOT)
 -              tbl->highest_used_slotid = slotid;
 -      ret_id = slotid;
 -out:
 -      dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n",
 -              __func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id);
 -      return ret_id;
 -}
 -
  static void nfs41_init_sequence(struct nfs4_sequence_args *args,
                struct nfs4_sequence_res *res, int cache_reply)
  {
 -      args->sa_session = NULL;
 +      args->sa_slot = NULL;
        args->sa_cache_this = 0;
 +      args->sa_privileged = 0;
        if (cache_reply)
                args->sa_cache_this = 1;
 -      res->sr_session = NULL;
        res->sr_slot = NULL;
  }
  
 +static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
 +{
 +      args->sa_privileged = 1;
 +}
 +
  int nfs41_setup_sequence(struct nfs4_session *session,
                                struct nfs4_sequence_args *args,
                                struct nfs4_sequence_res *res,
  {
        struct nfs4_slot *slot;
        struct nfs4_slot_table *tbl;
 -      u32 slotid;
  
        dprintk("--> %s\n", __func__);
        /* slot already allocated? */
        if (res->sr_slot != NULL)
 -              return 0;
 +              goto out_success;
  
        tbl = &session->fc_slot_table;
  
 +      task->tk_timeout = 0;
 +
        spin_lock(&tbl->slot_tbl_lock);
        if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) &&
 -          !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) {
 +          !args->sa_privileged) {
                /* The state manager will wait until the slot table is empty */
 -              rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
 -              spin_unlock(&tbl->slot_tbl_lock);
                dprintk("%s session is draining\n", __func__);
 -              return -EAGAIN;
 +              goto out_sleep;
        }
  
 -      if (!rpc_queue_empty(&tbl->slot_tbl_waitq) &&
 -          !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) {
 -              rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
 -              spin_unlock(&tbl->slot_tbl_lock);
 -              dprintk("%s enforce FIFO order\n", __func__);
 -              return -EAGAIN;
 -      }
 -
 -      slotid = nfs4_find_slot(tbl);
 -      if (slotid == NFS4_NO_SLOT) {
 -              rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
 -              spin_unlock(&tbl->slot_tbl_lock);
 +      slot = nfs4_alloc_slot(tbl);
 +      if (IS_ERR(slot)) {
 +              /* If out of memory, try again in 1/4 second */
 +              if (slot == ERR_PTR(-ENOMEM))
 +                      task->tk_timeout = HZ >> 2;
                dprintk("<-- %s: no free slots\n", __func__);
 -              return -EAGAIN;
 +              goto out_sleep;
        }
        spin_unlock(&tbl->slot_tbl_lock);
  
 -      rpc_task_set_priority(task, RPC_PRIORITY_NORMAL);
 -      slot = tbl->slots + slotid;
 -      args->sa_session = session;
 -      args->sa_slotid = slotid;
 +      args->sa_slot = slot;
  
 -      dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
 +      dprintk("<-- %s slotid=%d seqid=%d\n", __func__,
 +                      slot->slot_nr, slot->seq_nr);
  
 -      res->sr_session = session;
        res->sr_slot = slot;
 -      res->sr_renewal_time = jiffies;
        res->sr_status_flags = 0;
        /*
         * sr_status is only set in decode_sequence, and so will remain
         * set to 1 if an rpc level failure occurs.
         */
        res->sr_status = 1;
 +out_success:
 +      rpc_call_start(task);
        return 0;
 +out_sleep:
 +      /* Privileged tasks are queued with top priority */
 +      if (args->sa_privileged)
 +              rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task,
 +                              NULL, RPC_PRIORITY_PRIVILEGED);
 +      else
 +              rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
 +      spin_unlock(&tbl->slot_tbl_lock);
 +      return -EAGAIN;
  }
  EXPORT_SYMBOL_GPL(nfs41_setup_sequence);
  
@@@ -572,14 -665,12 +572,14 @@@ int nfs4_setup_sequence(const struct nf
        struct nfs4_session *session = nfs4_get_session(server);
        int ret = 0;
  
 -      if (session == NULL)
 +      if (session == NULL) {
 +              rpc_call_start(task);
                goto out;
 +      }
  
 -      dprintk("--> %s clp %p session %p sr_slot %td\n",
 +      dprintk("--> %s clp %p session %p sr_slot %d\n",
                __func__, session->clp, session, res->sr_slot ?
 -                      res->sr_slot - session->fc_slot_table.slots : -1);
 +                      res->sr_slot->slot_nr : -1);
  
        ret = nfs41_setup_sequence(session, args, res, task);
  out:
@@@ -596,11 -687,19 +596,11 @@@ struct nfs41_call_sync_data 
  static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
  {
        struct nfs41_call_sync_data *data = calldata;
 +      struct nfs4_session *session = nfs4_get_session(data->seq_server);
  
        dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server);
  
 -      if (nfs4_setup_sequence(data->seq_server, data->seq_args,
 -                              data->seq_res, task))
 -              return;
 -      rpc_call_start(task);
 -}
 -
 -static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata)
 -{
 -      rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
 -      nfs41_call_sync_prepare(task, calldata);
 +      nfs41_setup_sequence(session, data->seq_args, data->seq_res, task);
  }
  
  static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
@@@ -615,11 -714,17 +615,11 @@@ static const struct rpc_call_ops nfs41_
        .rpc_call_done = nfs41_call_sync_done,
  };
  
 -static const struct rpc_call_ops nfs41_call_priv_sync_ops = {
 -      .rpc_call_prepare = nfs41_call_priv_sync_prepare,
 -      .rpc_call_done = nfs41_call_sync_done,
 -};
 -
  static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
                                   struct nfs_server *server,
                                   struct rpc_message *msg,
                                   struct nfs4_sequence_args *args,
 -                                 struct nfs4_sequence_res *res,
 -                                 int privileged)
 +                                 struct nfs4_sequence_res *res)
  {
        int ret;
        struct rpc_task *task;
                .callback_data = &data
        };
  
 -      if (privileged)
 -              task_setup.callback_ops = &nfs41_call_priv_sync_ops;
        task = rpc_run_task(&task_setup);
        if (IS_ERR(task))
                ret = PTR_ERR(task);
        return ret;
  }
  
 -int _nfs4_call_sync_session(struct rpc_clnt *clnt,
 -                          struct nfs_server *server,
 -                          struct rpc_message *msg,
 -                          struct nfs4_sequence_args *args,
 -                          struct nfs4_sequence_res *res,
 -                          int cache_reply)
 -{
 -      nfs41_init_sequence(args, res, cache_reply);
 -      return nfs4_call_sync_sequence(clnt, server, msg, args, res, 0);
 -}
 -
  #else
 -static inline
 +static
  void nfs41_init_sequence(struct nfs4_sequence_args *args,
                struct nfs4_sequence_res *res, int cache_reply)
  {
  }
  
 +static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
 +{
 +}
 +
 +
  static int nfs4_sequence_done(struct rpc_task *task,
                               struct nfs4_sequence_res *res)
  {
  }
  #endif /* CONFIG_NFS_V4_1 */
  
 +static
  int _nfs4_call_sync(struct rpc_clnt *clnt,
                    struct nfs_server *server,
                    struct rpc_message *msg,
                    struct nfs4_sequence_args *args,
 -                  struct nfs4_sequence_res *res,
 -                  int cache_reply)
 +                  struct nfs4_sequence_res *res)
  {
 -      nfs41_init_sequence(args, res, cache_reply);
        return rpc_call_sync(clnt, msg, 0);
  }
  
 -static inline
 +static
  int nfs4_call_sync(struct rpc_clnt *clnt,
                   struct nfs_server *server,
                   struct rpc_message *msg,
                   struct nfs4_sequence_res *res,
                   int cache_reply)
  {
 +      nfs41_init_sequence(args, res, cache_reply);
        return server->nfs_client->cl_mvops->call_sync(clnt, server, msg,
 -                                              args, res, cache_reply);
 +                                              args, res);
  }
  
  static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
@@@ -1461,12 -1574,20 +1461,12 @@@ static void nfs4_open_prepare(struct rp
                                &data->o_res.seq_res,
                                task) != 0)
                nfs_release_seqid(data->o_arg.seqid);
 -      else
 -              rpc_call_start(task);
        return;
  unlock_no_action:
        rcu_read_unlock();
  out_no_action:
        task->tk_action = NULL;
 -
 -}
 -
 -static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata)
 -{
 -      rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
 -      nfs4_open_prepare(task, calldata);
 +      nfs4_sequence_done(task, &data->o_res.seq_res);
  }
  
  static void nfs4_open_done(struct rpc_task *task, void *calldata)
@@@ -1527,6 -1648,12 +1527,6 @@@ static const struct rpc_call_ops nfs4_o
        .rpc_release = nfs4_open_release,
  };
  
 -static const struct rpc_call_ops nfs4_recover_open_ops = {
 -      .rpc_call_prepare = nfs4_recover_open_prepare,
 -      .rpc_call_done = nfs4_open_done,
 -      .rpc_release = nfs4_open_release,
 -};
 -
  static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
  {
        struct inode *dir = data->dir->d_inode;
        data->rpc_status = 0;
        data->cancelled = 0;
        if (isrecover)
 -              task_setup_data.callback_ops = &nfs4_recover_open_ops;
 +              nfs4_set_sequence_privileged(&o_arg->seq_args);
        task = rpc_run_task(&task_setup_data);
          if (IS_ERR(task))
                  return PTR_ERR(task);
@@@ -1662,6 -1789,24 +1662,6 @@@ static int _nfs4_proc_open(struct nfs4_
        return 0;
  }
  
 -static int nfs4_client_recover_expired_lease(struct nfs_client *clp)
 -{
 -      unsigned int loop;
 -      int ret;
 -
 -      for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) {
 -              ret = nfs4_wait_clnt_recover(clp);
 -              if (ret != 0)
 -                      break;
 -              if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
 -                  !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state))
 -                      break;
 -              nfs4_schedule_state_manager(clp);
 -              ret = -EIO;
 -      }
 -      return ret;
 -}
 -
  static int nfs4_recover_expired_lease(struct nfs_server *server)
  {
        return nfs4_client_recover_expired_lease(server->nfs_client);
@@@ -2137,7 -2282,6 +2137,7 @@@ static void nfs4_close_prepare(struct r
        if (!call_close) {
                /* Note: exit _without_ calling nfs4_close_done */
                task->tk_action = NULL;
 +              nfs4_sequence_done(task, &calldata->res.seq_res);
                goto out;
        }
  
                                &calldata->res.seq_res,
                                task) != 0)
                nfs_release_seqid(calldata->arg.seqid);
 -      else
 -              rpc_call_start(task);
  out:
        dprintk("%s: done!\n", __func__);
  }
@@@ -2387,8 -2533,7 +2387,8 @@@ static int nfs4_find_root_sec(struct nf
        rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
  
        len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array));
 -      BUG_ON(len < 0);
 +      if (len < 0)
 +              return len;
  
        for (i = 0; i < len; i++) {
                /* AUTH_UNIX is the default flavor if none was specified,
@@@ -2893,10 -3038,12 +2893,10 @@@ static void nfs4_proc_unlink_setup(stru
  
  static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
  {
 -      if (nfs4_setup_sequence(NFS_SERVER(data->dir),
 -                              &data->args.seq_args,
 -                              &data->res.seq_res,
 -                              task))
 -              return;
 -      rpc_call_start(task);
 +      nfs4_setup_sequence(NFS_SERVER(data->dir),
 +                      &data->args.seq_args,
 +                      &data->res.seq_res,
 +                      task);
  }
  
  static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
@@@ -2924,10 -3071,12 +2924,10 @@@ static void nfs4_proc_rename_setup(stru
  
  static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
  {
 -      if (nfs4_setup_sequence(NFS_SERVER(data->old_dir),
 -                              &data->args.seq_args,
 -                              &data->res.seq_res,
 -                              task))
 -              return;
 -      rpc_call_start(task);
 +      nfs4_setup_sequence(NFS_SERVER(data->old_dir),
 +                      &data->args.seq_args,
 +                      &data->res.seq_res,
 +                      task);
  }
  
  static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
@@@ -3213,6 -3362,9 +3213,6 @@@ static int _nfs4_proc_mknod(struct inod
        int mode = sattr->ia_mode;
        int status = -ENOMEM;
  
 -      BUG_ON(!(sattr->ia_valid & ATTR_MODE));
 -      BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
 -
        data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
        if (data == NULL)
                goto out;
                data->arg.ftype = NF4CHR;
                data->arg.u.device.specdata1 = MAJOR(rdev);
                data->arg.u.device.specdata2 = MINOR(rdev);
 +      } else if (!S_ISSOCK(mode)) {
 +              status = -EINVAL;
 +              goto out_free;
        }
        
        status = nfs4_do_create(dir, dentry, data);
 -
 +out_free:
        nfs4_free_createdata(data);
  out:
        return status;
@@@ -3416,10 -3565,12 +3416,10 @@@ static void nfs4_proc_read_setup(struc
  
  static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
  {
 -      if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
 -                              &data->args.seq_args,
 -                              &data->res.seq_res,
 -                              task))
 -              return;
 -      rpc_call_start(task);
 +      nfs4_setup_sequence(NFS_SERVER(data->header->inode),
 +                      &data->args.seq_args,
 +                      &data->res.seq_res,
 +                      task);
  }
  
  static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data)
@@@ -3480,18 -3631,22 +3480,18 @@@ static void nfs4_proc_write_setup(struc
  
  static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data)
  {
 -      if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
 -                              &data->args.seq_args,
 -                              &data->res.seq_res,
 -                              task))
 -              return;
 -      rpc_call_start(task);
 +      nfs4_setup_sequence(NFS_SERVER(data->header->inode),
 +                      &data->args.seq_args,
 +                      &data->res.seq_res,
 +                      task);
  }
  
  static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
  {
 -      if (nfs4_setup_sequence(NFS_SERVER(data->inode),
 -                              &data->args.seq_args,
 -                              &data->res.seq_res,
 -                              task))
 -              return;
 -      rpc_call_start(task);
 +      nfs4_setup_sequence(NFS_SERVER(data->inode),
 +                      &data->args.seq_args,
 +                      &data->res.seq_res,
 +                      task);
  }
  
  static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data)
@@@ -3782,8 -3937,13 +3782,13 @@@ static ssize_t __nfs4_get_acl_uncached(
                goto out_free;
        }
        nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len);
-       if (buf)
+       if (buf) {
+               if (res.acl_len > buflen) {
+                       ret = -ERANGE;
+                       goto out_free;
+               }
                _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len);
+       }
  out_ok:
        ret = res.acl_len;
  out_free:
@@@ -4138,10 -4298,11 +4143,10 @@@ static void nfs4_delegreturn_prepare(st
  
        d_data = (struct nfs4_delegreturndata *)data;
  
 -      if (nfs4_setup_sequence(d_data->res.server,
 -                              &d_data->args.seq_args,
 -                              &d_data->res.seq_res, task))
 -              return;
 -      rpc_call_start(task);
 +      nfs4_setup_sequence(d_data->res.server,
 +                      &d_data->args.seq_args,
 +                      &d_data->res.seq_res,
 +                      task);
  }
  #endif /* CONFIG_NFS_V4_1 */
  
@@@ -4387,7 -4548,6 +4392,7 @@@ static void nfs4_locku_prepare(struct r
        if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) {
                /* Note: exit _without_ running nfs4_locku_done */
                task->tk_action = NULL;
 +              nfs4_sequence_done(task, &calldata->res.seq_res);
                return;
        }
        calldata->timestamp = jiffies;
                                &calldata->res.seq_res,
                                task) != 0)
                nfs_release_seqid(calldata->arg.seqid);
 -      else
 -              rpc_call_start(task);
  }
  
  static const struct rpc_call_ops nfs4_locku_ops = {
@@@ -4539,9 -4701,8 +4544,9 @@@ static void nfs4_lock_prepare(struct rp
                return;
        /* Do we need to do an open_to_lock_owner? */
        if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
 -              if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
 +              if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) {
                        goto out_release_lock_seqid;
 +              }
                data->arg.open_stateid = &state->stateid;
                data->arg.new_lock_owner = 1;
                data->res.open_seqid = data->arg.open_seqid;
        if (nfs4_setup_sequence(data->server,
                                &data->arg.seq_args,
                                &data->res.seq_res,
 -                              task) == 0) {
 -              rpc_call_start(task);
 +                              task) == 0)
                return;
 -      }
        nfs_release_seqid(data->arg.open_seqid);
  out_release_lock_seqid:
        nfs_release_seqid(data->arg.lock_seqid);
 -      dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);
 -}
 -
 -static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
 -{
 -      rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
 -      nfs4_lock_prepare(task, calldata);
 +      dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
  }
  
  static void nfs4_lock_done(struct rpc_task *task, void *calldata)
@@@ -4611,6 -4780,12 +4616,6 @@@ static const struct rpc_call_ops nfs4_l
        .rpc_release = nfs4_lock_release,
  };
  
 -static const struct rpc_call_ops nfs4_recover_lock_ops = {
 -      .rpc_call_prepare = nfs4_recover_lock_prepare,
 -      .rpc_call_done = nfs4_lock_done,
 -      .rpc_release = nfs4_lock_release,
 -};
 -
  static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
  {
        switch (error) {
@@@ -4653,15 -4828,15 +4658,15 @@@ static int _nfs4_do_setlk(struct nfs4_s
                return -ENOMEM;
        if (IS_SETLKW(cmd))
                data->arg.block = 1;
 -      if (recovery_type > NFS_LOCK_NEW) {
 -              if (recovery_type == NFS_LOCK_RECLAIM)
 -                      data->arg.reclaim = NFS_LOCK_RECLAIM;
 -              task_setup_data.callback_ops = &nfs4_recover_lock_ops;
 -      }
        nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
        msg.rpc_argp = &data->arg;
        msg.rpc_resp = &data->res;
        task_setup_data.callback_data = data;
 +      if (recovery_type > NFS_LOCK_NEW) {
 +              if (recovery_type == NFS_LOCK_RECLAIM)
 +                      data->arg.reclaim = NFS_LOCK_RECLAIM;
 +              nfs4_set_sequence_privileged(&data->arg.seq_args);
 +      }
        task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
@@@ -5187,6 -5362,7 +5192,6 @@@ int nfs4_proc_bind_conn_to_session(stru
        };
  
        dprintk("--> %s\n", __func__);
 -      BUG_ON(clp == NULL);
  
        res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
        if (unlikely(res.session == NULL)) {
@@@ -5398,16 -5574,20 +5403,16 @@@ struct nfs4_get_lease_time_data 
  static void nfs4_get_lease_time_prepare(struct rpc_task *task,
                                        void *calldata)
  {
 -      int ret;
        struct nfs4_get_lease_time_data *data =
                        (struct nfs4_get_lease_time_data *)calldata;
  
        dprintk("--> %s\n", __func__);
 -      rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
        /* just setup sequence, do not trigger session recovery
           since we're invoked within one */
 -      ret = nfs41_setup_sequence(data->clp->cl_session,
 -                                 &data->args->la_seq_args,
 -                                 &data->res->lr_seq_res, task);
 -
 -      BUG_ON(ret == -EAGAIN);
 -      rpc_call_start(task);
 +      nfs41_setup_sequence(data->clp->cl_session,
 +                      &data->args->la_seq_args,
 +                      &data->res->lr_seq_res,
 +                      task);
        dprintk("<-- %s\n", __func__);
  }
  
@@@ -5469,7 -5649,6 +5474,7 @@@ int nfs4_proc_get_lease_time(struct nfs
        int status;
  
        nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
 +      nfs4_set_sequence_privileged(&args.la_seq_args);
        dprintk("--> %s\n", __func__);
        task = rpc_run_task(&task_setup);
  
        return status;
  }
  
 -static struct nfs4_slot *nfs4_alloc_slots(u32 max_slots, gfp_t gfp_flags)
 -{
 -      return kcalloc(max_slots, sizeof(struct nfs4_slot), gfp_flags);
 -}
 -
 -static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
 -              struct nfs4_slot *new,
 -              u32 max_slots,
 -              u32 ivalue)
 -{
 -      struct nfs4_slot *old = NULL;
 -      u32 i;
 -
 -      spin_lock(&tbl->slot_tbl_lock);
 -      if (new) {
 -              old = tbl->slots;
 -              tbl->slots = new;
 -              tbl->max_slots = max_slots;
 -      }
 -      tbl->highest_used_slotid = NFS4_NO_SLOT;
 -      for (i = 0; i < tbl->max_slots; i++)
 -              tbl->slots[i].seq_nr = ivalue;
 -      spin_unlock(&tbl->slot_tbl_lock);
 -      kfree(old);
 -}
 -
 -/*
 - * (re)Initialise a slot table
 - */
 -static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
 -                               u32 ivalue)
 -{
 -      struct nfs4_slot *new = NULL;
 -      int ret = -ENOMEM;
 -
 -      dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
 -              max_reqs, tbl->max_slots);
 -
 -      /* Does the newly negotiated max_reqs match the existing slot table? */
 -      if (max_reqs != tbl->max_slots) {
 -              new = nfs4_alloc_slots(max_reqs, GFP_NOFS);
 -              if (!new)
 -                      goto out;
 -      }
 -      ret = 0;
 -
 -      nfs4_add_and_init_slots(tbl, new, max_reqs, ivalue);
 -      dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
 -              tbl, tbl->slots, tbl->max_slots);
 -out:
 -      dprintk("<-- %s: return %d\n", __func__, ret);
 -      return ret;
 -}
 -
 -/* Destroy the slot table */
 -static void nfs4_destroy_slot_tables(struct nfs4_session *session)
 -{
 -      if (session->fc_slot_table.slots != NULL) {
 -              kfree(session->fc_slot_table.slots);
 -              session->fc_slot_table.slots = NULL;
 -      }
 -      if (session->bc_slot_table.slots != NULL) {
 -              kfree(session->bc_slot_table.slots);
 -              session->bc_slot_table.slots = NULL;
 -      }
 -      return;
 -}
 -
 -/*
 - * Initialize or reset the forechannel and backchannel tables
 - */
 -static int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
 -{
 -      struct nfs4_slot_table *tbl;
 -      int status;
 -
 -      dprintk("--> %s\n", __func__);
 -      /* Fore channel */
 -      tbl = &ses->fc_slot_table;
 -      status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
 -      if (status) /* -ENOMEM */
 -              return status;
 -      /* Back channel */
 -      tbl = &ses->bc_slot_table;
 -      status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
 -      if (status && tbl->slots == NULL)
 -              /* Fore and back channel share a connection so get
 -               * both slot tables or neither */
 -              nfs4_destroy_slot_tables(ses);
 -      return status;
 -}
 -
 -struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
 -{
 -      struct nfs4_session *session;
 -      struct nfs4_slot_table *tbl;
 -
 -      session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
 -      if (!session)
 -              return NULL;
 -
 -      tbl = &session->fc_slot_table;
 -      tbl->highest_used_slotid = NFS4_NO_SLOT;
 -      spin_lock_init(&tbl->slot_tbl_lock);
 -      rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
 -      init_completion(&tbl->complete);
 -
 -      tbl = &session->bc_slot_table;
 -      tbl->highest_used_slotid = NFS4_NO_SLOT;
 -      spin_lock_init(&tbl->slot_tbl_lock);
 -      rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table");
 -      init_completion(&tbl->complete);
 -
 -      session->session_state = 1<<NFS4_SESSION_INITING;
 -
 -      session->clp = clp;
 -      return session;
 -}
 -
 -void nfs4_destroy_session(struct nfs4_session *session)
 -{
 -      struct rpc_xprt *xprt;
 -      struct rpc_cred *cred;
 -
 -      cred = nfs4_get_exchange_id_cred(session->clp);
 -      nfs4_proc_destroy_session(session, cred);
 -      if (cred)
 -              put_rpccred(cred);
 -
 -      rcu_read_lock();
 -      xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt);
 -      rcu_read_unlock();
 -      dprintk("%s Destroy backchannel for xprt %p\n",
 -              __func__, xprt);
 -      xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS);
 -      nfs4_destroy_slot_tables(session);
 -      kfree(session);
 -}
 -
  /*
   * Initialize the values to be used by the client in CREATE_SESSION
   * If nfs4_init_session set the fore channel request and response sizes,
  static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
  {
        struct nfs4_session *session = args->client->cl_session;
 -      unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz,
 -                   mxresp_sz = session->fc_attrs.max_resp_sz;
 +      unsigned int mxrqst_sz = session->fc_target_max_rqst_sz,
 +                   mxresp_sz = session->fc_target_max_resp_sz;
  
        if (mxrqst_sz == 0)
                mxrqst_sz = NFS_MAX_FILE_IO_SIZE;
@@@ -5606,9 -5924,10 +5611,9 @@@ static int _nfs4_proc_create_session(st
  
        status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
  
 -      if (!status)
 +      if (!status) {
                /* Verify the session's negotiated channel_attrs values */
                status = nfs4_verify_channel_attrs(&args, session);
 -      if (!status) {
                /* Increment the clientid slot sequence id */
                clp->cl_seqid++;
        }
@@@ -5677,6 -5996,83 +5682,6 @@@ int nfs4_proc_destroy_session(struct nf
        return status;
  }
  
 -/*
 - * With sessions, the client is not marked ready until after a
 - * successful EXCHANGE_ID and CREATE_SESSION.
 - *
 - * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate
 - * other versions of NFS can be tried.
 - */
 -static int nfs41_check_session_ready(struct nfs_client *clp)
 -{
 -      int ret;
 -      
 -      if (clp->cl_cons_state == NFS_CS_SESSION_INITING) {
 -              ret = nfs4_client_recover_expired_lease(clp);
 -              if (ret)
 -                      return ret;
 -      }
 -      if (clp->cl_cons_state < NFS_CS_READY)
 -              return -EPROTONOSUPPORT;
 -      smp_rmb();
 -      return 0;
 -}
 -
 -int nfs4_init_session(struct nfs_server *server)
 -{
 -      struct nfs_client *clp = server->nfs_client;
 -      struct nfs4_session *session;
 -      unsigned int rsize, wsize;
 -
 -      if (!nfs4_has_session(clp))
 -              return 0;
 -
 -      session = clp->cl_session;
 -      spin_lock(&clp->cl_lock);
 -      if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
 -
 -              rsize = server->rsize;
 -              if (rsize == 0)
 -                      rsize = NFS_MAX_FILE_IO_SIZE;
 -              wsize = server->wsize;
 -              if (wsize == 0)
 -                      wsize = NFS_MAX_FILE_IO_SIZE;
 -
 -              session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead;
 -              session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead;
 -      }
 -      spin_unlock(&clp->cl_lock);
 -
 -      return nfs41_check_session_ready(clp);
 -}
 -
 -int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time)
 -{
 -      struct nfs4_session *session = clp->cl_session;
 -      int ret;
 -
 -      spin_lock(&clp->cl_lock);
 -      if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
 -              /*
 -               * Do not set NFS_CS_CHECK_LEASE_TIME instead set the
 -               * DS lease to be equal to the MDS lease.
 -               */
 -              clp->cl_lease_time = lease_time;
 -              clp->cl_last_renewal = jiffies;
 -      }
 -      spin_unlock(&clp->cl_lock);
 -
 -      ret = nfs41_check_session_ready(clp);
 -      if (ret)
 -              return ret;
 -      /* Test for the DS role */
 -      if (!is_ds_client(clp))
 -              return -ENODEV;
 -      return 0;
 -}
 -EXPORT_SYMBOL_GPL(nfs4_init_ds_session);
 -
 -
  /*
   * Renew the cl_session lease.
   */
@@@ -5742,7 -6138,9 +5747,7 @@@ static void nfs41_sequence_prepare(stru
        args = task->tk_msg.rpc_argp;
        res = task->tk_msg.rpc_resp;
  
 -      if (nfs41_setup_sequence(clp->cl_session, args, res, task))
 -              return;
 -      rpc_call_start(task);
 +      nfs41_setup_sequence(clp->cl_session, args, res, task);
  }
  
  static const struct rpc_call_ops nfs41_sequence_ops = {
        .rpc_release = nfs41_sequence_release,
  };
  
 -static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
 +static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
 +              struct rpc_cred *cred,
 +              bool is_privileged)
  {
        struct nfs4_sequence_data *calldata;
        struct rpc_message msg = {
                return ERR_PTR(-ENOMEM);
        }
        nfs41_init_sequence(&calldata->args, &calldata->res, 0);
 +      if (is_privileged)
 +              nfs4_set_sequence_privileged(&calldata->args);
        msg.rpc_argp = &calldata->args;
        msg.rpc_resp = &calldata->res;
        calldata->clp = clp;
@@@ -5792,7 -6186,7 +5797,7 @@@ static int nfs41_proc_async_sequence(st
  
        if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
                return 0;
 -      task = _nfs41_proc_sequence(clp, cred);
 +      task = _nfs41_proc_sequence(clp, cred, false);
        if (IS_ERR(task))
                ret = PTR_ERR(task);
        else
@@@ -5806,7 -6200,7 +5811,7 @@@ static int nfs4_proc_sequence(struct nf
        struct rpc_task *task;
        int ret;
  
 -      task = _nfs41_proc_sequence(clp, cred);
 +      task = _nfs41_proc_sequence(clp, cred, true);
        if (IS_ERR(task)) {
                ret = PTR_ERR(task);
                goto out;
@@@ -5835,10 -6229,13 +5840,10 @@@ static void nfs4_reclaim_complete_prepa
  {
        struct nfs4_reclaim_complete_data *calldata = data;
  
 -      rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
 -      if (nfs41_setup_sequence(calldata->clp->cl_session,
 -                              &calldata->arg.seq_args,
 -                              &calldata->res.seq_res, task))
 -              return;
 -
 -      rpc_call_start(task);
 +      nfs41_setup_sequence(calldata->clp->cl_session,
 +                      &calldata->arg.seq_args,
 +                      &calldata->res.seq_res,
 +                      task);
  }
  
  static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp)
@@@ -5915,7 -6312,6 +5920,7 @@@ static int nfs41_proc_reclaim_complete(
        calldata->arg.one_fs = 0;
  
        nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0);
 +      nfs4_set_sequence_privileged(&calldata->arg.seq_args);
        msg.rpc_argp = &calldata->arg;
        msg.rpc_resp = &calldata->res;
        task_setup_data.callback_data = calldata;
@@@ -5939,7 -6335,6 +5944,7 @@@ nfs4_layoutget_prepare(struct rpc_task 
  {
        struct nfs4_layoutget *lgp = calldata;
        struct nfs_server *server = NFS_SERVER(lgp->args.inode);
 +      struct nfs4_session *session = nfs4_get_session(server);
  
        dprintk("--> %s\n", __func__);
        /* Note the is a race here, where a CB_LAYOUTRECALL can come in
         * However, that is not so catastrophic, and there seems
         * to be no way to prevent it completely.
         */
 -      if (nfs4_setup_sequence(server, &lgp->args.seq_args,
 +      if (nfs41_setup_sequence(session, &lgp->args.seq_args,
                                &lgp->res.seq_res, task))
                return;
        if (pnfs_choose_layoutget_stateid(&lgp->args.stateid,
                                          NFS_I(lgp->args.inode)->layout,
                                          lgp->args.ctx->state)) {
                rpc_exit(task, NFS4_OK);
 -              return;
        }
 -      rpc_call_start(task);
  }
  
  static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
  
        dprintk("--> %s\n", __func__);
  
 -      if (!nfs4_sequence_done(task, &lgp->res.seq_res))
 +      if (!nfs41_sequence_done(task, &lgp->res.seq_res))
                goto out;
  
        switch (task->tk_status) {
@@@ -6118,10 -6515,10 +6123,10 @@@ nfs4_layoutreturn_prepare(struct rpc_ta
        struct nfs4_layoutreturn *lrp = calldata;
  
        dprintk("--> %s\n", __func__);
 -      if (nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args,
 -                              &lrp->res.seq_res, task))
 -              return;
 -      rpc_call_start(task);
 +      nfs41_setup_sequence(lrp->clp->cl_session,
 +                      &lrp->args.seq_args,
 +                      &lrp->res.seq_res,
 +                      task);
  }
  
  static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
  
        dprintk("--> %s\n", __func__);
  
 -      if (!nfs4_sequence_done(task, &lrp->res.seq_res))
 +      if (!nfs41_sequence_done(task, &lrp->res.seq_res))
                return;
  
        server = NFS_SERVER(lrp->args.inode);
@@@ -6280,12 -6677,11 +6285,12 @@@ static void nfs4_layoutcommit_prepare(s
  {
        struct nfs4_layoutcommit_data *data = calldata;
        struct nfs_server *server = NFS_SERVER(data->args.inode);
 +      struct nfs4_session *session = nfs4_get_session(server);
  
 -      if (nfs4_setup_sequence(server, &data->args.seq_args,
 -                              &data->res.seq_res, task))
 -              return;
 -      rpc_call_start(task);
 +      nfs41_setup_sequence(session,
 +                      &data->args.seq_args,
 +                      &data->res.seq_res,
 +                      task);
  }
  
  static void
@@@ -6294,7 -6690,7 +6299,7 @@@ nfs4_layoutcommit_done(struct rpc_task 
        struct nfs4_layoutcommit_data *data = calldata;
        struct nfs_server *server = NFS_SERVER(data->args.inode);
  
 -      if (!nfs4_sequence_done(task, &data->res.seq_res))
 +      if (!nfs41_sequence_done(task, &data->res.seq_res))
                return;
  
        switch (task->tk_status) { /* Just ignore these failures */
@@@ -6482,9 -6878,7 +6487,9 @@@ static int _nfs41_test_stateid(struct n
  
        dprintk("NFS call  test_stateid %p\n", stateid);
        nfs41_init_sequence(&args.seq_args, &res.seq_res, 0);
 -      status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
 +      nfs4_set_sequence_privileged(&args.seq_args);
 +      status = nfs4_call_sync_sequence(server->client, server, &msg,
 +                      &args.seq_args, &res.seq_res);
        if (status != NFS_OK) {
                dprintk("NFS reply test_stateid: failed, %d\n", status);
                return status;
@@@ -6531,9 -6925,8 +6536,9 @@@ static int _nfs4_free_stateid(struct nf
  
        dprintk("NFS call  free_stateid %p\n", stateid);
        nfs41_init_sequence(&args.seq_args, &res.seq_res, 0);
 +      nfs4_set_sequence_privileged(&args.seq_args);
        status = nfs4_call_sync_sequence(server->client, server, &msg,
 -                                       &args.seq_args, &res.seq_res, 1);
 +                      &args.seq_args, &res.seq_res);
        dprintk("NFS reply free_stateid: %d\n", status);
        return status;
  }
@@@ -6653,7 -7046,7 +6658,7 @@@ static const struct nfs4_minor_version_
  #if defined(CONFIG_NFS_V4_1)
  static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
        .minor_version = 1,
 -      .call_sync = _nfs4_call_sync_session,
 +      .call_sync = nfs4_call_sync_sequence,
        .match_stateid = nfs41_match_stateid,
        .find_root_sec = nfs41_find_root_sec,
        .reboot_recovery_ops = &nfs41_reboot_recovery_ops,
diff --combined fs/nfs/nfs4xdr.c
index e786dc7582b1b2e6f886c489c8294634ffb96f11,142aacb924590320adaca695b2152c9585195222..26b143920433e628456476e0d1b708b8fc395d43
@@@ -56,7 -56,6 +56,7 @@@
  
  #include "nfs4_fs.h"
  #include "internal.h"
 +#include "nfs4session.h"
  #include "pnfs.h"
  #include "netns.h"
  
@@@ -271,6 -270,8 +271,8 @@@ static int nfs4_stat_to_errno(int)
  
  #if defined(CONFIG_NFS_V4_1)
  #define NFS4_MAX_MACHINE_NAME_LEN (64)
+ #define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \
+                        sizeof(utsname()->version) + sizeof(utsname()->machine) + 8)
  
  #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
                                encode_verifier_maxsz + \
                                1 /* nii_domain */ + \
                                XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
                                1 /* nii_name */ + \
-                               XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
+                               XDR_QUADLEN(IMPL_NAME_LIMIT) + \
                                3 /* nii_date */)
  #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
                                2 /* eir_clientid */ + \
@@@ -937,7 -938,7 +939,7 @@@ static void encode_compound_hdr(struct 
         * but this is not required as a MUST for the server to do so. */
        hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
  
 -      BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
 +      WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN);
        encode_string(xdr, hdr->taglen, hdr->tag);
        p = reserve_space(xdr, 8);
        *p++ = cpu_to_be32(hdr->minorversion);
@@@ -956,7 -957,7 +958,7 @@@ static void encode_op_hdr(struct xdr_st
  
  static void encode_nops(struct compound_hdr *hdr)
  {
 -      BUG_ON(hdr->nops > NFS4_MAX_OPS);
 +      WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS);
        *hdr->nops_p = htonl(hdr->nops);
  }
  
@@@ -1404,6 -1405,7 +1406,6 @@@ static void encode_opentype(struct xdr_
                *p = cpu_to_be32(NFS4_OPEN_NOCREATE);
                break;
        default:
 -              BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
                *p = cpu_to_be32(NFS4_OPEN_CREATE);
                encode_createmode(xdr, arg);
        }
@@@ -1621,6 -1623,7 +1623,6 @@@ encode_setacl(struct xdr_stream *xdr, s
        p = reserve_space(xdr, 2*4);
        *p++ = cpu_to_be32(1);
        *p = cpu_to_be32(FATTR4_WORD0_ACL);
 -      BUG_ON(arg->acl_len % 4);
        p = reserve_space(xdr, 4);
        *p = cpu_to_be32(arg->acl_len);
        xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
@@@ -1712,7 -1715,7 +1714,7 @@@ static void encode_exchange_id(struct x
                               struct compound_hdr *hdr)
  {
        __be32 *p;
-       char impl_name[NFS4_OPAQUE_LIMIT];
+       char impl_name[IMPL_NAME_LIMIT];
        int len = 0;
  
        encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr);
        if (send_implementation_id &&
            sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 &&
            sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN)
-               <= NFS4_OPAQUE_LIMIT + 1)
+               <= sizeof(impl_name) + 1)
                len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s",
                               utsname()->sysname, utsname()->release,
                               utsname()->version, utsname()->machine);
@@@ -1834,16 -1837,18 +1836,16 @@@ static void encode_sequence(struct xdr_
                            struct compound_hdr *hdr)
  {
  #if defined(CONFIG_NFS_V4_1)
 -      struct nfs4_session *session = args->sa_session;
 +      struct nfs4_session *session;
        struct nfs4_slot_table *tp;
 -      struct nfs4_slot *slot;
 +      struct nfs4_slot *slot = args->sa_slot;
        __be32 *p;
  
 -      if (!session)
 +      if (slot == NULL)
                return;
  
 -      tp = &session->fc_slot_table;
 -
 -      WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
 -      slot = tp->slots + args->sa_slotid;
 +      tp = slot->table;
 +      session = tp->session;
  
        encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr);
  
                ((u32 *)session->sess_id.data)[1],
                ((u32 *)session->sess_id.data)[2],
                ((u32 *)session->sess_id.data)[3],
 -              slot->seq_nr, args->sa_slotid,
 +              slot->seq_nr, slot->slot_nr,
                tp->highest_used_slotid, args->sa_cache_this);
        p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16);
        p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
        *p++ = cpu_to_be32(slot->seq_nr);
 -      *p++ = cpu_to_be32(args->sa_slotid);
 +      *p++ = cpu_to_be32(slot->slot_nr);
        *p++ = cpu_to_be32(tp->highest_used_slotid);
        *p = cpu_to_be32(args->sa_cache_this);
  #endif /* CONFIG_NFS_V4_1 */
@@@ -2024,9 -2029,8 +2026,9 @@@ static void encode_free_stateid(struct 
  static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
  {
  #if defined(CONFIG_NFS_V4_1)
 -      if (args->sa_session)
 -              return args->sa_session->clp->cl_mvops->minor_version;
 +
 +      if (args->sa_slot)
 +              return args->sa_slot->table->session->clp->cl_mvops->minor_version;
  #endif /* CONFIG_NFS_V4_1 */
        return 0;
  }
@@@ -5507,13 -5511,12 +5509,13 @@@ static int decode_sequence(struct xdr_s
                           struct rpc_rqst *rqstp)
  {
  #if defined(CONFIG_NFS_V4_1)
 +      struct nfs4_session *session;
        struct nfs4_sessionid id;
        u32 dummy;
        int status;
        __be32 *p;
  
 -      if (!res->sr_session)
 +      if (res->sr_slot == NULL)
                return 0;
  
        status = decode_op_hdr(xdr, OP_SEQUENCE);
         * sequence number, the server is looney tunes.
         */
        status = -EREMOTEIO;
 +      session = res->sr_slot->table->session;
  
 -      if (memcmp(id.data, res->sr_session->sess_id.data,
 +      if (memcmp(id.data, session->sess_id.data,
                   NFS4_MAX_SESSIONID_LEN)) {
                dprintk("%s Invalid session id\n", __func__);
                goto out_err;
        }
        /* slot id */
        dummy = be32_to_cpup(p++);
 -      if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
 +      if (dummy != res->sr_slot->slot_nr) {
                dprintk("%s Invalid slot id\n", __func__);
                goto out_err;
        }
 -      /* highest slot id - currently not processed */
 -      dummy = be32_to_cpup(p++);
 -      /* target highest slot id - currently not processed */
 -      dummy = be32_to_cpup(p++);
 +      /* highest slot id */
 +      res->sr_highest_slotid = be32_to_cpup(p++);
 +      /* target highest slot id */
 +      res->sr_target_highest_slotid = be32_to_cpup(p++);
        /* result flags */
        res->sr_status_flags = be32_to_cpup(p);
        status = 0;
diff --combined fs/nfs/write.c
index f5bc8e11713ba82f8861b9727e5ade4aedbe68ac,eecd8b879afe85285c408e95954f30d7c55cd04f..f608ca606b2b19f32f9bcbc813854e9c6aa50a0b
@@@ -239,18 -239,21 +239,18 @@@ int nfs_congestion_kb
  #define NFS_CONGESTION_OFF_THRESH     \
        (NFS_CONGESTION_ON_THRESH - (NFS_CONGESTION_ON_THRESH >> 2))
  
 -static int nfs_set_page_writeback(struct page *page)
 +static void nfs_set_page_writeback(struct page *page)
  {
 +      struct nfs_server *nfss = NFS_SERVER(page_file_mapping(page)->host);
        int ret = test_set_page_writeback(page);
  
 -      if (!ret) {
 -              struct inode *inode = page_file_mapping(page)->host;
 -              struct nfs_server *nfss = NFS_SERVER(inode);
 +      WARN_ON_ONCE(ret != 0);
  
 -              if (atomic_long_inc_return(&nfss->writeback) >
 -                              NFS_CONGESTION_ON_THRESH) {
 -                      set_bdi_congested(&nfss->backing_dev_info,
 -                                              BLK_RW_ASYNC);
 -              }
 +      if (atomic_long_inc_return(&nfss->writeback) >
 +                      NFS_CONGESTION_ON_THRESH) {
 +              set_bdi_congested(&nfss->backing_dev_info,
 +                                      BLK_RW_ASYNC);
        }
 -      return ret;
  }
  
  static void nfs_end_page_writeback(struct page *page)
@@@ -312,10 -315,10 +312,10 @@@ static int nfs_page_async_flush(struct 
        if (IS_ERR(req))
                goto out;
  
 -      ret = nfs_set_page_writeback(page);
 -      BUG_ON(ret != 0);
 -      BUG_ON(test_bit(PG_CLEAN, &req->wb_flags));
 +      nfs_set_page_writeback(page);
 +      WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
  
 +      ret = 0;
        if (!nfs_pageio_add_request(pgio, req)) {
                nfs_redirty_request(req);
                ret = pgio->pg_error;
@@@ -448,6 -451,8 +448,6 @@@ static void nfs_inode_remove_request(st
        struct inode *inode = req->wb_context->dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
  
 -      BUG_ON (!NFS_WBACK_BUSY(req));
 -
        spin_lock(&inode->i_lock);
        if (likely(!PageSwapCache(req->wb_page))) {
                set_page_private(req->wb_page, 0);
@@@ -879,7 -884,7 +879,7 @@@ static bool nfs_write_pageuptodate(stru
  {
        if (nfs_have_delegated_attributes(inode))
                goto out;
-       if (NFS_I(inode)->cache_validity & NFS_INO_REVAL_PAGECACHE)
+       if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE))
                return false;
  out:
        return PageUptodate(page) != 0;
@@@ -1722,6 -1727,7 +1722,6 @@@ int nfs_wb_page_cancel(struct inode *in
        struct nfs_page *req;
        int ret = 0;
  
 -      BUG_ON(!PageLocked(page));
        for (;;) {
                wait_on_page_writeback(page);
                req = nfs_page_find_request(page);
@@@ -1823,7 -1829,7 +1823,7 @@@ int __init nfs_init_writepagecache(void
                goto out_destroy_write_mempool;
  
        nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT,
-                                                     nfs_wdata_cachep);
+                                                     nfs_cdata_cachep);
        if (nfs_commit_mempool == NULL)
                goto out_destroy_commit_cache;
  
diff --combined net/sunrpc/rpc_pipe.c
index 3128a1503d8e1da1f5682793f5ceee7f578e90a6,e659def7774295794511679c75440ae971216bbf..fd10981ea7921774e54f19808b1c9fa9964d4d3d
@@@ -1093,7 -1093,7 +1093,7 @@@ void rpc_put_sb_net(const struct net *n
  {
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  
 -      BUG_ON(sn->pipefs_sb == NULL);
 +      WARN_ON(sn->pipefs_sb == NULL);
        mutex_unlock(&sn->pipefs_sb_lock);
  }
  EXPORT_SYMBOL_GPL(rpc_put_sb_net);
@@@ -1152,14 -1152,19 +1152,19 @@@ static void rpc_kill_sb(struct super_bl
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  
        mutex_lock(&sn->pipefs_sb_lock);
+       if (sn->pipefs_sb != sb) {
+               mutex_unlock(&sn->pipefs_sb_lock);
+               goto out;
+       }
        sn->pipefs_sb = NULL;
        mutex_unlock(&sn->pipefs_sb_lock);
-       put_net(net);
        dprintk("RPC:       sending pipefs UMOUNT notification for net %p%s\n",
                net, NET_NAME(net));
        blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
                                           RPC_PIPEFS_UMOUNT,
                                           sb);
+       put_net(net);
+ out:
        kill_litter_super(sb);
  }