Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 192362
b: refs/heads/master
c: b5a1a81
h: refs/heads/master
v: v3
  • Loading branch information
J. Bruce Fields committed Apr 22, 2010
1 parent ac16cb4 commit 4284d66
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 21 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3c4ab2aaa90826060b1e8d4036f9bb8325f8759e
refs/heads/master: b5a1a81e5c25fb6bb3fdc1812ba69ff6ab638fcf
54 changes: 52 additions & 2 deletions trunk/fs/nfsd/nfs4callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*/

#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc_xprt.h>
#include "nfsd.h"
#include "state.h"

Expand Down Expand Up @@ -692,11 +693,41 @@ static const struct rpc_call_ops nfsd4_cb_recall_ops = {
.rpc_release = nfsd4_cb_recall_release,
};

static struct workqueue_struct *callback_wq;

int nfsd4_create_callback_queue(void)
{
callback_wq = create_singlethread_workqueue("nfsd4_callbacks");
if (!callback_wq)
return -ENOMEM;
return 0;
}

void nfsd4_destroy_callback_queue(void)
{
destroy_workqueue(callback_wq);
}

void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt
*new)
{
struct rpc_clnt *old = clp->cl_cb_conn.cb_client;

clp->cl_cb_conn.cb_client = new;
/*
* After this, any work that saw the old value of cb_client will
* be gone:
*/
flush_workqueue(callback_wq);
/* So we can safely shut it down: */
if (old)
rpc_shutdown_client(old);
}

/*
* called with dp->dl_count inc'ed.
*/
void
nfsd4_cb_recall(struct nfs4_delegation *dp)
static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
{
struct nfs4_client *clp = dp->dl_client;
struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
Expand All @@ -707,6 +738,9 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
};
int status;

if (clnt == NULL)
return; /* Client is shutting down; give up. */

args->args_op = dp;
msg.rpc_argp = args;
dp->dl_retries = 1;
Expand All @@ -717,3 +751,19 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
nfs4_put_delegation(dp);
}
}

void nfsd4_do_callback_rpc(struct work_struct *w)
{
/* XXX: for now, just send off delegation recall. */
/* In future, generalize to handle any sort of callback. */
struct nfsd4_callback *c = container_of(w, struct nfsd4_callback, cb_work);
struct nfs4_delegation *dp = container_of(c, struct nfs4_delegation, dl_recall);

_nfsd4_cb_recall(dp);
}


void nfsd4_cb_recall(struct nfs4_delegation *dp)
{
queue_work(callback_wq, &dp->dl_recall.cb_work);
}
34 changes: 16 additions & 18 deletions trunk/fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
atomic_set(&dp->dl_count, 1);
list_add(&dp->dl_perfile, &fp->fi_delegations);
list_add(&dp->dl_perclnt, &clp->cl_delegations);
INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc);
return dp;
}

Expand Down Expand Up @@ -679,21 +680,6 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
return clp;
}

static void
shutdown_callback_client(struct nfs4_client *clp)
{
struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;

if (clnt) {
/*
* Callback threads take a reference on the client, so there
* should be no outstanding callbacks at this point.
*/
clp->cl_cb_conn.cb_client = NULL;
rpc_shutdown_client(clnt);
}
}

static inline void
free_client(struct nfs4_client *clp)
{
Expand Down Expand Up @@ -746,7 +732,7 @@ expire_client(struct nfs4_client *clp)
se_perclnt);
release_session(ses);
}
shutdown_callback_client(clp);
nfsd4_set_callback_client(clp, NULL);
if (clp->cl_cb_xprt)
svc_xprt_put(clp->cl_cb_xprt);
put_nfs4_client(clp);
Expand Down Expand Up @@ -1392,7 +1378,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
spin_unlock(&sessionid_lock);

/* wait for callbacks */
shutdown_callback_client(ses->se_client);
nfsd4_set_callback_client(ses->se_client, NULL);
nfsd4_put_session(ses);
status = nfs_ok;
out:
Expand Down Expand Up @@ -4004,16 +3990,27 @@ set_max_delegations(void)
static int
__nfs4_state_start(void)
{
int ret;

boot_time = get_seconds();
locks_start_grace(&nfsd4_manager);
printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
nfsd4_grace);
ret = set_callback_cred();
if (ret)
return -ENOMEM;
laundry_wq = create_singlethread_workqueue("nfsd4");
if (laundry_wq == NULL)
return -ENOMEM;
ret = nfsd4_create_callback_queue();
if (ret)
goto out_free_laundry;
queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ);
set_max_delegations();
return set_callback_cred();
return 0;
out_free_laundry:
destroy_workqueue(laundry_wq);
return ret;
}

int
Expand Down Expand Up @@ -4075,6 +4072,7 @@ nfs4_state_shutdown(void)
nfs4_lock_state();
nfs4_release_reclaim();
__nfs4_state_shutdown();
nfsd4_destroy_callback_queue();
nfs4_unlock_state();
}

Expand Down
5 changes: 5 additions & 0 deletions trunk/fs/nfsd/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct nfs4_rpc_args {

struct nfsd4_callback {
struct nfs4_rpc_args cb_args;
struct work_struct cb_work;
};

struct nfs4_delegation {
Expand Down Expand Up @@ -391,7 +392,11 @@ extern void put_nfs4_client(struct nfs4_client *clp);
extern void nfs4_free_stateowner(struct kref *kref);
extern int set_callback_cred(void);
extern void nfsd4_probe_callback(struct nfs4_client *clp);
extern void nfsd4_do_callback_rpc(struct work_struct *);
extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
extern int nfsd4_create_callback_queue(void);
extern void nfsd4_destroy_callback_queue(void);
extern void nfsd4_set_callback_client(struct nfs4_client *, struct rpc_clnt *);
extern void nfs4_put_delegation(struct nfs4_delegation *dp);
extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
extern void nfsd4_init_recdir(char *recdir_name);
Expand Down

0 comments on commit 4284d66

Please sign in to comment.