Merge tag 'nfs-for-3.16-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Jun 2014 22:02:42 +0000 (15:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Jun 2014 22:02:42 +0000 (15:02 -0700)
Pull NFS client updates from Trond Myklebust:
 "Highlights include:

   - massive cleanup of the NFS read/write code by Anna and Dros
   - support multiple NFS read/write requests per page in order to deal
     with non-page aligned pNFS striping.  Also cleans up the r/wsize <
     page size code nicely.
   - stable fix for ensuring inode is declared uptodate only after all
     the attributes have been checked.
   - stable fix for a kernel Oops when remounting
   - NFS over RDMA client fixes
   - move the pNFS files layout driver into its own subdirectory"

* tag 'nfs-for-3.16-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (79 commits)
  NFS: populate ->net in mount data when remounting
  pnfs: fix lockup caused by pnfs_generic_pg_test
  NFSv4.1: Fix typo in dprintk
  NFSv4.1: Comment is now wrong and redundant to code
  NFS: Use raw_write_seqcount_begin/end int nfs4_reclaim_open_state
  xprtrdma: Disconnect on registration failure
  xprtrdma: Remove BUG_ON() call sites
  xprtrdma: Avoid deadlock when credit window is reset
  SUNRPC: Move congestion window constants to header file
  xprtrdma: Reset connection timeout after successful reconnect
  xprtrdma: Use macros for reconnection timeout constants
  xprtrdma: Allocate missing pagelist
  xprtrdma: Remove Tavor MTU setting
  xprtrdma: Ensure ia->ri_id->qp is not NULL when reconnecting
  xprtrdma: Reduce the number of hardway buffer allocations
  xprtrdma: Limit work done by completion handler
  xprtrmda: Reduce calls to ib_poll_cq() in completion handlers
  xprtrmda: Reduce lock contention in completion handlers
  xprtrdma: Split the completion queue
  xprtrdma: Make rpcrdma_ep_destroy() return void
  ...

1  2 
fs/nfs/filelayout/filelayoutdev.c
fs/nfs/inode.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/write.c
include/linux/sunrpc/xprt.h
net/sunrpc/xprt.c

Simple merge
diff --cc fs/nfs/inode.c
Simple merge
Simple merge
Simple merge
@@@ -133,6 -138,151 +138,151 @@@ nfs_iocounter_wait(struct nfs_io_counte
        return __nfs_iocounter_wait(c);
  }
  
 -      smp_mb__before_clear_bit();
+ static int nfs_wait_bit_uninterruptible(void *word)
+ {
+       io_schedule();
+       return 0;
+ }
+ /*
+  * nfs_page_group_lock - lock the head of the page group
+  * @req - request in group that is to be locked
+  *
+  * this lock must be held if modifying the page group list
+  */
+ void
+ nfs_page_group_lock(struct nfs_page *req)
+ {
+       struct nfs_page *head = req->wb_head;
+       WARN_ON_ONCE(head != head->wb_head);
+       wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK,
+                       nfs_wait_bit_uninterruptible,
+                       TASK_UNINTERRUPTIBLE);
+ }
+ /*
+  * nfs_page_group_unlock - unlock the head of the page group
+  * @req - request in group that is to be unlocked
+  */
+ void
+ nfs_page_group_unlock(struct nfs_page *req)
+ {
+       struct nfs_page *head = req->wb_head;
+       WARN_ON_ONCE(head != head->wb_head);
 -      smp_mb__after_clear_bit();
++      smp_mb__before_atomic();
+       clear_bit(PG_HEADLOCK, &head->wb_flags);
++      smp_mb__after_atomic();
+       wake_up_bit(&head->wb_flags, PG_HEADLOCK);
+ }
+ /*
+  * nfs_page_group_sync_on_bit_locked
+  *
+  * must be called with page group lock held
+  */
+ static bool
+ nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit)
+ {
+       struct nfs_page *head = req->wb_head;
+       struct nfs_page *tmp;
+       WARN_ON_ONCE(!test_bit(PG_HEADLOCK, &head->wb_flags));
+       WARN_ON_ONCE(test_and_set_bit(bit, &req->wb_flags));
+       tmp = req->wb_this_page;
+       while (tmp != req) {
+               if (!test_bit(bit, &tmp->wb_flags))
+                       return false;
+               tmp = tmp->wb_this_page;
+       }
+       /* true! reset all bits */
+       tmp = req;
+       do {
+               clear_bit(bit, &tmp->wb_flags);
+               tmp = tmp->wb_this_page;
+       } while (tmp != req);
+       return true;
+ }
+ /*
+  * nfs_page_group_sync_on_bit - set bit on current request, but only
+  *   return true if the bit is set for all requests in page group
+  * @req - request in page group
+  * @bit - PG_* bit that is used to sync page group
+  */
+ bool nfs_page_group_sync_on_bit(struct nfs_page *req, unsigned int bit)
+ {
+       bool ret;
+       nfs_page_group_lock(req);
+       ret = nfs_page_group_sync_on_bit_locked(req, bit);
+       nfs_page_group_unlock(req);
+       return ret;
+ }
+ /*
+  * nfs_page_group_init - Initialize the page group linkage for @req
+  * @req - a new nfs request
+  * @prev - the previous request in page group, or NULL if @req is the first
+  *         or only request in the group (the head).
+  */
+ static inline void
+ nfs_page_group_init(struct nfs_page *req, struct nfs_page *prev)
+ {
+       WARN_ON_ONCE(prev == req);
+       if (!prev) {
+               req->wb_head = req;
+               req->wb_this_page = req;
+       } else {
+               WARN_ON_ONCE(prev->wb_this_page != prev->wb_head);
+               WARN_ON_ONCE(!test_bit(PG_HEADLOCK, &prev->wb_head->wb_flags));
+               req->wb_head = prev->wb_head;
+               req->wb_this_page = prev->wb_this_page;
+               prev->wb_this_page = req;
+               /* grab extra ref if head request has extra ref from
+                * the write/commit path to handle handoff between write
+                * and commit lists */
+               if (test_bit(PG_INODE_REF, &prev->wb_head->wb_flags))
+                       kref_get(&req->wb_kref);
+       }
+ }
+ /*
+  * nfs_page_group_destroy - sync the destruction of page groups
+  * @req - request that no longer needs the page group
+  *
+  * releases the page group reference from each member once all
+  * members have called this function.
+  */
+ static void
+ nfs_page_group_destroy(struct kref *kref)
+ {
+       struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
+       struct nfs_page *tmp, *next;
+       if (!nfs_page_group_sync_on_bit(req, PG_TEARDOWN))
+               return;
+       tmp = req;
+       do {
+               next = tmp->wb_this_page;
+               /* unlink and free */
+               tmp->wb_this_page = tmp;
+               tmp->wb_head = tmp;
+               nfs_free_request(tmp);
+               tmp = next;
+       } while (tmp != req);
+ }
  /**
   * nfs_create_request - Create an NFS read/write request.
   * @ctx: open context to use
diff --cc fs/nfs/pnfs.c
Simple merge
diff --cc fs/nfs/pnfs.h
Simple merge
diff --cc fs/nfs/write.c
Simple merge
Simple merge
Simple merge