NFSD introduce async copy feature
Upon receiving a request for async copy, create a new kthread. If we get asynchronous request, make sure to copy the needed arguments/state from the stack before starting the copy. Then start the thread and reply back to the client indicating copy is asynchronous. nfsd_copy_file_range() will copy in a loop over the total number of bytes is needed to copy. In case a failure happens in the middle, we ignore the error and return how much we copied so far. Once done creating a workitem for the callback workqueue and send CB_OFFLOAD with the results. The lifetime of the copy stateid is bound to the vfs copy. This way we don't need to keep the nfsd_net structure for the callback. We could keep it around longer so that an OFFLOAD_STATUS that came late would still get results, but clients should be able to deal without that. We handle OFFLOAD_CANCEL by sending a signal to the copy thread and calling kthread_stop. A client should cancel any ongoing copies before calling DESTROY_CLIENT; if not, we return a CLIENT_BUSY error. If the client is destroyed for some other reason (lease expiration, or server shutdown), we must clean up any ongoing copies ourselves. Signed-off-by: Olga Kornievskaia <kolga@netapp.com> [colin.king@canonical.com: fix leak in error case] [bfields@fieldses.org: remove signalling, merge patches] Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:

committed by
J. Bruce Fields

parent
885e2bf3ea
commit
e0639dc580
@@ -355,6 +355,8 @@ struct nfs4_client {
|
||||
struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */
|
||||
/* wait here for slots */
|
||||
struct net *net;
|
||||
struct list_head async_copies; /* list of async copies */
|
||||
spinlock_t async_lock; /* lock for async copies */
|
||||
};
|
||||
|
||||
/* struct nfs4_client_reset
|
||||
@@ -600,6 +602,7 @@ struct nfsd4_blocked_lock {
|
||||
|
||||
struct nfsd4_compound_state;
|
||||
struct nfsd_net;
|
||||
struct nfsd4_copy;
|
||||
|
||||
extern __be32 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
|
||||
struct nfsd4_compound_state *cstate, struct svc_fh *fhp,
|
||||
@@ -609,6 +612,8 @@ __be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
|
||||
struct nfs4_stid **s, struct nfsd_net *nn);
|
||||
struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
|
||||
void (*sc_free)(struct nfs4_stid *));
|
||||
int nfs4_init_cp_state(struct nfsd_net *nn, struct nfsd4_copy *copy);
|
||||
void nfs4_free_cp_state(struct nfsd4_copy *copy);
|
||||
void nfs4_unhash_stid(struct nfs4_stid *s);
|
||||
void nfs4_put_stid(struct nfs4_stid *s);
|
||||
void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid);
|
||||
@@ -627,6 +632,7 @@ extern void nfsd4_run_cb(struct nfsd4_callback *cb);
|
||||
extern int nfsd4_create_callback_queue(void);
|
||||
extern void nfsd4_destroy_callback_queue(void);
|
||||
extern void nfsd4_shutdown_callback(struct nfs4_client *);
|
||||
extern void nfsd4_shutdown_copy(struct nfs4_client *clp);
|
||||
extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp);
|
||||
extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
|
||||
struct nfsd_net *nn);
|
||||
@@ -634,6 +640,9 @@ extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
|
||||
|
||||
struct nfs4_file *find_file(struct knfsd_fh *fh);
|
||||
void put_nfs4_file(struct nfs4_file *fi);
|
||||
extern void nfs4_put_copy(struct nfsd4_copy *copy);
|
||||
extern struct nfsd4_copy *
|
||||
find_async_copy(struct nfs4_client *clp, stateid_t *staetid);
|
||||
static inline void get_nfs4_file(struct nfs4_file *fi)
|
||||
{
|
||||
refcount_inc(&fi->fi_ref);
|
||||
|
Reference in New Issue
Block a user