NFSD add COPY_NOTIFY operation
Introducing the COPY_NOTIFY operation. Create a new unique stateid that will keep track of the copy state and the upcoming READs that will use that stateid. Each associated parent stateid has a list of copy notify stateids. A copy notify structure makes a copy of the parent stateid and a clientid and will use it to look up the parent stateid during the READ request (suggested by Trond Myklebust <trond.myklebust@hammerspace.com>). At nfs4_put_stid() time, we walk the list of the associated copy notify stateids and delete them. Laundromat thread will traverse globally stored copy notify stateid in idr and notice if any haven't been referenced in the lease period, if so, it'll remove them. Return single netaddr to advertise to the copy. Suggested-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Olga Kornievskaia <kolga@netapp.com> Signed-off-by: Andy Adamson <andros@netapp.com>
This commit is contained in:

committed by
J. Bruce Fields

parent
51911868fc
commit
624322f1ad
@@ -37,6 +37,7 @@
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sunrpc/addr.h>
|
||||
|
||||
#include "idmap.h"
|
||||
#include "cache.h"
|
||||
@@ -776,7 +777,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
/* check stateid */
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
&read->rd_stateid, RD_STATE,
|
||||
&read->rd_nf);
|
||||
&read->rd_nf, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
|
||||
goto out;
|
||||
@@ -948,7 +949,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate,
|
||||
&cstate->current_fh, &setattr->sa_stateid,
|
||||
WR_STATE, NULL);
|
||||
WR_STATE, NULL, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
|
||||
return status;
|
||||
@@ -999,7 +1000,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
trace_nfsd_write_start(rqstp, &cstate->current_fh,
|
||||
write->wr_offset, cnt);
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
stateid, WR_STATE, &nf);
|
||||
stateid, WR_STATE, &nf, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
|
||||
return status;
|
||||
@@ -1034,14 +1035,14 @@ nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
return nfserr_nofilehandle;
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
|
||||
src_stateid, RD_STATE, src);
|
||||
src_stateid, RD_STATE, src, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: %s: couldn't process src stateid!\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
dst_stateid, WR_STATE, dst);
|
||||
dst_stateid, WR_STATE, dst, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: %s: couldn't process dst stateid!\n", __func__);
|
||||
goto out_put_src;
|
||||
@@ -1221,7 +1222,7 @@ static void dup_copy_fields(struct nfsd4_copy *src, struct nfsd4_copy *dst)
|
||||
|
||||
static void cleanup_async_copy(struct nfsd4_copy *copy)
|
||||
{
|
||||
nfs4_free_cp_state(copy);
|
||||
nfs4_free_copy_state(copy);
|
||||
nfsd_file_put(copy->nf_dst);
|
||||
nfsd_file_put(copy->nf_src);
|
||||
spin_lock(©->cp_clp->async_lock);
|
||||
@@ -1275,7 +1276,7 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
|
||||
if (!async_copy)
|
||||
goto out;
|
||||
if (!nfs4_init_cp_state(nn, copy)) {
|
||||
if (!nfs4_init_copy_state(nn, copy)) {
|
||||
kfree(async_copy);
|
||||
goto out;
|
||||
}
|
||||
@@ -1343,7 +1344,44 @@ static __be32
|
||||
nfsd4_copy_notify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
union nfsd4_op_u *u)
|
||||
{
|
||||
return nfserr_notsupp;
|
||||
struct nfsd4_copy_notify *cn = &u->copy_notify;
|
||||
__be32 status;
|
||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||
struct nfs4_stid *stid;
|
||||
struct nfs4_cpntf_state *cps;
|
||||
struct nfs4_client *clp = cstate->clp;
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
&cn->cpn_src_stateid, RD_STATE, NULL,
|
||||
&stid);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
cn->cpn_sec = nn->nfsd4_lease;
|
||||
cn->cpn_nsec = 0;
|
||||
|
||||
status = nfserrno(-ENOMEM);
|
||||
cps = nfs4_alloc_init_cpntf_state(nn, stid);
|
||||
if (!cps)
|
||||
goto out;
|
||||
memcpy(&cn->cpn_cnr_stateid, &cps->cp_stateid.stid, sizeof(stateid_t));
|
||||
memcpy(&cps->cp_p_stateid, &stid->sc_stateid, sizeof(stateid_t));
|
||||
memcpy(&cps->cp_p_clid, &clp->cl_clientid, sizeof(clientid_t));
|
||||
|
||||
/* For now, only return one server address in cpn_src, the
|
||||
* address used by the client to connect to this server.
|
||||
*/
|
||||
cn->cpn_src.nl4_type = NL4_NETADDR;
|
||||
status = nfsd4_set_netaddr((struct sockaddr *)&rqstp->rq_daddr,
|
||||
&cn->cpn_src.u.nl4_addr);
|
||||
WARN_ON_ONCE(status);
|
||||
if (status) {
|
||||
nfs4_put_cpntf_state(nn, cps);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
nfs4_put_stid(stid);
|
||||
return status;
|
||||
}
|
||||
|
||||
static __be32
|
||||
@@ -1355,7 +1393,7 @@ nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
&fallocate->falloc_stateid,
|
||||
WR_STATE, &nf);
|
||||
WR_STATE, &nf, NULL);
|
||||
if (status != nfs_ok) {
|
||||
dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
|
||||
return status;
|
||||
@@ -1414,7 +1452,7 @@ nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
|
||||
&seek->seek_stateid,
|
||||
RD_STATE, &nf);
|
||||
RD_STATE, &nf, NULL);
|
||||
if (status) {
|
||||
dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n");
|
||||
return status;
|
||||
|
Reference in New Issue
Block a user