diff options
author | Olga Kornievskaia <kolga@netapp.com> | 2017-05-08 18:02:24 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-05-08 19:01:06 -0400 |
commit | e092693443b995c8e3a565a73b5fdb05f1260f9b (patch) | |
tree | e3d20255e0cae9262b5950f3e86f78643a8ab7f4 | |
parent | 28cf22d0ba283deccc30b71de5f34d222cf9aa4c (diff) |
NFS append COMMIT after synchronous COPY
Instead of messing with the commit path which has been causing issues,
add a COMMIT op after the COPY and ask for stable copies in the first
space.
It saves a round trip, since after the COPY, the client sends a COMMIT
anyway.
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/internal.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs42proc.c | 21 | ||||
-rw-r--r-- | fs/nfs/nfs42xdr.c | 22 | ||||
-rw-r--r-- | fs/nfs/write.c | 30 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 |
5 files changed, 36 insertions, 39 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 31b26cf1b476..e9b4c3320e37 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -495,7 +495,6 @@ void nfs_mark_request_commit(struct nfs_page *req, | |||
495 | u32 ds_commit_idx); | 495 | u32 ds_commit_idx); |
496 | int nfs_write_need_commit(struct nfs_pgio_header *); | 496 | int nfs_write_need_commit(struct nfs_pgio_header *); |
497 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr); | 497 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr); |
498 | int nfs_commit_file(struct file *file, struct nfs_write_verifier *verf); | ||
499 | int nfs_generic_commit_list(struct inode *inode, struct list_head *head, | 498 | int nfs_generic_commit_list(struct inode *inode, struct list_head *head, |
500 | int how, struct nfs_commit_info *cinfo); | 499 | int how, struct nfs_commit_info *cinfo); |
501 | void nfs_retry_commit(struct list_head *page_list, | 500 | void nfs_retry_commit(struct list_head *page_list, |
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 87f5b7b971ca..929d09a5310a 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
@@ -167,23 +167,29 @@ static ssize_t _nfs42_proc_copy(struct file *src, | |||
167 | if (status) | 167 | if (status) |
168 | return status; | 168 | return status; |
169 | 169 | ||
170 | res->commit_res.verf = kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS); | ||
171 | if (!res->commit_res.verf) | ||
172 | return -ENOMEM; | ||
170 | status = nfs4_call_sync(server->client, server, &msg, | 173 | status = nfs4_call_sync(server->client, server, &msg, |
171 | &args->seq_args, &res->seq_res, 0); | 174 | &args->seq_args, &res->seq_res, 0); |
172 | if (status == -ENOTSUPP) | 175 | if (status == -ENOTSUPP) |
173 | server->caps &= ~NFS_CAP_COPY; | 176 | server->caps &= ~NFS_CAP_COPY; |
174 | if (status) | 177 | if (status) |
175 | return status; | 178 | goto out; |
176 | 179 | ||
177 | if (res->write_res.verifier.committed != NFS_FILE_SYNC) { | 180 | if (!nfs_write_verifier_cmp(&res->write_res.verifier.verifier, |
178 | status = nfs_commit_file(dst, &res->write_res.verifier.verifier); | 181 | &res->commit_res.verf->verifier)) { |
179 | if (status) | 182 | status = -EAGAIN; |
180 | return status; | 183 | goto out; |
181 | } | 184 | } |
182 | 185 | ||
183 | truncate_pagecache_range(dst_inode, pos_dst, | 186 | truncate_pagecache_range(dst_inode, pos_dst, |
184 | pos_dst + res->write_res.count); | 187 | pos_dst + res->write_res.count); |
185 | 188 | ||
186 | return res->write_res.count; | 189 | status = res->write_res.count; |
190 | out: | ||
191 | kfree(res->commit_res.verf); | ||
192 | return status; | ||
187 | } | 193 | } |
188 | 194 | ||
189 | ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src, | 195 | ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src, |
@@ -240,6 +246,9 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src, | |||
240 | if (err == -ENOTSUPP) { | 246 | if (err == -ENOTSUPP) { |
241 | err = -EOPNOTSUPP; | 247 | err = -EOPNOTSUPP; |
242 | break; | 248 | break; |
249 | } if (err == -EAGAIN) { | ||
250 | dst_exception.retry = 1; | ||
251 | continue; | ||
243 | } | 252 | } |
244 | 253 | ||
245 | err2 = nfs4_handle_exception(server, err, &src_exception); | 254 | err2 = nfs4_handle_exception(server, err, &src_exception); |
diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c index 6c7296454bbc..528362f69cc1 100644 --- a/fs/nfs/nfs42xdr.c +++ b/fs/nfs/nfs42xdr.c | |||
@@ -66,12 +66,14 @@ | |||
66 | encode_putfh_maxsz + \ | 66 | encode_putfh_maxsz + \ |
67 | encode_savefh_maxsz + \ | 67 | encode_savefh_maxsz + \ |
68 | encode_putfh_maxsz + \ | 68 | encode_putfh_maxsz + \ |
69 | encode_copy_maxsz) | 69 | encode_copy_maxsz + \ |
70 | encode_commit_maxsz) | ||
70 | #define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \ | 71 | #define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \ |
71 | decode_putfh_maxsz + \ | 72 | decode_putfh_maxsz + \ |
72 | decode_savefh_maxsz + \ | 73 | decode_savefh_maxsz + \ |
73 | decode_putfh_maxsz + \ | 74 | decode_putfh_maxsz + \ |
74 | decode_copy_maxsz) | 75 | decode_copy_maxsz + \ |
76 | decode_commit_maxsz) | ||
75 | #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ | 77 | #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ |
76 | encode_putfh_maxsz + \ | 78 | encode_putfh_maxsz + \ |
77 | encode_deallocate_maxsz + \ | 79 | encode_deallocate_maxsz + \ |
@@ -222,6 +224,18 @@ static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, | |||
222 | encode_nops(&hdr); | 224 | encode_nops(&hdr); |
223 | } | 225 | } |
224 | 226 | ||
227 | static void encode_copy_commit(struct xdr_stream *xdr, | ||
228 | struct nfs42_copy_args *args, | ||
229 | struct compound_hdr *hdr) | ||
230 | { | ||
231 | __be32 *p; | ||
232 | |||
233 | encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); | ||
234 | p = reserve_space(xdr, 12); | ||
235 | p = xdr_encode_hyper(p, args->dst_pos); | ||
236 | *p = cpu_to_be32(args->count); | ||
237 | } | ||
238 | |||
225 | /* | 239 | /* |
226 | * Encode COPY request | 240 | * Encode COPY request |
227 | */ | 241 | */ |
@@ -239,6 +253,7 @@ static void nfs4_xdr_enc_copy(struct rpc_rqst *req, | |||
239 | encode_savefh(xdr, &hdr); | 253 | encode_savefh(xdr, &hdr); |
240 | encode_putfh(xdr, args->dst_fh, &hdr); | 254 | encode_putfh(xdr, args->dst_fh, &hdr); |
241 | encode_copy(xdr, args, &hdr); | 255 | encode_copy(xdr, args, &hdr); |
256 | encode_copy_commit(xdr, args, &hdr); | ||
242 | encode_nops(&hdr); | 257 | encode_nops(&hdr); |
243 | } | 258 | } |
244 | 259 | ||
@@ -481,6 +496,9 @@ static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp, | |||
481 | if (status) | 496 | if (status) |
482 | goto out; | 497 | goto out; |
483 | status = decode_copy(xdr, res); | 498 | status = decode_copy(xdr, res); |
499 | if (status) | ||
500 | goto out; | ||
501 | status = decode_commit(xdr, &res->commit_res); | ||
484 | out: | 502 | out: |
485 | return status; | 503 | return status; |
486 | } | 504 | } |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 59e21cc0a266..85bfa416fcc8 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1742,36 +1742,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how, | |||
1742 | data->mds_ops, how, 0); | 1742 | data->mds_ops, how, 0); |
1743 | } | 1743 | } |
1744 | 1744 | ||
1745 | int nfs_commit_file(struct file *file, struct nfs_write_verifier *verf) | ||
1746 | { | ||
1747 | struct inode *inode = file_inode(file); | ||
1748 | struct nfs_open_context *open; | ||
1749 | struct nfs_commit_info cinfo; | ||
1750 | struct nfs_page *req; | ||
1751 | int ret; | ||
1752 | |||
1753 | open = get_nfs_open_context(nfs_file_open_context(file)); | ||
1754 | req = nfs_create_request(open, NULL, NULL, 0, i_size_read(inode)); | ||
1755 | if (IS_ERR(req)) { | ||
1756 | ret = PTR_ERR(req); | ||
1757 | goto out_put; | ||
1758 | } | ||
1759 | |||
1760 | nfs_init_cinfo_from_inode(&cinfo, inode); | ||
1761 | |||
1762 | memcpy(&req->wb_verf, verf, sizeof(struct nfs_write_verifier)); | ||
1763 | nfs_request_add_commit_list(req, &cinfo); | ||
1764 | ret = nfs_commit_inode(inode, FLUSH_SYNC); | ||
1765 | if (ret > 0) | ||
1766 | ret = 0; | ||
1767 | |||
1768 | nfs_free_request(req); | ||
1769 | out_put: | ||
1770 | put_nfs_open_context(open); | ||
1771 | return ret; | ||
1772 | } | ||
1773 | EXPORT_SYMBOL_GPL(nfs_commit_file); | ||
1774 | |||
1775 | /* | 1745 | /* |
1776 | * COMMIT call returned | 1746 | * COMMIT call returned |
1777 | */ | 1747 | */ |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 677c6b91dfcd..b28c83475ee8 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1383,6 +1383,7 @@ struct nfs42_copy_res { | |||
1383 | struct nfs42_write_res write_res; | 1383 | struct nfs42_write_res write_res; |
1384 | bool consecutive; | 1384 | bool consecutive; |
1385 | bool synchronous; | 1385 | bool synchronous; |
1386 | struct nfs_commitres commit_res; | ||
1386 | }; | 1387 | }; |
1387 | 1388 | ||
1388 | struct nfs42_seek_args { | 1389 | struct nfs42_seek_args { |