Skip to content

Commit 807ce06

Browse files
author
Trond Myklebust
committed
Merge branch 'linux-ssc-for-5.5'
2 parents 66eb3ad + 8dff1df commit 807ce06

File tree

13 files changed

+604
-47
lines changed

13 files changed

+604
-47
lines changed

fs/nfs/nfs42.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
#define PNFS_LAYOUTSTATS_MAXDEV (4)
1414

1515
/* nfs4.2proc.c */
16+
#ifdef CONFIG_NFS_V4_2
1617
int nfs42_proc_allocate(struct file *, loff_t, loff_t);
17-
ssize_t nfs42_proc_copy(struct file *, loff_t, struct file *, loff_t, size_t);
18+
ssize_t nfs42_proc_copy(struct file *, loff_t, struct file *, loff_t, size_t,
19+
struct nl4_server *, nfs4_stateid *, bool);
1820
int nfs42_proc_deallocate(struct file *, loff_t, loff_t);
1921
loff_t nfs42_proc_llseek(struct file *, loff_t, int);
2022
int nfs42_proc_layoutstats_generic(struct nfs_server *,
@@ -23,5 +25,16 @@ int nfs42_proc_clone(struct file *, struct file *, loff_t, loff_t, loff_t);
2325
int nfs42_proc_layouterror(struct pnfs_layout_segment *lseg,
2426
const struct nfs42_layout_error *errors,
2527
size_t n);
28+
int nfs42_proc_copy_notify(struct file *, struct file *,
29+
struct nfs42_copy_notify_res *);
30+
static inline bool nfs42_files_from_same_server(struct file *in,
31+
struct file *out)
32+
{
33+
struct nfs_client *c_in = (NFS_SERVER(file_inode(in)))->nfs_client;
34+
struct nfs_client *c_out = (NFS_SERVER(file_inode(out)))->nfs_client;
2635

36+
return nfs4_check_serverowner_major_id(c_in->cl_serverowner,
37+
c_out->cl_serverowner);
38+
}
39+
#endif /* CONFIG_NFS_V4_2 */
2740
#endif /* __LINUX_FS_NFS_NFS4_2_H */

fs/nfs/nfs42proc.c

Lines changed: 167 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (c) 2014 Anna Schumaker <[email protected]>
44
*/
55
#include <linux/fs.h>
6+
#include <linux/sunrpc/addr.h>
67
#include <linux/sunrpc/sched.h>
78
#include <linux/nfs.h>
89
#include <linux/nfs3.h>
@@ -15,10 +16,30 @@
1516
#include "pnfs.h"
1617
#include "nfs4session.h"
1718
#include "internal.h"
19+
#include "delegation.h"
1820

1921
#define NFSDBG_FACILITY NFSDBG_PROC
2022
static int nfs42_do_offload_cancel_async(struct file *dst, nfs4_stateid *std);
2123

24+
static void nfs42_set_netaddr(struct file *filep, struct nfs42_netaddr *naddr)
25+
{
26+
struct nfs_client *clp = (NFS_SERVER(file_inode(filep)))->nfs_client;
27+
unsigned short port = 2049;
28+
29+
rcu_read_lock();
30+
naddr->netid_len = scnprintf(naddr->netid,
31+
sizeof(naddr->netid), "%s",
32+
rpc_peeraddr2str(clp->cl_rpcclient,
33+
RPC_DISPLAY_NETID));
34+
naddr->addr_len = scnprintf(naddr->addr,
35+
sizeof(naddr->addr),
36+
"%s.%u.%u",
37+
rpc_peeraddr2str(clp->cl_rpcclient,
38+
RPC_DISPLAY_ADDR),
39+
port >> 8, port & 255);
40+
rcu_read_unlock();
41+
}
42+
2243
static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
2344
struct nfs_lock_context *lock, loff_t offset, loff_t len)
2445
{
@@ -132,22 +153,26 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
132153
}
133154

134155
static int handle_async_copy(struct nfs42_copy_res *res,
135-
struct nfs_server *server,
156+
struct nfs_server *dst_server,
157+
struct nfs_server *src_server,
136158
struct file *src,
137159
struct file *dst,
138-
nfs4_stateid *src_stateid)
160+
nfs4_stateid *src_stateid,
161+
bool *restart)
139162
{
140163
struct nfs4_copy_state *copy, *tmp_copy;
141164
int status = NFS4_OK;
142165
bool found_pending = false;
143-
struct nfs_open_context *ctx = nfs_file_open_context(dst);
166+
struct nfs_open_context *dst_ctx = nfs_file_open_context(dst);
167+
struct nfs_open_context *src_ctx = nfs_file_open_context(src);
144168

145169
copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS);
146170
if (!copy)
147171
return -ENOMEM;
148172

149-
spin_lock(&server->nfs_client->cl_lock);
150-
list_for_each_entry(tmp_copy, &server->nfs_client->pending_cb_stateids,
173+
spin_lock(&dst_server->nfs_client->cl_lock);
174+
list_for_each_entry(tmp_copy,
175+
&dst_server->nfs_client->pending_cb_stateids,
151176
copies) {
152177
if (memcmp(&res->write_res.stateid, &tmp_copy->stateid,
153178
NFS4_STATEID_SIZE))
@@ -157,40 +182,55 @@ static int handle_async_copy(struct nfs42_copy_res *res,
157182
break;
158183
}
159184
if (found_pending) {
160-
spin_unlock(&server->nfs_client->cl_lock);
185+
spin_unlock(&dst_server->nfs_client->cl_lock);
161186
kfree(copy);
162187
copy = tmp_copy;
163188
goto out;
164189
}
165190

166191
memcpy(&copy->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE);
167192
init_completion(&copy->completion);
168-
copy->parent_state = ctx->state;
193+
copy->parent_dst_state = dst_ctx->state;
194+
copy->parent_src_state = src_ctx->state;
169195

170-
list_add_tail(&copy->copies, &server->ss_copies);
171-
spin_unlock(&server->nfs_client->cl_lock);
196+
list_add_tail(&copy->copies, &dst_server->ss_copies);
197+
spin_unlock(&dst_server->nfs_client->cl_lock);
198+
199+
if (dst_server != src_server) {
200+
spin_lock(&src_server->nfs_client->cl_lock);
201+
list_add_tail(&copy->src_copies, &src_server->ss_copies);
202+
spin_unlock(&src_server->nfs_client->cl_lock);
203+
}
172204

173205
status = wait_for_completion_interruptible(&copy->completion);
174-
spin_lock(&server->nfs_client->cl_lock);
206+
spin_lock(&dst_server->nfs_client->cl_lock);
175207
list_del_init(&copy->copies);
176-
spin_unlock(&server->nfs_client->cl_lock);
208+
spin_unlock(&dst_server->nfs_client->cl_lock);
209+
if (dst_server != src_server) {
210+
spin_lock(&src_server->nfs_client->cl_lock);
211+
list_del_init(&copy->src_copies);
212+
spin_unlock(&src_server->nfs_client->cl_lock);
213+
}
177214
if (status == -ERESTARTSYS) {
178215
goto out_cancel;
179-
} else if (copy->flags) {
216+
} else if (copy->flags || copy->error == NFS4ERR_PARTNER_NO_AUTH) {
180217
status = -EAGAIN;
218+
*restart = true;
181219
goto out_cancel;
182220
}
183221
out:
184222
res->write_res.count = copy->count;
185223
memcpy(&res->write_res.verifier, &copy->verf, sizeof(copy->verf));
186224
status = -copy->error;
187225

226+
out_free:
188227
kfree(copy);
189228
return status;
190229
out_cancel:
191230
nfs42_do_offload_cancel_async(dst, &copy->stateid);
192-
kfree(copy);
193-
return status;
231+
if (!nfs42_files_from_same_server(src, dst))
232+
nfs42_do_offload_cancel_async(src, src_stateid);
233+
goto out_free;
194234
}
195235

196236
static int process_copy_commit(struct file *dst, loff_t pos_dst,
@@ -222,25 +262,34 @@ static ssize_t _nfs42_proc_copy(struct file *src,
222262
struct file *dst,
223263
struct nfs_lock_context *dst_lock,
224264
struct nfs42_copy_args *args,
225-
struct nfs42_copy_res *res)
265+
struct nfs42_copy_res *res,
266+
struct nl4_server *nss,
267+
nfs4_stateid *cnr_stateid,
268+
bool *restart)
226269
{
227270
struct rpc_message msg = {
228271
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY],
229272
.rpc_argp = args,
230273
.rpc_resp = res,
231274
};
232275
struct inode *dst_inode = file_inode(dst);
233-
struct nfs_server *server = NFS_SERVER(dst_inode);
276+
struct inode *src_inode = file_inode(src);
277+
struct nfs_server *dst_server = NFS_SERVER(dst_inode);
278+
struct nfs_server *src_server = NFS_SERVER(src_inode);
234279
loff_t pos_src = args->src_pos;
235280
loff_t pos_dst = args->dst_pos;
236281
size_t count = args->count;
237282
ssize_t status;
238283

239-
status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context,
240-
src_lock, FMODE_READ);
241-
if (status)
242-
return status;
243-
284+
if (nss) {
285+
args->cp_src = nss;
286+
nfs4_stateid_copy(&args->src_stateid, cnr_stateid);
287+
} else {
288+
status = nfs4_set_rw_stateid(&args->src_stateid,
289+
src_lock->open_context, src_lock, FMODE_READ);
290+
if (status)
291+
return status;
292+
}
244293
status = nfs_filemap_write_and_wait_range(file_inode(src)->i_mapping,
245294
pos_src, pos_src + (loff_t)count - 1);
246295
if (status)
@@ -262,13 +311,15 @@ static ssize_t _nfs42_proc_copy(struct file *src,
262311
if (!res->commit_res.verf)
263312
return -ENOMEM;
264313
}
314+
set_bit(NFS_CLNT_SRC_SSC_COPY_STATE,
315+
&src_lock->open_context->state->flags);
265316
set_bit(NFS_CLNT_DST_SSC_COPY_STATE,
266317
&dst_lock->open_context->state->flags);
267318

268-
status = nfs4_call_sync(server->client, server, &msg,
319+
status = nfs4_call_sync(dst_server->client, dst_server, &msg,
269320
&args->seq_args, &res->seq_res, 0);
270321
if (status == -ENOTSUPP)
271-
server->caps &= ~NFS_CAP_COPY;
322+
dst_server->caps &= ~NFS_CAP_COPY;
272323
if (status)
273324
goto out;
274325

@@ -280,8 +331,8 @@ static ssize_t _nfs42_proc_copy(struct file *src,
280331
}
281332

282333
if (!res->synchronous) {
283-
status = handle_async_copy(res, server, src, dst,
284-
&args->src_stateid);
334+
status = handle_async_copy(res, dst_server, src_server, src,
335+
dst, &args->src_stateid, restart);
285336
if (status)
286337
return status;
287338
}
@@ -304,8 +355,9 @@ static ssize_t _nfs42_proc_copy(struct file *src,
304355
}
305356

306357
ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
307-
struct file *dst, loff_t pos_dst,
308-
size_t count)
358+
struct file *dst, loff_t pos_dst, size_t count,
359+
struct nl4_server *nss,
360+
nfs4_stateid *cnr_stateid, bool sync)
309361
{
310362
struct nfs_server *server = NFS_SERVER(file_inode(dst));
311363
struct nfs_lock_context *src_lock;
@@ -316,7 +368,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
316368
.dst_fh = NFS_FH(file_inode(dst)),
317369
.dst_pos = pos_dst,
318370
.count = count,
319-
.sync = false,
371+
.sync = sync,
320372
};
321373
struct nfs42_copy_res res;
322374
struct nfs4_exception src_exception = {
@@ -328,6 +380,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
328380
.stateid = &args.dst_stateid,
329381
};
330382
ssize_t err, err2;
383+
bool restart = false;
331384

332385
src_lock = nfs_get_lock_context(nfs_file_open_context(src));
333386
if (IS_ERR(src_lock))
@@ -347,21 +400,33 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
347400
inode_lock(file_inode(dst));
348401
err = _nfs42_proc_copy(src, src_lock,
349402
dst, dst_lock,
350-
&args, &res);
403+
&args, &res,
404+
nss, cnr_stateid, &restart);
351405
inode_unlock(file_inode(dst));
352406

353407
if (err >= 0)
354408
break;
355-
if (err == -ENOTSUPP) {
409+
if (err == -ENOTSUPP &&
410+
nfs42_files_from_same_server(src, dst)) {
356411
err = -EOPNOTSUPP;
357412
break;
358413
} else if (err == -EAGAIN) {
359-
dst_exception.retry = 1;
360-
continue;
414+
if (!restart) {
415+
dst_exception.retry = 1;
416+
continue;
417+
}
418+
break;
361419
} else if (err == -NFS4ERR_OFFLOAD_NO_REQS && !args.sync) {
362420
args.sync = true;
363421
dst_exception.retry = 1;
364422
continue;
423+
} else if ((err == -ESTALE ||
424+
err == -NFS4ERR_OFFLOAD_DENIED ||
425+
err == -ENOTSUPP) &&
426+
!nfs42_files_from_same_server(src, dst)) {
427+
nfs42_do_offload_cancel_async(src, &args.src_stateid);
428+
err = -EOPNOTSUPP;
429+
break;
365430
}
366431

367432
err2 = nfs4_handle_exception(server, err, &src_exception);
@@ -459,6 +524,76 @@ static int nfs42_do_offload_cancel_async(struct file *dst,
459524
return status;
460525
}
461526

527+
int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
528+
struct nfs42_copy_notify_args *args,
529+
struct nfs42_copy_notify_res *res)
530+
{
531+
struct nfs_server *src_server = NFS_SERVER(file_inode(src));
532+
struct rpc_message msg = {
533+
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY_NOTIFY],
534+
.rpc_argp = args,
535+
.rpc_resp = res,
536+
};
537+
int status;
538+
struct nfs_open_context *ctx;
539+
struct nfs_lock_context *l_ctx;
540+
541+
ctx = get_nfs_open_context(nfs_file_open_context(src));
542+
l_ctx = nfs_get_lock_context(ctx);
543+
if (IS_ERR(l_ctx))
544+
return PTR_ERR(l_ctx);
545+
546+
status = nfs4_set_rw_stateid(&args->cna_src_stateid, ctx, l_ctx,
547+
FMODE_READ);
548+
nfs_put_lock_context(l_ctx);
549+
if (status)
550+
return status;
551+
552+
status = nfs4_call_sync(src_server->client, src_server, &msg,
553+
&args->cna_seq_args, &res->cnr_seq_res, 0);
554+
if (status == -ENOTSUPP)
555+
src_server->caps &= ~NFS_CAP_COPY_NOTIFY;
556+
557+
put_nfs_open_context(nfs_file_open_context(src));
558+
return status;
559+
}
560+
561+
int nfs42_proc_copy_notify(struct file *src, struct file *dst,
562+
struct nfs42_copy_notify_res *res)
563+
{
564+
struct nfs_server *src_server = NFS_SERVER(file_inode(src));
565+
struct nfs42_copy_notify_args *args;
566+
struct nfs4_exception exception = {
567+
.inode = file_inode(src),
568+
};
569+
int status;
570+
571+
if (!(src_server->caps & NFS_CAP_COPY_NOTIFY))
572+
return -EOPNOTSUPP;
573+
574+
args = kzalloc(sizeof(struct nfs42_copy_notify_args), GFP_NOFS);
575+
if (args == NULL)
576+
return -ENOMEM;
577+
578+
args->cna_src_fh = NFS_FH(file_inode(src)),
579+
args->cna_dst.nl4_type = NL4_NETADDR;
580+
nfs42_set_netaddr(dst, &args->cna_dst.u.nl4_addr);
581+
exception.stateid = &args->cna_src_stateid;
582+
583+
do {
584+
status = _nfs42_proc_copy_notify(src, dst, args, res);
585+
if (status == -ENOTSUPP) {
586+
status = -EOPNOTSUPP;
587+
goto out;
588+
}
589+
status = nfs4_handle_exception(src_server, status, &exception);
590+
} while (exception.retry);
591+
592+
out:
593+
kfree(args);
594+
return status;
595+
}
596+
462597
static loff_t _nfs42_proc_llseek(struct file *filep,
463598
struct nfs_lock_context *lock, loff_t offset, int whence)
464599
{

0 commit comments

Comments
 (0)