aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2017-02-17 18:42:32 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2017-02-22 13:49:11 -0500
commit9d8cacbf5636657d2cd0dda17438a56d806d3224 (patch)
tree80b2c01795b952d8fd4c8dad20c2c9a971666cab
parentdf3ab232e462bce20710596d697ade6b72497694 (diff)
NFSv4: Fix reboot recovery in copy offload
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> Cc: stable@vger.kernel.org # v4.7+ Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-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 98cf58341066..1e486c73ec94 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -129,30 +129,26 @@ out_unlock:
129 return err; 129 return err;
130} 130}
131 131
132static ssize_t _nfs42_proc_copy(struct file *src, loff_t pos_src, 132static ssize_t _nfs42_proc_copy(struct file *src,
133 struct nfs_lock_context *src_lock, 133 struct nfs_lock_context *src_lock,
134 struct file *dst, loff_t pos_dst, 134 struct file *dst,
135 struct nfs_lock_context *dst_lock, 135 struct nfs_lock_context *dst_lock,
136 size_t count) 136 struct nfs42_copy_args *args,
137 struct nfs42_copy_res *res)
137{ 138{
138 struct nfs42_copy_args args = {
139 .src_fh = NFS_FH(file_inode(src)),
140 .src_pos = pos_src,
141 .dst_fh = NFS_FH(file_inode(dst)),
142 .dst_pos = pos_dst,
143 .count = count,
144 };
145 struct nfs42_copy_res res;
146 struct rpc_message msg = { 139 struct rpc_message msg = {
147 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY], 140 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY],
148 .rpc_argp = &args, 141 .rpc_argp = args,
149 .rpc_resp = &res, 142 .rpc_resp = res,
150 }; 143 };
151 struct inode *dst_inode = file_inode(dst); 144 struct inode *dst_inode = file_inode(dst);
152 struct nfs_server *server = NFS_SERVER(dst_inode); 145 struct nfs_server *server = NFS_SERVER(dst_inode);
146 loff_t pos_src = args->src_pos;
147 loff_t pos_dst = args->dst_pos;
148 size_t count = args->count;
153 int status; 149 int status;
154 150
155 status = nfs4_set_rw_stateid(&args.src_stateid, src_lock->open_context, 151 status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context,
156 src_lock, FMODE_READ); 152 src_lock, FMODE_READ);
157 if (status) 153 if (status)
158 return status; 154 return status;
@@ -162,7 +158,7 @@ static ssize_t _nfs42_proc_copy(struct file *src, loff_t pos_src,
162 if (status) 158 if (status)
163 return status; 159 return status;
164 160
165 status = nfs4_set_rw_stateid(&args.dst_stateid, dst_lock->open_context, 161 status = nfs4_set_rw_stateid(&args->dst_stateid, dst_lock->open_context,
166 dst_lock, FMODE_WRITE); 162 dst_lock, FMODE_WRITE);
167 if (status) 163 if (status)
168 return status; 164 return status;
@@ -172,22 +168,22 @@ static ssize_t _nfs42_proc_copy(struct file *src, loff_t pos_src,
172 return status; 168 return status;
173 169
174 status = nfs4_call_sync(server->client, server, &msg, 170 status = nfs4_call_sync(server->client, server, &msg,
175 &args.seq_args, &res.seq_res, 0); 171 &args->seq_args, &res->seq_res, 0);
176 if (status == -ENOTSUPP) 172 if (status == -ENOTSUPP)
177 server->caps &= ~NFS_CAP_COPY; 173 server->caps &= ~NFS_CAP_COPY;
178 if (status) 174 if (status)
179 return status; 175 return status;
180 176
181 if (res.write_res.verifier.committed != NFS_FILE_SYNC) { 177 if (res->write_res.verifier.committed != NFS_FILE_SYNC) {
182 status = nfs_commit_file(dst, &res.write_res.verifier.verifier); 178 status = nfs_commit_file(dst, &res->write_res.verifier.verifier);
183 if (status) 179 if (status)
184 return status; 180 return status;
185 } 181 }
186 182
187 truncate_pagecache_range(dst_inode, pos_dst, 183 truncate_pagecache_range(dst_inode, pos_dst,
188 pos_dst + res.write_res.count); 184 pos_dst + res->write_res.count);
189 185
190 return res.write_res.count; 186 return res->write_res.count;
191} 187}
192 188
193ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src, 189ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
@@ -197,8 +193,22 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
197 struct nfs_server *server = NFS_SERVER(file_inode(dst)); 193 struct nfs_server *server = NFS_SERVER(file_inode(dst));
198 struct nfs_lock_context *src_lock; 194 struct nfs_lock_context *src_lock;
199 struct nfs_lock_context *dst_lock; 195 struct nfs_lock_context *dst_lock;
200 struct nfs4_exception src_exception = { }; 196 struct nfs42_copy_args args = {
201 struct nfs4_exception dst_exception = { }; 197 .src_fh = NFS_FH(file_inode(src)),
198 .src_pos = pos_src,
199 .dst_fh = NFS_FH(file_inode(dst)),
200 .dst_pos = pos_dst,
201 .count = count,
202 };
203 struct nfs42_copy_res res;
204 struct nfs4_exception src_exception = {
205 .inode = file_inode(src),
206 .stateid = &args.src_stateid,
207 };
208 struct nfs4_exception dst_exception = {
209 .inode = file_inode(dst),
210 .stateid = &args.dst_stateid,
211 };
202 ssize_t err, err2; 212 ssize_t err, err2;
203 213
204 if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY)) 214 if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY))
@@ -208,7 +218,6 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
208 if (IS_ERR(src_lock)) 218 if (IS_ERR(src_lock))
209 return PTR_ERR(src_lock); 219 return PTR_ERR(src_lock);
210 220
211 src_exception.inode = file_inode(src);
212 src_exception.state = src_lock->open_context->state; 221 src_exception.state = src_lock->open_context->state;
213 222
214 dst_lock = nfs_get_lock_context(nfs_file_open_context(dst)); 223 dst_lock = nfs_get_lock_context(nfs_file_open_context(dst));
@@ -217,15 +226,17 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
217 goto out_put_src_lock; 226 goto out_put_src_lock;
218 } 227 }
219 228
220 dst_exception.inode = file_inode(dst);
221 dst_exception.state = dst_lock->open_context->state; 229 dst_exception.state = dst_lock->open_context->state;
222 230
223 do { 231 do {
224 inode_lock(file_inode(dst)); 232 inode_lock(file_inode(dst));
225 err = _nfs42_proc_copy(src, pos_src, src_lock, 233 err = _nfs42_proc_copy(src, src_lock,
226 dst, pos_dst, dst_lock, count); 234 dst, dst_lock,
235 &args, &res);
227 inode_unlock(file_inode(dst)); 236 inode_unlock(file_inode(dst));
228 237
238 if (err >= 0)
239 break;
229 if (err == -ENOTSUPP) { 240 if (err == -ENOTSUPP) {
230 err = -EOPNOTSUPP; 241 err = -EOPNOTSUPP;
231 break; 242 break;