aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2017-02-17 18:42:32 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-12 00:41:51 -0500
commit77bbc0c7712a43442e2637247eaa4f01f73f0eb8 (patch)
tree63bd755f1f09592b6b63b3fc9dad4425063f3ac0
parent0465339eb54953f0be1f03e980b07eeb01e16fca (diff)
NFSv4: Fix reboot recovery in copy offload
commit 9d8cacbf5636657d2cd0dda17438a56d806d3224 upstream. Copy offload code needs to be hooked into the code for handling NFS4ERR_BAD_STATEID by ensuring that we set the "stateid" field in struct nfs4_exception. Reported-by: Olga Kornievskaia <aglo@umich.edu> Fixes: 2e72448b07dc3 ("NFS: Add COPY nfs operation") Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/nfs/nfs42proc.c63
1 files changed, 37 insertions, 26 deletions
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index 608501971fe0..5cda392028ce 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -128,30 +128,26 @@ out_unlock:
128 return err; 128 return err;
129} 129}
130 130
131static ssize_t _nfs42_proc_copy(struct file *src, loff_t pos_src, 131static ssize_t _nfs42_proc_copy(struct file *src,
132 struct nfs_lock_context *src_lock, 132 struct nfs_lock_context *src_lock,
133 struct file *dst, loff_t pos_dst, 133 struct file *dst,
134 struct nfs_lock_context *dst_lock, 134 struct nfs_lock_context *dst_lock,
135 size_t count) 135 struct nfs42_copy_args *args,
136 struct nfs42_copy_res *res)
136{ 137{
137 struct nfs42_copy_args args = {
138 .src_fh = NFS_FH(file_inode(src)),
139 .src_pos = pos_src,
140 .dst_fh = NFS_FH(file_inode(dst)),
141 .dst_pos = pos_dst,
142 .count = count,
143 };
144 struct nfs42_copy_res res;
145 struct rpc_message msg = { 138 struct rpc_message msg = {
146 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY], 139 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY],
147 .rpc_argp = &args, 140 .rpc_argp = args,
148 .rpc_resp = &res, 141 .rpc_resp = res,
149 }; 142 };
150 struct inode *dst_inode = file_inode(dst); 143 struct inode *dst_inode = file_inode(dst);
151 struct nfs_server *server = NFS_SERVER(dst_inode); 144 struct nfs_server *server = NFS_SERVER(dst_inode);
145 loff_t pos_src = args->src_pos;
146 loff_t pos_dst = args->dst_pos;
147 size_t count = args->count;
152 int status; 148 int status;
153 149
154 status = nfs4_set_rw_stateid(&args.src_stateid, src_lock->open_context, 150 status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context,
155 src_lock, FMODE_READ); 151 src_lock, FMODE_READ);
156 if (status) 152 if (status)
157 return status; 153 return status;
@@ -161,7 +157,7 @@ static ssize_t _nfs42_proc_copy(struct file *src, loff_t pos_src,
161 if (status) 157 if (status)
162 return status; 158 return status;
163 159
164 status = nfs4_set_rw_stateid(&args.dst_stateid, dst_lock->open_context, 160 status = nfs4_set_rw_stateid(&args->dst_stateid, dst_lock->open_context,
165 dst_lock, FMODE_WRITE); 161 dst_lock, FMODE_WRITE);
166 if (status) 162 if (status)
167 return status; 163 return status;
@@ -171,22 +167,22 @@ static ssize_t _nfs42_proc_copy(struct file *src, loff_t pos_src,
171 return status; 167 return status;
172 168
173 status = nfs4_call_sync(server->client, server, &msg, 169 status = nfs4_call_sync(server->client, server, &msg,
174 &args.seq_args, &res.seq_res, 0); 170 &args->seq_args, &res->seq_res, 0);
175 if (status == -ENOTSUPP) 171 if (status == -ENOTSUPP)
176 server->caps &= ~NFS_CAP_COPY; 172 server->caps &= ~NFS_CAP_COPY;
177 if (status) 173 if (status)
178 return status; 174 return status;
179 175
180 if (res.write_res.verifier.committed != NFS_FILE_SYNC) { 176 if (res->write_res.verifier.committed != NFS_FILE_SYNC) {
181 status = nfs_commit_file(dst, &res.write_res.verifier.verifier); 177 status = nfs_commit_file(dst, &res->write_res.verifier.verifier);
182 if (status) 178 if (status)
183 return status; 179 return status;
184 } 180 }
185 181
186 truncate_pagecache_range(dst_inode, pos_dst, 182 truncate_pagecache_range(dst_inode, pos_dst,
187 pos_dst + res.write_res.count); 183 pos_dst + res->write_res.count);
188 184
189 return res.write_res.count; 185 return res->write_res.count;
190} 186}
191 187
192ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src, 188ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
@@ -196,8 +192,22 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
196 struct nfs_server *server = NFS_SERVER(file_inode(dst)); 192 struct nfs_server *server = NFS_SERVER(file_inode(dst));
197 struct nfs_lock_context *src_lock; 193 struct nfs_lock_context *src_lock;
198 struct nfs_lock_context *dst_lock; 194 struct nfs_lock_context *dst_lock;
199 struct nfs4_exception src_exception = { }; 195 struct nfs42_copy_args args = {
200 struct nfs4_exception dst_exception = { }; 196 .src_fh = NFS_FH(file_inode(src)),
197 .src_pos = pos_src,
198 .dst_fh = NFS_FH(file_inode(dst)),
199 .dst_pos = pos_dst,
200 .count = count,
201 };
202 struct nfs42_copy_res res;
203 struct nfs4_exception src_exception = {
204 .inode = file_inode(src),
205 .stateid = &args.src_stateid,
206 };
207 struct nfs4_exception dst_exception = {
208 .inode = file_inode(dst),
209 .stateid = &args.dst_stateid,
210 };
201 ssize_t err, err2; 211 ssize_t err, err2;
202 212
203 if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY)) 213 if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY))
@@ -207,7 +217,6 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
207 if (IS_ERR(src_lock)) 217 if (IS_ERR(src_lock))
208 return PTR_ERR(src_lock); 218 return PTR_ERR(src_lock);
209 219
210 src_exception.inode = file_inode(src);
211 src_exception.state = src_lock->open_context->state; 220 src_exception.state = src_lock->open_context->state;
212 221
213 dst_lock = nfs_get_lock_context(nfs_file_open_context(dst)); 222 dst_lock = nfs_get_lock_context(nfs_file_open_context(dst));
@@ -216,15 +225,17 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
216 goto out_put_src_lock; 225 goto out_put_src_lock;
217 } 226 }
218 227
219 dst_exception.inode = file_inode(dst);
220 dst_exception.state = dst_lock->open_context->state; 228 dst_exception.state = dst_lock->open_context->state;
221 229
222 do { 230 do {
223 inode_lock(file_inode(dst)); 231 inode_lock(file_inode(dst));
224 err = _nfs42_proc_copy(src, pos_src, src_lock, 232 err = _nfs42_proc_copy(src, src_lock,
225 dst, pos_dst, dst_lock, count); 233 dst, dst_lock,
234 &args, &res);
226 inode_unlock(file_inode(dst)); 235 inode_unlock(file_inode(dst));
227 236
237 if (err >= 0)
238 break;
228 if (err == -ENOTSUPP) { 239 if (err == -ENOTSUPP) {
229 err = -EOPNOTSUPP; 240 err = -EOPNOTSUPP;
230 break; 241 break;