aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlga Kornievskaia <kolga@netapp.com>2017-05-08 18:02:24 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-05-08 19:01:06 -0400
commite092693443b995c8e3a565a73b5fdb05f1260f9b (patch)
treee3d20255e0cae9262b5950f3e86f78643a8ab7f4
parent28cf22d0ba283deccc30b71de5f34d222cf9aa4c (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.h1
-rw-r--r--fs/nfs/nfs42proc.c21
-rw-r--r--fs/nfs/nfs42xdr.c22
-rw-r--r--fs/nfs/write.c30
-rw-r--r--include/linux/nfs_xdr.h1
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);
496int nfs_write_need_commit(struct nfs_pgio_header *); 496int nfs_write_need_commit(struct nfs_pgio_header *);
497void nfs_writeback_update_inode(struct nfs_pgio_header *hdr); 497void nfs_writeback_update_inode(struct nfs_pgio_header *hdr);
498int nfs_commit_file(struct file *file, struct nfs_write_verifier *verf);
499int nfs_generic_commit_list(struct inode *inode, struct list_head *head, 498int 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);
501void nfs_retry_commit(struct list_head *page_list, 500void 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;
190out:
191 kfree(res->commit_res.verf);
192 return status;
187} 193}
188 194
189ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src, 195ssize_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
227static 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);
484out: 502out:
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
1745int 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);
1769out_put:
1770 put_nfs_open_context(open);
1771 return ret;
1772}
1773EXPORT_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
1388struct nfs42_seek_args { 1389struct nfs42_seek_args {