diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-06-10 13:30:23 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-12 13:40:28 -0400 |
| commit | d8007d4dd6ff8749cc8a4063c3ec87442db76d82 (patch) | |
| tree | f778176d24666f2e2c7cd7ef4dc5917aa11cc207 | |
| parent | 1751c3638f2a07a8c66a803a31791bab9bd3fced (diff) | |
NFSv4.1: Add an initialisation callback for pNFS
Ensure that we always get a layout before setting up the i/o request.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
| -rw-r--r-- | fs/nfs/nfs4filelayout.c | 2 | ||||
| -rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 2 | ||||
| -rw-r--r-- | fs/nfs/pagelist.c | 2 | ||||
| -rw-r--r-- | fs/nfs/pnfs.c | 57 | ||||
| -rw-r--r-- | fs/nfs/pnfs.h | 14 | ||||
| -rw-r--r-- | fs/nfs/read.c | 16 | ||||
| -rw-r--r-- | fs/nfs/write.c | 12 | ||||
| -rw-r--r-- | include/linux/nfs_page.h | 1 |
8 files changed, 47 insertions, 59 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 46bb31b79683..faac87f24797 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -682,11 +682,13 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
| 682 | } | 682 | } |
| 683 | 683 | ||
| 684 | static const struct nfs_pageio_ops filelayout_pg_read_ops = { | 684 | static const struct nfs_pageio_ops filelayout_pg_read_ops = { |
| 685 | .pg_init = pnfs_generic_pg_init_read, | ||
| 685 | .pg_test = filelayout_pg_test, | 686 | .pg_test = filelayout_pg_test, |
| 686 | .pg_doio = nfs_generic_pg_readpages, | 687 | .pg_doio = nfs_generic_pg_readpages, |
| 687 | }; | 688 | }; |
| 688 | 689 | ||
| 689 | static const struct nfs_pageio_ops filelayout_pg_write_ops = { | 690 | static const struct nfs_pageio_ops filelayout_pg_write_ops = { |
| 691 | .pg_init = pnfs_generic_pg_init_write, | ||
| 690 | .pg_test = filelayout_pg_test, | 692 | .pg_test = filelayout_pg_test, |
| 691 | .pg_doio = nfs_generic_pg_writepages, | 693 | .pg_doio = nfs_generic_pg_writepages, |
| 692 | }; | 694 | }; |
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index c203fab694af..b759aeba57b9 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
| @@ -1008,11 +1008,13 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, | |||
| 1008 | } | 1008 | } |
| 1009 | 1009 | ||
| 1010 | static const struct nfs_pageio_ops objio_pg_read_ops = { | 1010 | static const struct nfs_pageio_ops objio_pg_read_ops = { |
| 1011 | .pg_init = pnfs_generic_pg_init_read, | ||
| 1011 | .pg_test = objio_pg_test, | 1012 | .pg_test = objio_pg_test, |
| 1012 | .pg_doio = nfs_generic_pg_readpages, | 1013 | .pg_doio = nfs_generic_pg_readpages, |
| 1013 | }; | 1014 | }; |
| 1014 | 1015 | ||
| 1015 | static const struct nfs_pageio_ops objio_pg_write_ops = { | 1016 | static const struct nfs_pageio_ops objio_pg_write_ops = { |
| 1017 | .pg_init = pnfs_generic_pg_init_write, | ||
| 1016 | .pg_test = objio_pg_test, | 1018 | .pg_test = objio_pg_test, |
| 1017 | .pg_doio = nfs_generic_pg_writepages, | 1019 | .pg_doio = nfs_generic_pg_writepages, |
| 1018 | }; | 1020 | }; |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 9b8a4730f0bd..d421e19557a5 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
| @@ -295,6 +295,8 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, | |||
| 295 | if (!nfs_can_coalesce_requests(prev, req, desc)) | 295 | if (!nfs_can_coalesce_requests(prev, req, desc)) |
| 296 | return 0; | 296 | return 0; |
| 297 | } else { | 297 | } else { |
| 298 | if (desc->pg_ops->pg_init) | ||
| 299 | desc->pg_ops->pg_init(desc, req); | ||
| 298 | desc->pg_base = req->wb_pgbase; | 300 | desc->pg_base = req->wb_pgbase; |
| 299 | } | 301 | } |
| 300 | nfs_list_remove_request(req); | 302 | nfs_list_remove_request(req); |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 7ec46d5f05ab..69a0c3f1e462 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -911,7 +911,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, | |||
| 911 | * Layout segment is retreived from the server if not cached. | 911 | * Layout segment is retreived from the server if not cached. |
| 912 | * The appropriate layout segment is referenced and returned to the caller. | 912 | * The appropriate layout segment is referenced and returned to the caller. |
| 913 | */ | 913 | */ |
| 914 | struct pnfs_layout_segment * | 914 | static struct pnfs_layout_segment * |
| 915 | pnfs_update_layout(struct inode *ino, | 915 | pnfs_update_layout(struct inode *ino, |
| 916 | struct nfs_open_context *ctx, | 916 | struct nfs_open_context *ctx, |
| 917 | loff_t pos, | 917 | loff_t pos, |
| @@ -1055,6 +1055,34 @@ out_forget_reply: | |||
| 1055 | goto out; | 1055 | goto out; |
| 1056 | } | 1056 | } |
| 1057 | 1057 | ||
| 1058 | void | ||
| 1059 | pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | ||
| 1060 | { | ||
| 1061 | BUG_ON(pgio->pg_lseg != NULL); | ||
| 1062 | |||
| 1063 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | ||
| 1064 | req->wb_context, | ||
| 1065 | req_offset(req), | ||
| 1066 | req->wb_bytes, | ||
| 1067 | IOMODE_READ, | ||
| 1068 | GFP_KERNEL); | ||
| 1069 | } | ||
| 1070 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_read); | ||
| 1071 | |||
| 1072 | void | ||
| 1073 | pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | ||
| 1074 | { | ||
| 1075 | BUG_ON(pgio->pg_lseg != NULL); | ||
| 1076 | |||
| 1077 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | ||
| 1078 | req->wb_context, | ||
| 1079 | req_offset(req), | ||
| 1080 | req->wb_bytes, | ||
| 1081 | IOMODE_RW, | ||
| 1082 | GFP_NOFS); | ||
| 1083 | } | ||
| 1084 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write); | ||
| 1085 | |||
| 1058 | bool | 1086 | bool |
| 1059 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode) | 1087 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode) |
| 1060 | { | 1088 | { |
| @@ -1083,31 +1111,8 @@ bool | |||
| 1083 | pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | 1111 | pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, |
| 1084 | struct nfs_page *req) | 1112 | struct nfs_page *req) |
| 1085 | { | 1113 | { |
| 1086 | enum pnfs_iomode access_type; | 1114 | if (pgio->pg_lseg == NULL) |
| 1087 | gfp_t gfp_flags; | 1115 | return nfs_generic_pg_test(pgio, prev, req); |
| 1088 | |||
| 1089 | /* We assume that pg_ioflags == 0 iff we're reading a page */ | ||
| 1090 | if (pgio->pg_ioflags == 0) { | ||
| 1091 | access_type = IOMODE_READ; | ||
| 1092 | gfp_flags = GFP_KERNEL; | ||
| 1093 | } else { | ||
| 1094 | access_type = IOMODE_RW; | ||
| 1095 | gfp_flags = GFP_NOFS; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | if (pgio->pg_lseg == NULL) { | ||
| 1099 | if (pgio->pg_count != prev->wb_bytes) | ||
| 1100 | return true; | ||
| 1101 | /* This is first coelesce call for a series of nfs_pages */ | ||
| 1102 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | ||
| 1103 | prev->wb_context, | ||
| 1104 | req_offset(prev), | ||
| 1105 | pgio->pg_count, | ||
| 1106 | access_type, | ||
| 1107 | gfp_flags); | ||
| 1108 | if (pgio->pg_lseg == NULL) | ||
| 1109 | return true; | ||
| 1110 | } | ||
| 1111 | 1116 | ||
| 1112 | /* | 1117 | /* |
| 1113 | * Test if a nfs_page is fully contained in the pnfs_layout_range. | 1118 | * Test if a nfs_page is fully contained in the pnfs_layout_range. |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 137a2bd5c8c7..dd54351ae6ac 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
| @@ -149,10 +149,6 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); | |||
| 149 | /* pnfs.c */ | 149 | /* pnfs.c */ |
| 150 | void get_layout_hdr(struct pnfs_layout_hdr *lo); | 150 | void get_layout_hdr(struct pnfs_layout_hdr *lo); |
| 151 | void put_lseg(struct pnfs_layout_segment *lseg); | 151 | void put_lseg(struct pnfs_layout_segment *lseg); |
| 152 | struct pnfs_layout_segment * | ||
| 153 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | ||
| 154 | loff_t pos, u64 count, enum pnfs_iomode access_type, | ||
| 155 | gfp_t gfp_flags); | ||
| 156 | 152 | ||
| 157 | bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); | 153 | bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); |
| 158 | bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int); | 154 | bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int); |
| @@ -163,6 +159,8 @@ enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, | |||
| 163 | const struct rpc_call_ops *, int); | 159 | const struct rpc_call_ops *, int); |
| 164 | enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *, | 160 | enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *, |
| 165 | const struct rpc_call_ops *); | 161 | const struct rpc_call_ops *); |
| 162 | void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); | ||
| 163 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); | ||
| 166 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); | 164 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); |
| 167 | int pnfs_layout_process(struct nfs4_layoutget *lgp); | 165 | int pnfs_layout_process(struct nfs4_layoutget *lgp); |
| 168 | void pnfs_free_lseg_list(struct list_head *tmp_list); | 166 | void pnfs_free_lseg_list(struct list_head *tmp_list); |
| @@ -318,14 +316,6 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg) | |||
| 318 | { | 316 | { |
| 319 | } | 317 | } |
| 320 | 318 | ||
| 321 | static inline struct pnfs_layout_segment * | ||
| 322 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | ||
| 323 | loff_t pos, u64 count, enum pnfs_iomode access_type, | ||
| 324 | gfp_t gfp_flags) | ||
| 325 | { | ||
| 326 | return NULL; | ||
| 327 | } | ||
| 328 | |||
| 329 | static inline enum pnfs_try_status | 319 | static inline enum pnfs_try_status |
| 330 | pnfs_try_to_read_data(struct nfs_read_data *data, | 320 | pnfs_try_to_read_data(struct nfs_read_data *data, |
| 331 | const struct rpc_call_ops *call_ops) | 321 | const struct rpc_call_ops *call_ops) |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index b6d9ec9a208b..2cf728b832cd 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
| @@ -147,9 +147,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | |||
| 147 | zero_user_segment(page, len, PAGE_CACHE_SIZE); | 147 | zero_user_segment(page, len, PAGE_CACHE_SIZE); |
| 148 | 148 | ||
| 149 | nfs_pageio_init_read(&pgio, inode); | 149 | nfs_pageio_init_read(&pgio, inode); |
| 150 | nfs_list_add_request(new, &pgio.pg_list); | 150 | nfs_pageio_add_request(&pgio, new); |
| 151 | pgio.pg_count = len; | ||
| 152 | |||
| 153 | nfs_pageio_complete(&pgio); | 151 | nfs_pageio_complete(&pgio); |
| 154 | return 0; | 152 | return 0; |
| 155 | } | 153 | } |
| @@ -281,7 +279,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc) | |||
| 281 | unsigned int offset; | 279 | unsigned int offset; |
| 282 | int requests = 0; | 280 | int requests = 0; |
| 283 | int ret = 0; | 281 | int ret = 0; |
| 284 | struct pnfs_layout_segment *lseg; | 282 | struct pnfs_layout_segment *lseg = desc->pg_lseg; |
| 285 | LIST_HEAD(list); | 283 | LIST_HEAD(list); |
| 286 | 284 | ||
| 287 | nfs_list_remove_request(req); | 285 | nfs_list_remove_request(req); |
| @@ -299,10 +297,6 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc) | |||
| 299 | } while(nbytes != 0); | 297 | } while(nbytes != 0); |
| 300 | atomic_set(&req->wb_complete, requests); | 298 | atomic_set(&req->wb_complete, requests); |
| 301 | 299 | ||
| 302 | BUG_ON(desc->pg_lseg != NULL); | ||
| 303 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, | ||
| 304 | req_offset(req), desc->pg_count, | ||
| 305 | IOMODE_READ, GFP_KERNEL); | ||
| 306 | ClearPageError(page); | 300 | ClearPageError(page); |
| 307 | offset = 0; | 301 | offset = 0; |
| 308 | nbytes = desc->pg_count; | 302 | nbytes = desc->pg_count; |
| @@ -336,6 +330,8 @@ out_bad: | |||
| 336 | } | 330 | } |
| 337 | SetPageError(page); | 331 | SetPageError(page); |
| 338 | nfs_readpage_release(req); | 332 | nfs_readpage_release(req); |
| 333 | put_lseg(lseg); | ||
| 334 | desc->pg_lseg = NULL; | ||
| 339 | return -ENOMEM; | 335 | return -ENOMEM; |
| 340 | } | 336 | } |
| 341 | 337 | ||
| @@ -364,10 +360,6 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc) | |||
| 364 | *pages++ = req->wb_page; | 360 | *pages++ = req->wb_page; |
| 365 | } | 361 | } |
| 366 | req = nfs_list_entry(data->pages.next); | 362 | req = nfs_list_entry(data->pages.next); |
| 367 | if ((!lseg) && list_is_singular(&data->pages)) | ||
| 368 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, | ||
| 369 | req_offset(req), desc->pg_count, | ||
| 370 | IOMODE_READ, GFP_KERNEL); | ||
| 371 | 363 | ||
| 372 | ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count, | 364 | ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count, |
| 373 | 0, lseg); | 365 | 0, lseg); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index b144b5474546..d1ae7e45886f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -916,7 +916,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) | |||
| 916 | unsigned int offset; | 916 | unsigned int offset; |
| 917 | int requests = 0; | 917 | int requests = 0; |
| 918 | int ret = 0; | 918 | int ret = 0; |
| 919 | struct pnfs_layout_segment *lseg; | 919 | struct pnfs_layout_segment *lseg = desc->pg_lseg; |
| 920 | LIST_HEAD(list); | 920 | LIST_HEAD(list); |
| 921 | 921 | ||
| 922 | nfs_list_remove_request(req); | 922 | nfs_list_remove_request(req); |
| @@ -940,10 +940,6 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) | |||
| 940 | } while (nbytes != 0); | 940 | } while (nbytes != 0); |
| 941 | atomic_set(&req->wb_complete, requests); | 941 | atomic_set(&req->wb_complete, requests); |
| 942 | 942 | ||
| 943 | BUG_ON(desc->pg_lseg); | ||
| 944 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, | ||
| 945 | req_offset(req), desc->pg_count, | ||
| 946 | IOMODE_RW, GFP_NOFS); | ||
| 947 | ClearPageError(page); | 943 | ClearPageError(page); |
| 948 | offset = 0; | 944 | offset = 0; |
| 949 | nbytes = desc->pg_count; | 945 | nbytes = desc->pg_count; |
| @@ -976,6 +972,8 @@ out_bad: | |||
| 976 | nfs_writedata_free(data); | 972 | nfs_writedata_free(data); |
| 977 | } | 973 | } |
| 978 | nfs_redirty_request(req); | 974 | nfs_redirty_request(req); |
| 975 | put_lseg(lseg); | ||
| 976 | desc->pg_lseg = NULL; | ||
| 979 | return -ENOMEM; | 977 | return -ENOMEM; |
| 980 | } | 978 | } |
| 981 | 979 | ||
| @@ -1016,10 +1014,6 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) | |||
| 1016 | *pages++ = req->wb_page; | 1014 | *pages++ = req->wb_page; |
| 1017 | } | 1015 | } |
| 1018 | req = nfs_list_entry(data->pages.next); | 1016 | req = nfs_list_entry(data->pages.next); |
| 1019 | if ((!lseg) && list_is_singular(&data->pages)) | ||
| 1020 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, | ||
| 1021 | req_offset(req), desc->pg_count, | ||
| 1022 | IOMODE_RW, GFP_NOFS); | ||
| 1023 | 1017 | ||
| 1024 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | 1018 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && |
| 1025 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) | 1019 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index d378f08b905e..9ac2dd158d0b 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
| @@ -57,6 +57,7 @@ struct nfs_page { | |||
| 57 | 57 | ||
| 58 | struct nfs_pageio_descriptor; | 58 | struct nfs_pageio_descriptor; |
| 59 | struct nfs_pageio_ops { | 59 | struct nfs_pageio_ops { |
| 60 | void (*pg_init)(struct nfs_pageio_descriptor *, struct nfs_page *); | ||
| 60 | bool (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *); | 61 | bool (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *); |
| 61 | int (*pg_doio)(struct nfs_pageio_descriptor *); | 62 | int (*pg_doio)(struct nfs_pageio_descriptor *); |
| 62 | }; | 63 | }; |
