diff options
author | Fred Isaman <iisaman@netapp.com> | 2011-03-03 10:13:44 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-11 15:38:44 -0500 |
commit | 44b83799a922a153957c65ccfc985a8c902958c8 (patch) | |
tree | 4dad6ec4655a876c3f12a15919fad407fd22ef59 | |
parent | 5053aa568d4017aeb1fa35247d4ad96be262920f (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.c | 22 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 7 | ||||
-rw-r--r-- | fs/nfs/write.c | 32 |
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 | ||
876 | static 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 | |||
889 | void | ||
890 | pnfs_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 *); | |||
123 | enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *, | 123 | enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *, |
124 | const struct rpc_call_ops *); | 124 | const struct rpc_call_ops *); |
125 | void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); | 125 | void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); |
126 | void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *); | ||
126 | int pnfs_layout_process(struct nfs4_layoutget *lgp); | 127 | int pnfs_layout_process(struct nfs4_layoutget *lgp); |
127 | void pnfs_free_lseg_list(struct list_head *tmp_list); | 128 | void pnfs_free_lseg_list(struct list_head *tmp_list); |
128 | void pnfs_destroy_layout(struct nfs_inode *); | 129 | void 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 | ||
239 | static inline void | ||
240 | pnfs_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 | ||
945 | out_bad: | 948 | out_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: | 997 | out: |
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 | ||
994 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | 1002 | static 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); |