aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2011-03-03 10:13:44 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-11 15:38:44 -0500
commit44b83799a922a153957c65ccfc985a8c902958c8 (patch)
tree4dad6ec4655a876c3f12a15919fad407fd22ef59
parent5053aa568d4017aeb1fa35247d4ad96be262920f (diff)
NFSv4.1: trigger LAYOUTGET for writes
Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/pnfs.c22
-rw-r--r--fs/nfs/pnfs.h7
-rw-r--r--fs/nfs/write.c32
3 files changed, 49 insertions, 12 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 3e545144a0b2..5f205d31d96c 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -873,6 +873,28 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
873 pgio->pg_test = (ld && ld->pg_test) ? pnfs_read_pg_test : NULL; 873 pgio->pg_test = (ld && ld->pg_test) ? pnfs_read_pg_test : NULL;
874} 874}
875 875
876static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio,
877 struct nfs_page *prev,
878 struct nfs_page *req)
879{
880 if (pgio->pg_count == prev->wb_bytes) {
881 /* This is first coelesce call for a series of nfs_pages */
882 pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
883 prev->wb_context,
884 IOMODE_RW);
885 }
886 return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
887}
888
889void
890pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode)
891{
892 struct pnfs_layoutdriver_type *ld;
893
894 ld = NFS_SERVER(inode)->pnfs_curr_ld;
895 pgio->pg_test = (ld && ld->pg_test) ? pnfs_write_pg_test : NULL;
896}
897
876/* 898/*
877 * Call the appropriate parallel I/O subsystem read function. 899 * Call the appropriate parallel I/O subsystem read function.
878 */ 900 */
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index acbb77802075..1d4e6317fa95 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -123,6 +123,7 @@ void unset_pnfs_layoutdriver(struct nfs_server *);
123enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *, 123enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *,
124 const struct rpc_call_ops *); 124 const struct rpc_call_ops *);
125void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); 125void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
126void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *);
126int pnfs_layout_process(struct nfs4_layoutget *lgp); 127int pnfs_layout_process(struct nfs4_layoutget *lgp);
127void pnfs_free_lseg_list(struct list_head *tmp_list); 128void pnfs_free_lseg_list(struct list_head *tmp_list);
128void pnfs_destroy_layout(struct nfs_inode *); 129void pnfs_destroy_layout(struct nfs_inode *);
@@ -235,6 +236,12 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *ino)
235 pgio->pg_test = NULL; 236 pgio->pg_test = NULL;
236} 237}
237 238
239static inline void
240pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *ino)
241{
242 pgio->pg_test = NULL;
243}
244
238#endif /* CONFIG_NFS_V4_1 */ 245#endif /* CONFIG_NFS_V4_1 */
239 246
240#endif /* FS_NFS_PNFS_H */ 247#endif /* FS_NFS_PNFS_H */
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 72b0ec0bb0e1..49c4784c24e5 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -919,6 +919,8 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
919 } while (nbytes != 0); 919 } while (nbytes != 0);
920 atomic_set(&req->wb_complete, requests); 920 atomic_set(&req->wb_complete, requests);
921 921
922 BUG_ON(lseg);
923 lseg = pnfs_update_layout(inode, req->wb_context, IOMODE_RW);
922 ClearPageError(page); 924 ClearPageError(page);
923 offset = 0; 925 offset = 0;
924 nbytes = count; 926 nbytes = count;
@@ -940,6 +942,7 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
940 nbytes -= wsize; 942 nbytes -= wsize;
941 } while (nbytes != 0); 943 } while (nbytes != 0);
942 944
945 put_lseg(lseg);
943 return ret; 946 return ret;
944 947
945out_bad: 948out_bad:
@@ -965,11 +968,18 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
965 struct nfs_page *req; 968 struct nfs_page *req;
966 struct page **pages; 969 struct page **pages;
967 struct nfs_write_data *data; 970 struct nfs_write_data *data;
971 int ret;
968 972
969 data = nfs_writedata_alloc(npages); 973 data = nfs_writedata_alloc(npages);
970 if (!data) 974 if (!data) {
971 goto out_bad; 975 while (!list_empty(head)) {
972 976 req = nfs_list_entry(head->next);
977 nfs_list_remove_request(req);
978 nfs_redirty_request(req);
979 }
980 ret = -ENOMEM;
981 goto out;
982 }
973 pages = data->pagevec; 983 pages = data->pagevec;
974 while (!list_empty(head)) { 984 while (!list_empty(head)) {
975 req = nfs_list_entry(head->next); 985 req = nfs_list_entry(head->next);
@@ -979,16 +989,14 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
979 *pages++ = req->wb_page; 989 *pages++ = req->wb_page;
980 } 990 }
981 req = nfs_list_entry(data->pages.next); 991 req = nfs_list_entry(data->pages.next);
992 if ((!lseg) && list_is_singular(&data->pages))
993 lseg = pnfs_update_layout(inode, req->wb_context, IOMODE_RW);
982 994
983 /* Set up the argument struct */ 995 /* Set up the argument struct */
984 return nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, lseg, how); 996 ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, lseg, how);
985 out_bad: 997out:
986 while (!list_empty(head)) { 998 put_lseg(lseg); /* Cleans any gotten in ->pg_test */
987 req = nfs_list_entry(head->next); 999 return ret;
988 nfs_list_remove_request(req);
989 nfs_redirty_request(req);
990 }
991 return -ENOMEM;
992} 1000}
993 1001
994static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, 1002static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
@@ -996,7 +1004,7 @@ static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
996{ 1004{
997 size_t wsize = NFS_SERVER(inode)->wsize; 1005 size_t wsize = NFS_SERVER(inode)->wsize;
998 1006
999 pgio->pg_test = NULL; 1007 pnfs_pageio_init_write(pgio, inode);
1000 1008
1001 if (wsize < PAGE_CACHE_SIZE) 1009 if (wsize < PAGE_CACHE_SIZE)
1002 nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags); 1010 nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);