Merge branch 'nfs-for-3.1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2011 20:23:02 +0000 (13:23 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2011 20:23:02 +0000 (13:23 -0700)
* 'nfs-for-3.1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (44 commits)
  NFSv4: Don't use the delegation->inode in nfs_mark_return_delegation()
  nfs: don't use d_move in nfs_async_rename_done
  RDMA: Increasing RPCRDMA_MAX_DATA_SEGS
  SUNRPC: Replace xprt->resend and xprt->sending with a priority queue
  SUNRPC: Allow caller of rpc_sleep_on() to select priority levels
  SUNRPC: Support dynamic slot allocation for TCP connections
  SUNRPC: Clean up the slot table allocation
  SUNRPC: Initalise the struct xprt upon allocation
  SUNRPC: Ensure that we grab the XPRT_LOCK before calling xprt_alloc_slot
  pnfs: simplify pnfs files module autoloading
  nfs: document nfsv4 sillyrename issues
  NFS: Convert nfs4_set_ds_client to EXPORT_SYMBOL_GPL
  SUNRPC: Convert the backchannel exports to EXPORT_SYMBOL_GPL
  SUNRPC: sunrpc should not explicitly depend on NFS config options
  NFS: Clean up - simplify the switch to read/write-through-MDS
  NFS: Move the pnfs write code into pnfs.c
  NFS: Move the pnfs read code into pnfs.c
  NFS: Allow the nfs_pageio_descriptor to signal that a re-coalesce is needed
  NFS: Use the nfs_pageio_descriptor->pg_bsize in the read/write request
  NFS: Cache rpc_ops in struct nfs_pageio_descriptor
  ...

1  2 
fs/nfs/write.c
include/linux/nfs_fs_sb.h
include/linux/sunrpc/svc.h
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/xprt_rdma.h

diff --combined fs/nfs/write.c
@@@ -97,7 -97,7 +97,7 @@@ void nfs_writedata_free(struct nfs_writ
        mempool_free(p, nfs_wdata_mempool);
  }
  
static void nfs_writedata_release(struct nfs_write_data *wdata)
+ void nfs_writedata_release(struct nfs_write_data *wdata)
  {
        put_lseg(wdata->lseg);
        put_nfs_open_context(wdata->args.context);
@@@ -845,11 -845,9 +845,9 @@@ EXPORT_SYMBOL_GPL(nfs_initiate_write)
  /*
   * Set up the argument/result storage required for the RPC call.
   */
- static int nfs_write_rpcsetup(struct nfs_page *req,
+ static void nfs_write_rpcsetup(struct nfs_page *req,
                struct nfs_write_data *data,
-               const struct rpc_call_ops *call_ops,
                unsigned int count, unsigned int offset,
-               struct pnfs_layout_segment *lseg,
                int how)
  {
        struct inode *inode = req->wb_context->dentry->d_inode;
        data->req = req;
        data->inode = inode = req->wb_context->dentry->d_inode;
        data->cred = req->wb_context->cred;
-       data->lseg = get_lseg(lseg);
  
        data->args.fh     = NFS_FH(inode);
        data->args.offset = req_offset(req) + offset;
        data->args.context = get_nfs_open_context(req->wb_context);
        data->args.lock_context = req->wb_lock_context;
        data->args.stable  = NFS_UNSTABLE;
-       if (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) {
-               data->args.stable = NFS_DATA_SYNC;
-               if (!nfs_need_commit(NFS_I(inode)))
-                       data->args.stable = NFS_FILE_SYNC;
+       switch (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) {
+       case 0:
+               break;
+       case FLUSH_COND_STABLE:
+               if (nfs_need_commit(NFS_I(inode)))
+                       break;
+       default:
+               data->args.stable = NFS_FILE_SYNC;
        }
  
        data->res.fattr   = &data->fattr;
        data->res.count   = count;
        data->res.verf    = &data->verf;
        nfs_fattr_init(&data->fattr);
+ }
  
-       if (data->lseg &&
-           (pnfs_try_to_write_data(data, call_ops, how) == PNFS_ATTEMPTED))
-               return 0;
+ static int nfs_do_write(struct nfs_write_data *data,
+               const struct rpc_call_ops *call_ops,
+               int how)
+ {
+       struct inode *inode = data->args.context->dentry->d_inode;
  
        return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how);
  }
  
+ static int nfs_do_multiple_writes(struct list_head *head,
+               const struct rpc_call_ops *call_ops,
+               int how)
+ {
+       struct nfs_write_data *data;
+       int ret = 0;
+       while (!list_empty(head)) {
+               int ret2;
+               data = list_entry(head->next, struct nfs_write_data, list);
+               list_del_init(&data->list);
+               
+               ret2 = nfs_do_write(data, call_ops, how);
+                if (ret == 0)
+                        ret = ret2;
+       }
+       return ret;
+ }
  /* If a nfs_flush_* function fails, it should remove reqs from @head and
   * call this on each, which will prepare them to be retried on next
   * writeback using standard nfs.
@@@ -907,17 -931,15 +931,15 @@@ static void nfs_redirty_request(struct 
   * Generate multiple small requests to write out a single
   * contiguous dirty area on one page.
   */
- static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
+ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head *res)
  {
        struct nfs_page *req = nfs_list_entry(desc->pg_list.next);
        struct page *page = req->wb_page;
        struct nfs_write_data *data;
-       size_t wsize = NFS_SERVER(desc->pg_inode)->wsize, nbytes;
+       size_t wsize = desc->pg_bsize, nbytes;
        unsigned int offset;
        int requests = 0;
        int ret = 0;
-       struct pnfs_layout_segment *lseg;
-       LIST_HEAD(list);
  
        nfs_list_remove_request(req);
  
                desc->pg_ioflags &= ~FLUSH_COND_STABLE;
  
  
+       offset = 0;
        nbytes = desc->pg_count;
        do {
                size_t len = min(nbytes, wsize);
                data = nfs_writedata_alloc(1);
                if (!data)
                        goto out_bad;
-               list_add(&data->pages, &list);
+               data->pagevec[0] = page;
+               nfs_write_rpcsetup(req, data, wsize, offset, desc->pg_ioflags);
+               list_add(&data->list, res);
                requests++;
                nbytes -= len;
+               offset += len;
        } while (nbytes != 0);
        atomic_set(&req->wb_complete, requests);
-       BUG_ON(desc->pg_lseg);
-       lseg = pnfs_update_layout(desc->pg_inode, req->wb_context,
-                                 req_offset(req), desc->pg_count,
-                                 IOMODE_RW, GFP_NOFS);
-       ClearPageError(page);
-       offset = 0;
-       nbytes = desc->pg_count;
-       do {
-               int ret2;
-               data = list_entry(list.next, struct nfs_write_data, pages);
-               list_del_init(&data->pages);
-               data->pagevec[0] = page;
-               if (nbytes < wsize)
-                       wsize = nbytes;
-               ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
-                                         wsize, offset, lseg, desc->pg_ioflags);
-               if (ret == 0)
-                       ret = ret2;
-               offset += wsize;
-               nbytes -= wsize;
-       } while (nbytes != 0);
-       put_lseg(lseg);
-       desc->pg_lseg = NULL;
+       desc->pg_rpc_callops = &nfs_write_partial_ops;
        return ret;
  
  out_bad:
-       while (!list_empty(&list)) {
-               data = list_entry(list.next, struct nfs_write_data, pages);
-               list_del(&data->pages);
+       while (!list_empty(res)) {
+               data = list_entry(res->next, struct nfs_write_data, list);
+               list_del(&data->list);
                nfs_writedata_free(data);
        }
        nfs_redirty_request(req);
   * This is the case if nfs_updatepage detects a conflicting request
   * that has been written but not committed.
   */
- static int nfs_flush_one(struct nfs_pageio_descriptor *desc)
+ static int nfs_flush_one(struct nfs_pageio_descriptor *desc, struct list_head *res)
  {
        struct nfs_page         *req;
        struct page             **pages;
        struct nfs_write_data   *data;
        struct list_head *head = &desc->pg_list;
-       struct pnfs_layout_segment *lseg = desc->pg_lseg;
-       int ret;
+       int ret = 0;
  
        data = nfs_writedata_alloc(nfs_page_array_len(desc->pg_base,
                                                      desc->pg_count));
                *pages++ = req->wb_page;
        }
        req = nfs_list_entry(data->pages.next);
-       if ((!lseg) && list_is_singular(&data->pages))
-               lseg = pnfs_update_layout(desc->pg_inode, req->wb_context,
-                                         req_offset(req), desc->pg_count,
-                                         IOMODE_RW, GFP_NOFS);
  
        if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
            (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit))
                desc->pg_ioflags &= ~FLUSH_COND_STABLE;
  
        /* Set up the argument struct */
-       ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags);
+       nfs_write_rpcsetup(req, data, desc->pg_count, 0, desc->pg_ioflags);
+       list_add(&data->list, res);
+       desc->pg_rpc_callops = &nfs_write_full_ops;
  out:
-       put_lseg(lseg); /* Cleans any gotten in ->pg_test */
-       desc->pg_lseg = NULL;
        return ret;
  }
  
- static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
+ int nfs_generic_flush(struct nfs_pageio_descriptor *desc, struct list_head *head)
+ {
+       if (desc->pg_bsize < PAGE_CACHE_SIZE)
+               return nfs_flush_multi(desc, head);
+       return nfs_flush_one(desc, head);
+ }
+ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
+ {
+       LIST_HEAD(head);
+       int ret;
+       ret = nfs_generic_flush(desc, &head);
+       if (ret == 0)
+               ret = nfs_do_multiple_writes(&head, desc->pg_rpc_callops,
+                               desc->pg_ioflags);
+       return ret;
+ }
+ static const struct nfs_pageio_ops nfs_pageio_write_ops = {
+       .pg_test = nfs_generic_pg_test,
+       .pg_doio = nfs_generic_pg_writepages,
+ };
+ static void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
                                  struct inode *inode, int ioflags)
  {
-       size_t wsize = NFS_SERVER(inode)->wsize;
+       nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops,
+                               NFS_SERVER(inode)->wsize, ioflags);
+ }
  
-       if (wsize < PAGE_CACHE_SIZE)
-               nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);
-       else
-               nfs_pageio_init(pgio, inode, nfs_flush_one, wsize, ioflags);
+ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
+ {
+       pgio->pg_ops = &nfs_pageio_write_ops;
+       pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->wsize;
+ }
+ EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);
+ static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
+                                 struct inode *inode, int ioflags)
+ {
+       if (!pnfs_pageio_init_write(pgio, inode, ioflags))
+               nfs_pageio_init_write_mds(pgio, inode, ioflags);
  }
  
  /*
@@@ -1566,7 -1594,8 +1594,7 @@@ int nfs_write_inode(struct inode *inode
                int status;
                bool sync = true;
  
 -              if (wbc->sync_mode == WB_SYNC_NONE || wbc->nonblocking ||
 -                  wbc->for_background)
 +              if (wbc->sync_mode == WB_SYNC_NONE)
                        sync = false;
  
                status = pnfs_layoutcommit_inode(inode, sync);
@@@ -7,7 -7,7 +7,7 @@@
  #include <linux/nfs_xdr.h>
  #include <linux/sunrpc/xprt.h>
  
 -#include <asm/atomic.h>
 +#include <linux/atomic.h>
  
  struct nfs4_session;
  struct nfs_iostats;
@@@ -16,6 -16,7 +16,7 @@@ struct nfs4_sequence_args
  struct nfs4_sequence_res;
  struct nfs_server;
  struct nfs4_minor_version_ops;
+ struct server_scope;
  
  /*
   * The nfs_client identifies our client state to the server.
@@@ -77,12 -78,13 +78,13 @@@ struct nfs_client 
        /* The flags used for obtaining the clientid during EXCHANGE_ID */
        u32                     cl_exchange_flags;
        struct nfs4_session     *cl_session;    /* sharred session */
-       struct list_head        cl_layouts;
  #endif /* CONFIG_NFS_V4 */
  
  #ifdef CONFIG_NFS_FSCACHE
        struct fscache_cookie   *fscache;       /* client index cache cookie */
  #endif
+       struct server_scope     *server_scope;  /* from exchange_id */
  };
  
  /*
@@@ -149,6 -151,7 +151,7 @@@ struct nfs_server 
        struct rb_root          openowner_id;
        struct rb_root          lockowner_id;
  #endif
+       struct list_head        layouts;
        struct list_head        delegations;
        void (*destroy)(struct nfs_server *);
  
@@@ -92,7 -92,7 +92,7 @@@ struct svc_serv 
        struct module *         sv_module;      /* optional module to count when
                                                 * adding threads */
        svc_thread_fn           sv_function;    /* main function for threads */
- #if defined(CONFIG_NFS_V4_1)
+ #if defined(CONFIG_SUNRPC_BACKCHANNEL)
        struct list_head        sv_cb_list;     /* queue for callback requests
                                                 * that arrive over the same
                                                 * connection */
        wait_queue_head_t       sv_cb_waitq;    /* sleep here if there are no
                                                 * entries in the svc_cb_list */
        struct svc_xprt         *sv_bc_xprt;    /* callback on fore channel */
- #endif /* CONFIG_NFS_V4_1 */
+ #endif /* CONFIG_SUNRPC_BACKCHANNEL */
  };
  
  /*
@@@ -273,7 -273,6 +273,7 @@@ struct svc_rqst 
        /* Catering to nfsd */
        struct auth_domain *    rq_client;      /* RPC peer info */
        struct auth_domain *    rq_gssclient;   /* "gss/"-style peer info */
 +      int                     rq_cachetype;
        struct svc_cacherep *   rq_cacherep;    /* cache info */
        int                     rq_splice_ok;   /* turned off in gss privacy
                                                 * to prevent encrypting page
diff --combined net/sunrpc/svcsock.c
@@@ -51,8 -51,6 +51,8 @@@
  #include <linux/sunrpc/stats.h>
  #include <linux/sunrpc/xprt.h>
  
 +#include "sunrpc.h"
 +
  #define RPCDBG_FACILITY       RPCDBG_SVCXPRT
  
  
@@@ -68,12 -66,12 +68,12 @@@ static void                svc_sock_free(struct svc_x
  static struct svc_xprt *svc_create_socket(struct svc_serv *, int,
                                          struct net *, struct sockaddr *,
                                          int, int);
- #if defined(CONFIG_NFS_V4_1)
+ #if defined(CONFIG_SUNRPC_BACKCHANNEL)
  static struct svc_xprt *svc_bc_create_socket(struct svc_serv *, int,
                                             struct net *, struct sockaddr *,
                                             int, int);
  static void svc_bc_sock_free(struct svc_xprt *xprt);
- #endif /* CONFIG_NFS_V4_1 */
+ #endif /* CONFIG_SUNRPC_BACKCHANNEL */
  
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  static struct lock_class_key svc_key[2];
@@@ -1243,7 -1241,7 +1243,7 @@@ static struct svc_xprt *svc_tcp_create(
        return svc_create_socket(serv, IPPROTO_TCP, net, sa, salen, flags);
  }
  
- #if defined(CONFIG_NFS_V4_1)
+ #if defined(CONFIG_SUNRPC_BACKCHANNEL)
  static struct svc_xprt *svc_bc_create_socket(struct svc_serv *, int,
                                             struct net *, struct sockaddr *,
                                             int, int);
@@@ -1284,7 -1282,7 +1284,7 @@@ static void svc_cleanup_bc_xprt_sock(vo
  {
        svc_unreg_xprt_class(&svc_tcp_bc_class);
  }
- #else /* CONFIG_NFS_V4_1 */
+ #else /* CONFIG_SUNRPC_BACKCHANNEL */
  static void svc_init_bc_xprt_sock(void)
  {
  }
  static void svc_cleanup_bc_xprt_sock(void)
  {
  }
- #endif /* CONFIG_NFS_V4_1 */
+ #endif /* CONFIG_SUNRPC_BACKCHANNEL */
  
  static struct svc_xprt_ops svc_tcp_ops = {
        .xpo_create = svc_tcp_create,
@@@ -1623,7 -1621,7 +1623,7 @@@ static void svc_sock_free(struct svc_xp
        kfree(svsk);
  }
  
- #if defined(CONFIG_NFS_V4_1)
+ #if defined(CONFIG_SUNRPC_BACKCHANNEL)
  /*
   * Create a back channel svc_xprt which shares the fore channel socket.
   */
@@@ -1662,4 -1660,4 +1662,4 @@@ static void svc_bc_sock_free(struct svc
        if (xprt)
                kfree(container_of(xprt, struct svc_sock, sk_xprt));
  }
- #endif /* CONFIG_NFS_V4_1 */
+ #endif /* CONFIG_SUNRPC_BACKCHANNEL */
@@@ -42,7 -42,7 +42,7 @@@
  
  #include <linux/wait.h>               /* wait_queue_head_t, etc */
  #include <linux/spinlock.h>           /* spinlock_t, etc */
 -#include <asm/atomic.h>                       /* atomic_t, etc */
 +#include <linux/atomic.h>                     /* atomic_t, etc */
  
  #include <rdma/rdma_cm.h>             /* RDMA connection api */
  #include <rdma/ib_verbs.h>            /* RDMA verbs api */
@@@ -109,7 -109,7 +109,7 @@@ struct rpcrdma_ep 
   */
  
  /* temporary static scatter/gather max */
- #define RPCRDMA_MAX_DATA_SEGS (8)     /* max scatter/gather */
+ #define RPCRDMA_MAX_DATA_SEGS (64)    /* max scatter/gather */
  #define RPCRDMA_MAX_SEGS      (RPCRDMA_MAX_DATA_SEGS + 2) /* head+tail = 2 */
  #define MAX_RPCRDMAHDR        (\
        /* max supported RPC/RDMA header */ \