[PATCH 2/2] pnfs: fix pnfs_commit update_layout range

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Andy Adamson <andros@xxxxxxxxxx>

Whole file semantics are different for COMMIT (0,0) and layouts
(0,NFS4_MAX_UINT64).

Reported-by: Alexandros Batsakis <batsakis@xxxxxxxxxx>

Translate COMMIT whole file semantics to LAYOUTGET whole file semantics.

The LAYOUTGET request uses u64 length, change pnfs_update_layout() count field
type to match.

Replace PAGE_SIZE with PAGE_CACHE_SIZE and PAGE_CACHE_SHIFT.

Signed-off-by: Andy Adamson <andros@xxxxxxxxxx>
---
 fs/nfs/pnfs.c |   36 ++++++++++++++++++++++++++++--------
 fs/nfs/pnfs.h |    2 +-
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 674d8b7..ffed515 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1052,7 +1052,7 @@ void drain_layoutreturns(struct pnfs_layout_type *lo)
 int
 pnfs_update_layout(struct inode *ino,
 		   struct nfs_open_context *ctx,
-		   size_t count,
+		   u64 count,
 		   loff_t pos,
 		   enum pnfs_iomode iomode,
 		   struct pnfs_layout_segment **lsegpp)
@@ -1518,17 +1518,29 @@ pnfs_update_layout_commit(struct inode *inode,
 {
 	struct nfs_server *nfss = NFS_SERVER(inode);
 	struct nfs_page *nfs_page = nfs_list_entry(head->next);
+	u64 count;
+	loff_t start;
 	int status;
 
 	dprintk("--> %s inode %p layout range: %Zd@%llu\n", __func__, inode,
-		(size_t)(npages * PAGE_SIZE),
-		(u64)((u64)idx_start * PAGE_SIZE));
+		(size_t)(npages * PAGE_CACHE_SIZE),
+		(u64)((u64)idx_start << PAGE_CACHE_SHIFT));
 
 	if (!pnfs_enabled_sb(nfss))
 		return;
+
+	/* COMMIT indicates the whole file with offset = count = 0
+	 * whereas layout segments indicate whole file with offset = 0,
+	 * count = NFS4_MAX_UINT64.
+	 */
+	count = (size_t)npages * PAGE_CACHE_SIZE;
+	start = (loff_t)idx_start <<  PAGE_CACHE_SHIFT;
+	if (start == 0 && count == 0)
+		count = NFS4_MAX_UINT64;
+
 	status = pnfs_update_layout(inode, nfs_page->wb_context,
-				(size_t)npages * PAGE_SIZE,
-				(loff_t)idx_start * PAGE_SIZE,
+				count,
+				start,
 				IOMODE_RW,
 				NULL);
 	dprintk("%s  virt update status %d\n", __func__, status);
@@ -2057,6 +2069,7 @@ pnfs_commit(struct nfs_write_data *data, int sync)
 	struct nfs_page *first, *last, *p;
 	int npages;
 	enum pnfs_try_status trypnfs;
+	u64 count;
 
 	dprintk("%s: Begin\n", __func__);
 
@@ -2069,6 +2082,15 @@ pnfs_commit(struct nfs_write_data *data, int sync)
 		last = p;
 		npages++;
 	}
+	/* COMMIT indicates the whole file with offset = count = 0
+	 * whereas layout segments indicate whole file with offset = 0,
+	 * count = NFS4_MAX_UINT64.
+	 */
+	count = ((npages - 1) << PAGE_CACHE_SHIFT) + first->wb_bytes +
+		(first != last) ? last->wb_bytes : 0;
+	if (first->wb_offset == 0 && count == 0)
+		count = NFS4_MAX_UINT64;
+
 	/* FIXME: we really ought to keep the layout segment that we used
 	   to write the page around for committing it and never ask for a
 	   new one.  If it was recalled we better commit the data first
@@ -2076,9 +2098,7 @@ pnfs_commit(struct nfs_write_data *data, int sync)
 	   either with a new layout or to the MDS */
 	result = pnfs_update_layout(data->inode,
 				    NULL,
-				    ((npages - 1) << PAGE_CACHE_SHIFT) +
-				     first->wb_bytes +
-				     (first != last) ? last->wb_bytes : 0,
+				    count,
 				    first->wb_offset,
 				    IOMODE_RW,
 				    &lseg);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index b06fde4..2f5dae4 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -34,7 +34,7 @@ extern int pnfs4_proc_layoutreturn(struct nfs4_pnfs_layoutreturn *lrp);
 extern const nfs4_stateid zero_stateid;
 
 int pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
-	size_t count, loff_t pos, enum pnfs_iomode access_type,
+	u64 count, loff_t pos, enum pnfs_iomode access_type,
 	struct pnfs_layout_segment **lsegpp);
 
 int _pnfs_return_layout(struct inode *, struct nfs4_pnfs_layout_segment *,
-- 
1.6.2.5

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux