forked from Minki/linux
Merge branch 'linux-ssc-for-5.5'
This commit is contained in:
commit
807ce06c24
@ -13,8 +13,10 @@
|
||||
#define PNFS_LAYOUTSTATS_MAXDEV (4)
|
||||
|
||||
/* nfs4.2proc.c */
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
int nfs42_proc_allocate(struct file *, loff_t, loff_t);
|
||||
ssize_t nfs42_proc_copy(struct file *, loff_t, struct file *, loff_t, size_t);
|
||||
ssize_t nfs42_proc_copy(struct file *, loff_t, struct file *, loff_t, size_t,
|
||||
struct nl4_server *, nfs4_stateid *, bool);
|
||||
int nfs42_proc_deallocate(struct file *, loff_t, loff_t);
|
||||
loff_t nfs42_proc_llseek(struct file *, loff_t, int);
|
||||
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);
|
||||
int nfs42_proc_layouterror(struct pnfs_layout_segment *lseg,
|
||||
const struct nfs42_layout_error *errors,
|
||||
size_t n);
|
||||
int nfs42_proc_copy_notify(struct file *, struct file *,
|
||||
struct nfs42_copy_notify_res *);
|
||||
static inline bool nfs42_files_from_same_server(struct file *in,
|
||||
struct file *out)
|
||||
{
|
||||
struct nfs_client *c_in = (NFS_SERVER(file_inode(in)))->nfs_client;
|
||||
struct nfs_client *c_out = (NFS_SERVER(file_inode(out)))->nfs_client;
|
||||
|
||||
return nfs4_check_serverowner_major_id(c_in->cl_serverowner,
|
||||
c_out->cl_serverowner);
|
||||
}
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
#endif /* __LINUX_FS_NFS_NFS4_2_H */
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
|
||||
*/
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sunrpc/addr.h>
|
||||
#include <linux/sunrpc/sched.h>
|
||||
#include <linux/nfs.h>
|
||||
#include <linux/nfs3.h>
|
||||
@ -15,10 +16,30 @@
|
||||
#include "pnfs.h"
|
||||
#include "nfs4session.h"
|
||||
#include "internal.h"
|
||||
#include "delegation.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_PROC
|
||||
static int nfs42_do_offload_cancel_async(struct file *dst, nfs4_stateid *std);
|
||||
|
||||
static void nfs42_set_netaddr(struct file *filep, struct nfs42_netaddr *naddr)
|
||||
{
|
||||
struct nfs_client *clp = (NFS_SERVER(file_inode(filep)))->nfs_client;
|
||||
unsigned short port = 2049;
|
||||
|
||||
rcu_read_lock();
|
||||
naddr->netid_len = scnprintf(naddr->netid,
|
||||
sizeof(naddr->netid), "%s",
|
||||
rpc_peeraddr2str(clp->cl_rpcclient,
|
||||
RPC_DISPLAY_NETID));
|
||||
naddr->addr_len = scnprintf(naddr->addr,
|
||||
sizeof(naddr->addr),
|
||||
"%s.%u.%u",
|
||||
rpc_peeraddr2str(clp->cl_rpcclient,
|
||||
RPC_DISPLAY_ADDR),
|
||||
port >> 8, port & 255);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
|
||||
struct nfs_lock_context *lock, loff_t offset, loff_t len)
|
||||
{
|
||||
@ -132,22 +153,26 @@ out_unlock:
|
||||
}
|
||||
|
||||
static int handle_async_copy(struct nfs42_copy_res *res,
|
||||
struct nfs_server *server,
|
||||
struct nfs_server *dst_server,
|
||||
struct nfs_server *src_server,
|
||||
struct file *src,
|
||||
struct file *dst,
|
||||
nfs4_stateid *src_stateid)
|
||||
nfs4_stateid *src_stateid,
|
||||
bool *restart)
|
||||
{
|
||||
struct nfs4_copy_state *copy, *tmp_copy;
|
||||
int status = NFS4_OK;
|
||||
bool found_pending = false;
|
||||
struct nfs_open_context *ctx = nfs_file_open_context(dst);
|
||||
struct nfs_open_context *dst_ctx = nfs_file_open_context(dst);
|
||||
struct nfs_open_context *src_ctx = nfs_file_open_context(src);
|
||||
|
||||
copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock(&server->nfs_client->cl_lock);
|
||||
list_for_each_entry(tmp_copy, &server->nfs_client->pending_cb_stateids,
|
||||
spin_lock(&dst_server->nfs_client->cl_lock);
|
||||
list_for_each_entry(tmp_copy,
|
||||
&dst_server->nfs_client->pending_cb_stateids,
|
||||
copies) {
|
||||
if (memcmp(&res->write_res.stateid, &tmp_copy->stateid,
|
||||
NFS4_STATEID_SIZE))
|
||||
@ -157,7 +182,7 @@ static int handle_async_copy(struct nfs42_copy_res *res,
|
||||
break;
|
||||
}
|
||||
if (found_pending) {
|
||||
spin_unlock(&server->nfs_client->cl_lock);
|
||||
spin_unlock(&dst_server->nfs_client->cl_lock);
|
||||
kfree(copy);
|
||||
copy = tmp_copy;
|
||||
goto out;
|
||||
@ -165,19 +190,32 @@ static int handle_async_copy(struct nfs42_copy_res *res,
|
||||
|
||||
memcpy(©->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE);
|
||||
init_completion(©->completion);
|
||||
copy->parent_state = ctx->state;
|
||||
copy->parent_dst_state = dst_ctx->state;
|
||||
copy->parent_src_state = src_ctx->state;
|
||||
|
||||
list_add_tail(©->copies, &server->ss_copies);
|
||||
spin_unlock(&server->nfs_client->cl_lock);
|
||||
list_add_tail(©->copies, &dst_server->ss_copies);
|
||||
spin_unlock(&dst_server->nfs_client->cl_lock);
|
||||
|
||||
if (dst_server != src_server) {
|
||||
spin_lock(&src_server->nfs_client->cl_lock);
|
||||
list_add_tail(©->src_copies, &src_server->ss_copies);
|
||||
spin_unlock(&src_server->nfs_client->cl_lock);
|
||||
}
|
||||
|
||||
status = wait_for_completion_interruptible(©->completion);
|
||||
spin_lock(&server->nfs_client->cl_lock);
|
||||
spin_lock(&dst_server->nfs_client->cl_lock);
|
||||
list_del_init(©->copies);
|
||||
spin_unlock(&server->nfs_client->cl_lock);
|
||||
spin_unlock(&dst_server->nfs_client->cl_lock);
|
||||
if (dst_server != src_server) {
|
||||
spin_lock(&src_server->nfs_client->cl_lock);
|
||||
list_del_init(©->src_copies);
|
||||
spin_unlock(&src_server->nfs_client->cl_lock);
|
||||
}
|
||||
if (status == -ERESTARTSYS) {
|
||||
goto out_cancel;
|
||||
} else if (copy->flags) {
|
||||
} else if (copy->flags || copy->error == NFS4ERR_PARTNER_NO_AUTH) {
|
||||
status = -EAGAIN;
|
||||
*restart = true;
|
||||
goto out_cancel;
|
||||
}
|
||||
out:
|
||||
@ -185,12 +223,14 @@ out:
|
||||
memcpy(&res->write_res.verifier, ©->verf, sizeof(copy->verf));
|
||||
status = -copy->error;
|
||||
|
||||
out_free:
|
||||
kfree(copy);
|
||||
return status;
|
||||
out_cancel:
|
||||
nfs42_do_offload_cancel_async(dst, ©->stateid);
|
||||
kfree(copy);
|
||||
return status;
|
||||
if (!nfs42_files_from_same_server(src, dst))
|
||||
nfs42_do_offload_cancel_async(src, src_stateid);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
static int process_copy_commit(struct file *dst, loff_t pos_dst,
|
||||
@ -222,7 +262,10 @@ static ssize_t _nfs42_proc_copy(struct file *src,
|
||||
struct file *dst,
|
||||
struct nfs_lock_context *dst_lock,
|
||||
struct nfs42_copy_args *args,
|
||||
struct nfs42_copy_res *res)
|
||||
struct nfs42_copy_res *res,
|
||||
struct nl4_server *nss,
|
||||
nfs4_stateid *cnr_stateid,
|
||||
bool *restart)
|
||||
{
|
||||
struct rpc_message msg = {
|
||||
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY],
|
||||
@ -230,17 +273,23 @@ static ssize_t _nfs42_proc_copy(struct file *src,
|
||||
.rpc_resp = res,
|
||||
};
|
||||
struct inode *dst_inode = file_inode(dst);
|
||||
struct nfs_server *server = NFS_SERVER(dst_inode);
|
||||
struct inode *src_inode = file_inode(src);
|
||||
struct nfs_server *dst_server = NFS_SERVER(dst_inode);
|
||||
struct nfs_server *src_server = NFS_SERVER(src_inode);
|
||||
loff_t pos_src = args->src_pos;
|
||||
loff_t pos_dst = args->dst_pos;
|
||||
size_t count = args->count;
|
||||
ssize_t status;
|
||||
|
||||
status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context,
|
||||
src_lock, FMODE_READ);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (nss) {
|
||||
args->cp_src = nss;
|
||||
nfs4_stateid_copy(&args->src_stateid, cnr_stateid);
|
||||
} else {
|
||||
status = nfs4_set_rw_stateid(&args->src_stateid,
|
||||
src_lock->open_context, src_lock, FMODE_READ);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
status = nfs_filemap_write_and_wait_range(file_inode(src)->i_mapping,
|
||||
pos_src, pos_src + (loff_t)count - 1);
|
||||
if (status)
|
||||
@ -262,13 +311,15 @@ static ssize_t _nfs42_proc_copy(struct file *src,
|
||||
if (!res->commit_res.verf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
set_bit(NFS_CLNT_SRC_SSC_COPY_STATE,
|
||||
&src_lock->open_context->state->flags);
|
||||
set_bit(NFS_CLNT_DST_SSC_COPY_STATE,
|
||||
&dst_lock->open_context->state->flags);
|
||||
|
||||
status = nfs4_call_sync(server->client, server, &msg,
|
||||
status = nfs4_call_sync(dst_server->client, dst_server, &msg,
|
||||
&args->seq_args, &res->seq_res, 0);
|
||||
if (status == -ENOTSUPP)
|
||||
server->caps &= ~NFS_CAP_COPY;
|
||||
dst_server->caps &= ~NFS_CAP_COPY;
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
@ -280,8 +331,8 @@ static ssize_t _nfs42_proc_copy(struct file *src,
|
||||
}
|
||||
|
||||
if (!res->synchronous) {
|
||||
status = handle_async_copy(res, server, src, dst,
|
||||
&args->src_stateid);
|
||||
status = handle_async_copy(res, dst_server, src_server, src,
|
||||
dst, &args->src_stateid, restart);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
@ -304,8 +355,9 @@ out:
|
||||
}
|
||||
|
||||
ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
|
||||
struct file *dst, loff_t pos_dst,
|
||||
size_t count)
|
||||
struct file *dst, loff_t pos_dst, size_t count,
|
||||
struct nl4_server *nss,
|
||||
nfs4_stateid *cnr_stateid, bool sync)
|
||||
{
|
||||
struct nfs_server *server = NFS_SERVER(file_inode(dst));
|
||||
struct nfs_lock_context *src_lock;
|
||||
@ -316,7 +368,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
|
||||
.dst_fh = NFS_FH(file_inode(dst)),
|
||||
.dst_pos = pos_dst,
|
||||
.count = count,
|
||||
.sync = false,
|
||||
.sync = sync,
|
||||
};
|
||||
struct nfs42_copy_res res;
|
||||
struct nfs4_exception src_exception = {
|
||||
@ -328,6 +380,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
|
||||
.stateid = &args.dst_stateid,
|
||||
};
|
||||
ssize_t err, err2;
|
||||
bool restart = false;
|
||||
|
||||
src_lock = nfs_get_lock_context(nfs_file_open_context(src));
|
||||
if (IS_ERR(src_lock))
|
||||
@ -347,21 +400,33 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
|
||||
inode_lock(file_inode(dst));
|
||||
err = _nfs42_proc_copy(src, src_lock,
|
||||
dst, dst_lock,
|
||||
&args, &res);
|
||||
&args, &res,
|
||||
nss, cnr_stateid, &restart);
|
||||
inode_unlock(file_inode(dst));
|
||||
|
||||
if (err >= 0)
|
||||
break;
|
||||
if (err == -ENOTSUPP) {
|
||||
if (err == -ENOTSUPP &&
|
||||
nfs42_files_from_same_server(src, dst)) {
|
||||
err = -EOPNOTSUPP;
|
||||
break;
|
||||
} else if (err == -EAGAIN) {
|
||||
dst_exception.retry = 1;
|
||||
continue;
|
||||
if (!restart) {
|
||||
dst_exception.retry = 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else if (err == -NFS4ERR_OFFLOAD_NO_REQS && !args.sync) {
|
||||
args.sync = true;
|
||||
dst_exception.retry = 1;
|
||||
continue;
|
||||
} else if ((err == -ESTALE ||
|
||||
err == -NFS4ERR_OFFLOAD_DENIED ||
|
||||
err == -ENOTSUPP) &&
|
||||
!nfs42_files_from_same_server(src, dst)) {
|
||||
nfs42_do_offload_cancel_async(src, &args.src_stateid);
|
||||
err = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
err2 = nfs4_handle_exception(server, err, &src_exception);
|
||||
@ -459,6 +524,76 @@ static int nfs42_do_offload_cancel_async(struct file *dst,
|
||||
return status;
|
||||
}
|
||||
|
||||
int _nfs42_proc_copy_notify(struct file *src, struct file *dst,
|
||||
struct nfs42_copy_notify_args *args,
|
||||
struct nfs42_copy_notify_res *res)
|
||||
{
|
||||
struct nfs_server *src_server = NFS_SERVER(file_inode(src));
|
||||
struct rpc_message msg = {
|
||||
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY_NOTIFY],
|
||||
.rpc_argp = args,
|
||||
.rpc_resp = res,
|
||||
};
|
||||
int status;
|
||||
struct nfs_open_context *ctx;
|
||||
struct nfs_lock_context *l_ctx;
|
||||
|
||||
ctx = get_nfs_open_context(nfs_file_open_context(src));
|
||||
l_ctx = nfs_get_lock_context(ctx);
|
||||
if (IS_ERR(l_ctx))
|
||||
return PTR_ERR(l_ctx);
|
||||
|
||||
status = nfs4_set_rw_stateid(&args->cna_src_stateid, ctx, l_ctx,
|
||||
FMODE_READ);
|
||||
nfs_put_lock_context(l_ctx);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = nfs4_call_sync(src_server->client, src_server, &msg,
|
||||
&args->cna_seq_args, &res->cnr_seq_res, 0);
|
||||
if (status == -ENOTSUPP)
|
||||
src_server->caps &= ~NFS_CAP_COPY_NOTIFY;
|
||||
|
||||
put_nfs_open_context(nfs_file_open_context(src));
|
||||
return status;
|
||||
}
|
||||
|
||||
int nfs42_proc_copy_notify(struct file *src, struct file *dst,
|
||||
struct nfs42_copy_notify_res *res)
|
||||
{
|
||||
struct nfs_server *src_server = NFS_SERVER(file_inode(src));
|
||||
struct nfs42_copy_notify_args *args;
|
||||
struct nfs4_exception exception = {
|
||||
.inode = file_inode(src),
|
||||
};
|
||||
int status;
|
||||
|
||||
if (!(src_server->caps & NFS_CAP_COPY_NOTIFY))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
args = kzalloc(sizeof(struct nfs42_copy_notify_args), GFP_NOFS);
|
||||
if (args == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
args->cna_src_fh = NFS_FH(file_inode(src)),
|
||||
args->cna_dst.nl4_type = NL4_NETADDR;
|
||||
nfs42_set_netaddr(dst, &args->cna_dst.u.nl4_addr);
|
||||
exception.stateid = &args->cna_src_stateid;
|
||||
|
||||
do {
|
||||
status = _nfs42_proc_copy_notify(src, dst, args, res);
|
||||
if (status == -ENOTSUPP) {
|
||||
status = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
status = nfs4_handle_exception(src_server, status, &exception);
|
||||
} while (exception.retry);
|
||||
|
||||
out:
|
||||
kfree(args);
|
||||
return status;
|
||||
}
|
||||
|
||||
static loff_t _nfs42_proc_llseek(struct file *filep,
|
||||
struct nfs_lock_context *lock, loff_t offset, int whence)
|
||||
{
|
||||
|
@ -21,7 +21,10 @@
|
||||
#define encode_copy_maxsz (op_encode_hdr_maxsz + \
|
||||
XDR_QUADLEN(NFS4_STATEID_SIZE) + \
|
||||
XDR_QUADLEN(NFS4_STATEID_SIZE) + \
|
||||
2 + 2 + 2 + 1 + 1 + 1)
|
||||
2 + 2 + 2 + 1 + 1 + 1 +\
|
||||
1 + /* One cnr_source_server */\
|
||||
1 + /* nl4_type */ \
|
||||
1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
|
||||
#define decode_copy_maxsz (op_decode_hdr_maxsz + \
|
||||
NFS42_WRITE_RES_SIZE + \
|
||||
1 /* cr_consecutive */ + \
|
||||
@ -29,6 +32,16 @@
|
||||
#define encode_offload_cancel_maxsz (op_encode_hdr_maxsz + \
|
||||
XDR_QUADLEN(NFS4_STATEID_SIZE))
|
||||
#define decode_offload_cancel_maxsz (op_decode_hdr_maxsz)
|
||||
#define encode_copy_notify_maxsz (op_encode_hdr_maxsz + \
|
||||
XDR_QUADLEN(NFS4_STATEID_SIZE) + \
|
||||
1 + /* nl4_type */ \
|
||||
1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
|
||||
#define decode_copy_notify_maxsz (op_decode_hdr_maxsz + \
|
||||
3 + /* cnr_lease_time */\
|
||||
XDR_QUADLEN(NFS4_STATEID_SIZE) + \
|
||||
1 + /* Support 1 cnr_source_server */\
|
||||
1 + /* nl4_type */ \
|
||||
1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
|
||||
#define encode_deallocate_maxsz (op_encode_hdr_maxsz + \
|
||||
encode_fallocate_maxsz)
|
||||
#define decode_deallocate_maxsz (op_decode_hdr_maxsz)
|
||||
@ -99,6 +112,12 @@
|
||||
decode_sequence_maxsz + \
|
||||
decode_putfh_maxsz + \
|
||||
decode_offload_cancel_maxsz)
|
||||
#define NFS4_enc_copy_notify_sz (compound_encode_hdr_maxsz + \
|
||||
encode_putfh_maxsz + \
|
||||
encode_copy_notify_maxsz)
|
||||
#define NFS4_dec_copy_notify_sz (compound_decode_hdr_maxsz + \
|
||||
decode_putfh_maxsz + \
|
||||
decode_copy_notify_maxsz)
|
||||
#define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \
|
||||
encode_sequence_maxsz + \
|
||||
encode_putfh_maxsz + \
|
||||
@ -166,6 +185,26 @@ static void encode_allocate(struct xdr_stream *xdr,
|
||||
encode_fallocate(xdr, args);
|
||||
}
|
||||
|
||||
static void encode_nl4_server(struct xdr_stream *xdr,
|
||||
const struct nl4_server *ns)
|
||||
{
|
||||
encode_uint32(xdr, ns->nl4_type);
|
||||
switch (ns->nl4_type) {
|
||||
case NL4_NAME:
|
||||
case NL4_URL:
|
||||
encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
|
||||
break;
|
||||
case NL4_NETADDR:
|
||||
encode_string(xdr, ns->u.nl4_addr.netid_len,
|
||||
ns->u.nl4_addr.netid);
|
||||
encode_string(xdr, ns->u.nl4_addr.addr_len,
|
||||
ns->u.nl4_addr.addr);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void encode_copy(struct xdr_stream *xdr,
|
||||
const struct nfs42_copy_args *args,
|
||||
struct compound_hdr *hdr)
|
||||
@ -180,7 +219,12 @@ static void encode_copy(struct xdr_stream *xdr,
|
||||
|
||||
encode_uint32(xdr, 1); /* consecutive = true */
|
||||
encode_uint32(xdr, args->sync);
|
||||
encode_uint32(xdr, 0); /* src server list */
|
||||
if (args->cp_src == NULL) { /* intra-ssc */
|
||||
encode_uint32(xdr, 0); /* no src server list */
|
||||
return;
|
||||
}
|
||||
encode_uint32(xdr, 1); /* supporting 1 server */
|
||||
encode_nl4_server(xdr, args->cp_src);
|
||||
}
|
||||
|
||||
static void encode_offload_cancel(struct xdr_stream *xdr,
|
||||
@ -191,6 +235,15 @@ static void encode_offload_cancel(struct xdr_stream *xdr,
|
||||
encode_nfs4_stateid(xdr, &args->osa_stateid);
|
||||
}
|
||||
|
||||
static void encode_copy_notify(struct xdr_stream *xdr,
|
||||
const struct nfs42_copy_notify_args *args,
|
||||
struct compound_hdr *hdr)
|
||||
{
|
||||
encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
|
||||
encode_nfs4_stateid(xdr, &args->cna_src_stateid);
|
||||
encode_nl4_server(xdr, &args->cna_dst);
|
||||
}
|
||||
|
||||
static void encode_deallocate(struct xdr_stream *xdr,
|
||||
const struct nfs42_falloc_args *args,
|
||||
struct compound_hdr *hdr)
|
||||
@ -354,6 +407,25 @@ static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
|
||||
encode_nops(&hdr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode COPY_NOTIFY request
|
||||
*/
|
||||
static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
|
||||
struct xdr_stream *xdr,
|
||||
const void *data)
|
||||
{
|
||||
const struct nfs42_copy_notify_args *args = data;
|
||||
struct compound_hdr hdr = {
|
||||
.minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
|
||||
};
|
||||
|
||||
encode_compound_hdr(xdr, req, &hdr);
|
||||
encode_sequence(xdr, &args->cna_seq_args, &hdr);
|
||||
encode_putfh(xdr, args->cna_src_fh, &hdr);
|
||||
encode_copy_notify(xdr, args, &hdr);
|
||||
encode_nops(&hdr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode DEALLOCATE request
|
||||
*/
|
||||
@ -490,6 +562,58 @@ static int decode_write_response(struct xdr_stream *xdr,
|
||||
return decode_verifier(xdr, &res->verifier.verifier);
|
||||
}
|
||||
|
||||
static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
|
||||
{
|
||||
struct nfs42_netaddr *naddr;
|
||||
uint32_t dummy;
|
||||
char *dummy_str;
|
||||
__be32 *p;
|
||||
int status;
|
||||
|
||||
/* nl_type */
|
||||
p = xdr_inline_decode(xdr, 4);
|
||||
if (unlikely(!p))
|
||||
return -EIO;
|
||||
ns->nl4_type = be32_to_cpup(p);
|
||||
switch (ns->nl4_type) {
|
||||
case NL4_NAME:
|
||||
case NL4_URL:
|
||||
status = decode_opaque_inline(xdr, &dummy, &dummy_str);
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
|
||||
return -EIO;
|
||||
memcpy(&ns->u.nl4_str, dummy_str, dummy);
|
||||
ns->u.nl4_str_sz = dummy;
|
||||
break;
|
||||
case NL4_NETADDR:
|
||||
naddr = &ns->u.nl4_addr;
|
||||
|
||||
/* netid string */
|
||||
status = decode_opaque_inline(xdr, &dummy, &dummy_str);
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
|
||||
return -EIO;
|
||||
naddr->netid_len = dummy;
|
||||
memcpy(naddr->netid, dummy_str, naddr->netid_len);
|
||||
|
||||
/* uaddr string */
|
||||
status = decode_opaque_inline(xdr, &dummy, &dummy_str);
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
|
||||
return -EIO;
|
||||
naddr->addr_len = dummy;
|
||||
memcpy(naddr->addr, dummy_str, naddr->addr_len);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_copy_requirements(struct xdr_stream *xdr,
|
||||
struct nfs42_copy_res *res) {
|
||||
__be32 *p;
|
||||
@ -529,6 +653,42 @@ static int decode_offload_cancel(struct xdr_stream *xdr,
|
||||
return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
|
||||
}
|
||||
|
||||
static int decode_copy_notify(struct xdr_stream *xdr,
|
||||
struct nfs42_copy_notify_res *res)
|
||||
{
|
||||
__be32 *p;
|
||||
int status, count;
|
||||
|
||||
status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
|
||||
if (status)
|
||||
return status;
|
||||
/* cnr_lease_time */
|
||||
p = xdr_inline_decode(xdr, 12);
|
||||
if (unlikely(!p))
|
||||
return -EIO;
|
||||
p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
|
||||
res->cnr_lease_time.nseconds = be32_to_cpup(p);
|
||||
|
||||
status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
|
||||
if (unlikely(status))
|
||||
return -EIO;
|
||||
|
||||
/* number of source addresses */
|
||||
p = xdr_inline_decode(xdr, 4);
|
||||
if (unlikely(!p))
|
||||
return -EIO;
|
||||
|
||||
count = be32_to_cpup(p);
|
||||
if (count > 1)
|
||||
pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
|
||||
__func__, count);
|
||||
|
||||
status = decode_nl4_server(xdr, &res->cnr_src);
|
||||
if (unlikely(status))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
|
||||
{
|
||||
return decode_op_hdr(xdr, OP_DEALLOCATE);
|
||||
@ -656,6 +816,32 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode COPY_NOTIFY response
|
||||
*/
|
||||
static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
|
||||
struct xdr_stream *xdr,
|
||||
void *data)
|
||||
{
|
||||
struct nfs42_copy_notify_res *res = data;
|
||||
struct compound_hdr hdr;
|
||||
int status;
|
||||
|
||||
status = decode_compound_hdr(xdr, &hdr);
|
||||
if (status)
|
||||
goto out;
|
||||
status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
|
||||
if (status)
|
||||
goto out;
|
||||
status = decode_putfh(xdr);
|
||||
if (status)
|
||||
goto out;
|
||||
status = decode_copy_notify(xdr, res);
|
||||
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode DEALLOCATE request
|
||||
*/
|
||||
|
@ -168,6 +168,8 @@ enum {
|
||||
NFS_STATE_CHANGE_WAIT, /* A state changing operation is outstanding */
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
NFS_CLNT_DST_SSC_COPY_STATE, /* dst server open state on client*/
|
||||
NFS_CLNT_SRC_SSC_COPY_STATE, /* src server open state on client*/
|
||||
NFS_SRV_SSC_COPY_STATE, /* ssc state on the dst server */
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
};
|
||||
|
||||
@ -311,6 +313,13 @@ extern int nfs4_set_rw_stateid(nfs4_stateid *stateid,
|
||||
const struct nfs_open_context *ctx,
|
||||
const struct nfs_lock_context *l_ctx,
|
||||
fmode_t fmode);
|
||||
extern int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||
struct nfs_fattr *fattr, struct nfs4_label *label,
|
||||
struct inode *inode);
|
||||
extern int update_open_stateid(struct nfs4_state *state,
|
||||
const nfs4_stateid *open_stateid,
|
||||
const nfs4_stateid *deleg_stateid,
|
||||
fmode_t fmode);
|
||||
|
||||
extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
|
||||
struct nfs_fsinfo *fsinfo);
|
||||
@ -457,6 +466,8 @@ int nfs41_discover_server_trunking(struct nfs_client *clp,
|
||||
struct nfs_client **, const struct cred *);
|
||||
extern void nfs4_schedule_session_recovery(struct nfs4_session *, int);
|
||||
extern void nfs41_notify_server(struct nfs_client *);
|
||||
bool nfs4_check_serverowner_major_id(struct nfs41_server_owner *o1,
|
||||
struct nfs41_server_owner *o2);
|
||||
#else
|
||||
static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
|
||||
{
|
||||
|
@ -629,7 +629,7 @@ out:
|
||||
/*
|
||||
* Returns true if the server major ids match
|
||||
*/
|
||||
static bool
|
||||
bool
|
||||
nfs4_check_serverowner_major_id(struct nfs41_server_owner *o1,
|
||||
struct nfs41_server_owner *o2)
|
||||
{
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <linux/file.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/file.h>
|
||||
#include "delegation.h"
|
||||
#include "internal.h"
|
||||
#include "iostat.h"
|
||||
@ -133,14 +134,54 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
|
||||
struct file *file_out, loff_t pos_out,
|
||||
size_t count, unsigned int flags)
|
||||
{
|
||||
struct nfs42_copy_notify_res *cn_resp = NULL;
|
||||
struct nl4_server *nss = NULL;
|
||||
nfs4_stateid *cnrs = NULL;
|
||||
ssize_t ret;
|
||||
bool sync = false;
|
||||
|
||||
/* Only offload copy if superblock is the same */
|
||||
if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
|
||||
if (file_in->f_op != &nfs4_file_operations)
|
||||
return -EXDEV;
|
||||
if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY))
|
||||
return -EOPNOTSUPP;
|
||||
if (file_inode(file_in) == file_inode(file_out))
|
||||
return -EOPNOTSUPP;
|
||||
return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
|
||||
/* if the copy size if smaller than 2 RPC payloads, make it
|
||||
* synchronous
|
||||
*/
|
||||
if (count <= 2 * NFS_SERVER(file_inode(file_in))->rsize)
|
||||
sync = true;
|
||||
retry:
|
||||
if (!nfs42_files_from_same_server(file_in, file_out)) {
|
||||
/* for inter copy, if copy size if smaller than 12 RPC
|
||||
* payloads, fallback to traditional copy. There are
|
||||
* 14 RPCs during an NFSv4.x mount between source/dest
|
||||
* servers.
|
||||
*/
|
||||
if (sync ||
|
||||
count <= 14 * NFS_SERVER(file_inode(file_in))->rsize)
|
||||
return -EOPNOTSUPP;
|
||||
cn_resp = kzalloc(sizeof(struct nfs42_copy_notify_res),
|
||||
GFP_NOFS);
|
||||
if (unlikely(cn_resp == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
ret = nfs42_proc_copy_notify(file_in, file_out, cn_resp);
|
||||
if (ret) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
nss = &cn_resp->cnr_src;
|
||||
cnrs = &cn_resp->cnr_stateid;
|
||||
}
|
||||
ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count,
|
||||
nss, cnrs, sync);
|
||||
out:
|
||||
kfree(cn_resp);
|
||||
if (ret == -EAGAIN)
|
||||
goto retry;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
|
||||
@ -263,6 +304,100 @@ out_unlock:
|
||||
out:
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static int read_name_gen = 1;
|
||||
#define SSC_READ_NAME_BODY "ssc_read_%d"
|
||||
|
||||
struct file *
|
||||
nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
|
||||
nfs4_stateid *stateid)
|
||||
{
|
||||
struct nfs_fattr fattr;
|
||||
struct file *filep, *res;
|
||||
struct nfs_server *server;
|
||||
struct inode *r_ino = NULL;
|
||||
struct nfs_open_context *ctx;
|
||||
struct nfs4_state_owner *sp;
|
||||
char *read_name;
|
||||
int len, status = 0;
|
||||
|
||||
server = NFS_SERVER(ss_mnt->mnt_root->d_inode);
|
||||
|
||||
nfs_fattr_init(&fattr);
|
||||
|
||||
status = nfs4_proc_getattr(server, src_fh, &fattr, NULL, NULL);
|
||||
if (status < 0) {
|
||||
res = ERR_PTR(status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = ERR_PTR(-ENOMEM);
|
||||
len = strlen(SSC_READ_NAME_BODY) + 16;
|
||||
read_name = kzalloc(len, GFP_NOFS);
|
||||
if (read_name == NULL)
|
||||
goto out;
|
||||
snprintf(read_name, len, SSC_READ_NAME_BODY, read_name_gen++);
|
||||
|
||||
r_ino = nfs_fhget(ss_mnt->mnt_root->d_inode->i_sb, src_fh, &fattr,
|
||||
NULL);
|
||||
if (IS_ERR(r_ino)) {
|
||||
res = ERR_CAST(r_ino);
|
||||
goto out;
|
||||
}
|
||||
|
||||
filep = alloc_file_pseudo(r_ino, ss_mnt, read_name, FMODE_READ,
|
||||
r_ino->i_fop);
|
||||
if (IS_ERR(filep)) {
|
||||
res = ERR_CAST(filep);
|
||||
goto out;
|
||||
}
|
||||
filep->f_mode |= FMODE_READ;
|
||||
|
||||
ctx = alloc_nfs_open_context(filep->f_path.dentry, filep->f_mode,
|
||||
filep);
|
||||
if (IS_ERR(ctx)) {
|
||||
res = ERR_CAST(ctx);
|
||||
goto out_filep;
|
||||
}
|
||||
|
||||
res = ERR_PTR(-EINVAL);
|
||||
sp = nfs4_get_state_owner(server, ctx->cred, GFP_KERNEL);
|
||||
if (sp == NULL)
|
||||
goto out_ctx;
|
||||
|
||||
ctx->state = nfs4_get_open_state(r_ino, sp);
|
||||
if (ctx->state == NULL)
|
||||
goto out_stateowner;
|
||||
|
||||
set_bit(NFS_SRV_SSC_COPY_STATE, &ctx->state->flags);
|
||||
set_bit(NFS_OPEN_STATE, &ctx->state->flags);
|
||||
memcpy(&ctx->state->open_stateid.other, &stateid->other,
|
||||
NFS4_STATEID_OTHER_SIZE);
|
||||
update_open_stateid(ctx->state, stateid, NULL, filep->f_mode);
|
||||
|
||||
nfs_file_set_open_context(filep, ctx);
|
||||
put_nfs_open_context(ctx);
|
||||
|
||||
file_ra_state_init(&filep->f_ra, filep->f_mapping->host->i_mapping);
|
||||
res = filep;
|
||||
out:
|
||||
return res;
|
||||
out_stateowner:
|
||||
nfs4_put_state_owner(sp);
|
||||
out_ctx:
|
||||
put_nfs_open_context(ctx);
|
||||
out_filep:
|
||||
fput(filep);
|
||||
goto out;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs42_ssc_open);
|
||||
void nfs42_ssc_close(struct file *filep)
|
||||
{
|
||||
struct nfs_open_context *ctx = nfs_file_open_context(filep);
|
||||
|
||||
ctx->state->flags = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs42_ssc_close);
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
const struct file_operations nfs4_file_operations = {
|
||||
|
@ -91,7 +91,6 @@ struct nfs4_opendata;
|
||||
static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
|
||||
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
|
||||
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
|
||||
static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label, struct inode *inode);
|
||||
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label, struct inode *inode);
|
||||
static int nfs4_do_setattr(struct inode *inode, const struct cred *cred,
|
||||
struct nfs_fattr *fattr, struct iattr *sattr,
|
||||
@ -476,6 +475,7 @@ static int nfs4_do_handle_exception(struct nfs_server *server,
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_EXPIRED:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
case -NFS4ERR_PARTNER_NO_AUTH:
|
||||
if (inode != NULL && stateid != NULL) {
|
||||
nfs_inode_find_state_and_recover(inode,
|
||||
stateid);
|
||||
@ -1716,7 +1716,7 @@ static void nfs_state_clear_delegation(struct nfs4_state *state)
|
||||
write_sequnlock(&state->seqlock);
|
||||
}
|
||||
|
||||
static int update_open_stateid(struct nfs4_state *state,
|
||||
int update_open_stateid(struct nfs4_state *state,
|
||||
const nfs4_stateid *open_stateid,
|
||||
const nfs4_stateid *delegation,
|
||||
fmode_t fmode)
|
||||
@ -4062,7 +4062,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||
return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
|
||||
}
|
||||
|
||||
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||
int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||
struct nfs_fattr *fattr, struct nfs4_label *label,
|
||||
struct inode *inode)
|
||||
{
|
||||
@ -9901,6 +9901,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
|
||||
| NFS_CAP_ALLOCATE
|
||||
| NFS_CAP_COPY
|
||||
| NFS_CAP_OFFLOAD_CANCEL
|
||||
| NFS_CAP_COPY_NOTIFY
|
||||
| NFS_CAP_DEALLOCATE
|
||||
| NFS_CAP_SEEK
|
||||
| NFS_CAP_LAYOUTSTATS
|
||||
|
@ -1557,16 +1557,32 @@ static void nfs42_complete_copies(struct nfs4_state_owner *sp, struct nfs4_state
|
||||
{
|
||||
struct nfs4_copy_state *copy;
|
||||
|
||||
if (!test_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags))
|
||||
if (!test_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags) &&
|
||||
!test_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags))
|
||||
return;
|
||||
|
||||
spin_lock(&sp->so_server->nfs_client->cl_lock);
|
||||
list_for_each_entry(copy, &sp->so_server->ss_copies, copies) {
|
||||
if (!nfs4_stateid_match_other(&state->stateid, ©->parent_state->stateid))
|
||||
continue;
|
||||
if ((test_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags) &&
|
||||
!nfs4_stateid_match_other(&state->stateid,
|
||||
©->parent_dst_state->stateid)))
|
||||
continue;
|
||||
copy->flags = 1;
|
||||
complete(©->completion);
|
||||
break;
|
||||
if (test_and_clear_bit(NFS_CLNT_DST_SSC_COPY_STATE,
|
||||
&state->flags)) {
|
||||
clear_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags);
|
||||
complete(©->completion);
|
||||
}
|
||||
}
|
||||
list_for_each_entry(copy, &sp->so_server->ss_copies, src_copies) {
|
||||
if ((test_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags) &&
|
||||
!nfs4_stateid_match_other(&state->stateid,
|
||||
©->parent_src_state->stateid)))
|
||||
continue;
|
||||
copy->flags = 1;
|
||||
if (test_and_clear_bit(NFS_CLNT_DST_SSC_COPY_STATE,
|
||||
&state->flags))
|
||||
complete(©->completion);
|
||||
}
|
||||
spin_unlock(&sp->so_server->nfs_client->cl_lock);
|
||||
}
|
||||
@ -1610,6 +1626,9 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
|
||||
struct nfs4_state *state;
|
||||
unsigned int loop = 0;
|
||||
int status = 0;
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
bool found_ssc_copy_state = false;
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
/* Note: we rely on the sp->so_states list being ordered
|
||||
* so that we always reclaim open(O_RDWR) and/or open(O_WRITE)
|
||||
@ -1629,6 +1648,13 @@ restart:
|
||||
continue;
|
||||
if (state->state == 0)
|
||||
continue;
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
if (test_bit(NFS_SRV_SSC_COPY_STATE, &state->flags)) {
|
||||
nfs4_state_mark_recovery_failed(state, -EIO);
|
||||
found_ssc_copy_state = true;
|
||||
continue;
|
||||
}
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
refcount_inc(&state->count);
|
||||
spin_unlock(&sp->so_lock);
|
||||
status = __nfs4_reclaim_open_state(sp, state, ops);
|
||||
@ -1683,6 +1709,10 @@ restart:
|
||||
}
|
||||
raw_write_seqcount_end(&sp->so_reclaim_seqcount);
|
||||
spin_unlock(&sp->so_lock);
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
if (found_ssc_copy_state)
|
||||
return -EIO;
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
return 0;
|
||||
out_err:
|
||||
nfs4_put_open_state(state);
|
||||
|
@ -7578,6 +7578,7 @@ const struct rpc_procinfo nfs4_procedures[] = {
|
||||
PROC42(CLONE, enc_clone, dec_clone),
|
||||
PROC42(COPY, enc_copy, dec_copy),
|
||||
PROC42(OFFLOAD_CANCEL, enc_offload_cancel, dec_offload_cancel),
|
||||
PROC42(COPY_NOTIFY, enc_copy_notify, dec_copy_notify),
|
||||
PROC(LOOKUPP, enc_lookupp, dec_lookupp),
|
||||
PROC42(LAYOUTERROR, enc_layouterror, dec_layouterror),
|
||||
};
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/uidgid.h>
|
||||
#include <uapi/linux/nfs4.h>
|
||||
#include <linux/sunrpc/msg_prot.h>
|
||||
|
||||
enum nfs4_acl_whotype {
|
||||
NFS4_ACL_WHO_NAMED = 0,
|
||||
@ -536,6 +537,7 @@ enum {
|
||||
NFSPROC4_CLNT_CLONE,
|
||||
NFSPROC4_CLNT_COPY,
|
||||
NFSPROC4_CLNT_OFFLOAD_CANCEL,
|
||||
NFSPROC4_CLNT_COPY_NOTIFY,
|
||||
|
||||
NFSPROC4_CLNT_LOOKUPP,
|
||||
NFSPROC4_CLNT_LAYOUTERROR,
|
||||
@ -674,4 +676,27 @@ struct nfs4_op_map {
|
||||
} u;
|
||||
};
|
||||
|
||||
struct nfs42_netaddr {
|
||||
char netid[RPCBIND_MAXNETIDLEN];
|
||||
char addr[RPCBIND_MAXUADDRLEN + 1];
|
||||
u32 netid_len;
|
||||
u32 addr_len;
|
||||
};
|
||||
|
||||
enum netloc_type4 {
|
||||
NL4_NAME = 1,
|
||||
NL4_URL = 2,
|
||||
NL4_NETADDR = 3,
|
||||
};
|
||||
|
||||
struct nl4_server {
|
||||
enum netloc_type4 nl4_type;
|
||||
union {
|
||||
struct { /* NL4_NAME, NL4_URL */
|
||||
int nl4_str_sz;
|
||||
char nl4_str[NFS4_OPAQUE_LIMIT + 1];
|
||||
};
|
||||
struct nfs42_netaddr nl4_addr; /* NL4_NETADDR */
|
||||
} u;
|
||||
};
|
||||
#endif
|
||||
|
@ -189,13 +189,15 @@ struct nfs_inode {
|
||||
|
||||
struct nfs4_copy_state {
|
||||
struct list_head copies;
|
||||
struct list_head src_copies;
|
||||
nfs4_stateid stateid;
|
||||
struct completion completion;
|
||||
uint64_t count;
|
||||
struct nfs_writeverf verf;
|
||||
int error;
|
||||
int flags;
|
||||
struct nfs4_state *parent_state;
|
||||
struct nfs4_state *parent_src_state;
|
||||
struct nfs4_state *parent_dst_state;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -279,5 +279,6 @@ struct nfs_server {
|
||||
#define NFS_CAP_COPY (1U << 24)
|
||||
#define NFS_CAP_OFFLOAD_CANCEL (1U << 25)
|
||||
#define NFS_CAP_LAYOUTERROR (1U << 26)
|
||||
#define NFS_CAP_COPY_NOTIFY (1U << 27)
|
||||
|
||||
#endif
|
||||
|
@ -1435,6 +1435,7 @@ struct nfs42_copy_args {
|
||||
|
||||
u64 count;
|
||||
bool sync;
|
||||
struct nl4_server *cp_src;
|
||||
};
|
||||
|
||||
struct nfs42_write_res {
|
||||
@ -1463,6 +1464,22 @@ struct nfs42_offload_status_res {
|
||||
int osr_status;
|
||||
};
|
||||
|
||||
struct nfs42_copy_notify_args {
|
||||
struct nfs4_sequence_args cna_seq_args;
|
||||
|
||||
struct nfs_fh *cna_src_fh;
|
||||
nfs4_stateid cna_src_stateid;
|
||||
struct nl4_server cna_dst;
|
||||
};
|
||||
|
||||
struct nfs42_copy_notify_res {
|
||||
struct nfs4_sequence_res cnr_seq_res;
|
||||
|
||||
struct nfstime4 cnr_lease_time;
|
||||
nfs4_stateid cnr_stateid;
|
||||
struct nl4_server cnr_src;
|
||||
};
|
||||
|
||||
struct nfs42_seek_args {
|
||||
struct nfs4_sequence_args seq_args;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user