Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 297464
b: refs/heads/master
c: 2a4317c
h: refs/heads/master
v: v3
  • Loading branch information
Jeff Layton authored and J. Bruce Fields committed Mar 26, 2012
1 parent 30d12f3 commit 708e0b7
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 59 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: a52d726bbd928164609e6abc4dc967e819dbf09c
refs/heads/master: 2a4317c55438d8589a015d42912454ede12031f0
136 changes: 126 additions & 10 deletions trunk/fs/nfsd/nfs4recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,20 @@

#define NFSDDBG_FACILITY NFSDDBG_PROC

/* Declarations */
struct nfsd4_client_tracking_ops {
int (*init)(struct net *);
void (*exit)(struct net *);
void (*create)(struct nfs4_client *);
void (*remove)(struct nfs4_client *);
int (*check)(struct nfs4_client *);
void (*grace_done)(struct net *, time_t);
};

/* Globals */
static struct file *rec_file;
static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
static struct nfsd4_client_tracking_ops *client_tracking_ops;

static int
nfs4_save_creds(const struct cred **original_creds)
Expand Down Expand Up @@ -117,7 +128,8 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
return status;
}

void nfsd4_create_clid_dir(struct nfs4_client *clp)
static void
nfsd4_create_clid_dir(struct nfs4_client *clp)
{
const struct cred *original_cred;
char *dname = clp->cl_recdir;
Expand Down Expand Up @@ -264,7 +276,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
return status;
}

void
static void
nfsd4_remove_clid_dir(struct nfs4_client *clp)
{
const struct cred *original_cred;
Expand All @@ -291,7 +303,6 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
if (status)
printk("NFSD: Failed to remove expired client state directory"
" %.*s\n", HEXDIR_LEN, clp->cl_recdir);
return;
}

static int
Expand All @@ -310,8 +321,9 @@ purge_old(struct dentry *parent, struct dentry *child)
return 0;
}

void
nfsd4_recdir_purge_old(void) {
static void
nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
{
int status;

if (!rec_file)
Expand Down Expand Up @@ -342,7 +354,7 @@ load_recdir(struct dentry *parent, struct dentry *child)
return 0;
}

int
static int
nfsd4_recdir_load(void) {
int status;

Expand All @@ -360,8 +372,8 @@ nfsd4_recdir_load(void) {
* Hold reference to the recovery directory.
*/

void
nfsd4_init_recdir()
static int
nfsd4_init_recdir(void)
{
const struct cred *original_cred;
int status;
Expand All @@ -376,20 +388,37 @@ nfsd4_init_recdir()
printk("NFSD: Unable to change credentials to find recovery"
" directory: error %d\n",
status);
return;
return status;
}

rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
if (IS_ERR(rec_file)) {
printk("NFSD: unable to find recovery directory %s\n",
user_recovery_dirname);
status = PTR_ERR(rec_file);
rec_file = NULL;
}

nfs4_reset_creds(original_cred);
return status;
}

void
static int
nfsd4_load_reboot_recovery_data(struct net *net)
{
int status;

nfs4_lock_state();
status = nfsd4_init_recdir();
if (!status)
status = nfsd4_recdir_load();
nfs4_unlock_state();
if (status)
printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
return status;
}

static void
nfsd4_shutdown_recdir(void)
{
if (!rec_file)
Expand All @@ -398,6 +427,13 @@ nfsd4_shutdown_recdir(void)
rec_file = NULL;
}

static void
nfsd4_legacy_tracking_exit(struct net *net)
{
nfs4_release_reclaim();
nfsd4_shutdown_recdir();
}

/*
* Change the NFSv4 recovery directory to recdir.
*/
Expand All @@ -424,3 +460,83 @@ nfs4_recoverydir(void)
{
return user_recovery_dirname;
}

static int
nfsd4_check_legacy_client(struct nfs4_client *clp)
{
/* did we already find that this client is stable? */
if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
return 0;

/* look for it in the reclaim hashtable otherwise */
if (nfsd4_find_reclaim_client(clp)) {
set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
return 0;
}

return -ENOENT;
}

static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
.init = nfsd4_load_reboot_recovery_data,
.exit = nfsd4_legacy_tracking_exit,
.create = nfsd4_create_clid_dir,
.remove = nfsd4_remove_clid_dir,
.check = nfsd4_check_legacy_client,
.grace_done = nfsd4_recdir_purge_old,
};

int
nfsd4_client_tracking_init(struct net *net)
{
int status;

client_tracking_ops = &nfsd4_legacy_tracking_ops;

status = client_tracking_ops->init(net);
if (status) {
printk(KERN_WARNING "NFSD: Unable to initialize client "
"recovery tracking! (%d)\n", status);
client_tracking_ops = NULL;
}
return status;
}

void
nfsd4_client_tracking_exit(struct net *net)
{
if (client_tracking_ops) {
client_tracking_ops->exit(net);
client_tracking_ops = NULL;
}
}

void
nfsd4_client_record_create(struct nfs4_client *clp)
{
if (client_tracking_ops)
client_tracking_ops->create(clp);
}

void
nfsd4_client_record_remove(struct nfs4_client *clp)
{
if (client_tracking_ops)
client_tracking_ops->remove(clp);
}

int
nfsd4_client_record_check(struct nfs4_client *clp)
{
if (client_tracking_ops)
return client_tracking_ops->check(clp);

return -EOPNOTSUPP;
}

void
nfsd4_record_grace_done(struct net *net, time_t boot_time)
{
if (client_tracking_ops)
client_tracking_ops->grace_done(net, boot_time);
}
63 changes: 21 additions & 42 deletions trunk/fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -2085,7 +2085,7 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
goto out;

status = nfs_ok;
nfsd4_create_clid_dir(cstate->session->se_client);
nfsd4_client_record_create(cstate->session->se_client);
out:
nfs4_unlock_state();
return status;
Expand Down Expand Up @@ -2280,7 +2280,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
conf = find_confirmed_client_by_str(unconf->cl_recdir,
hash);
if (conf) {
nfsd4_remove_clid_dir(conf);
nfsd4_client_record_remove(conf);
expire_client(conf);
}
move_to_confirmed(unconf);
Expand Down Expand Up @@ -3159,7 +3159,7 @@ static void
nfsd4_end_grace(void)
{
dprintk("NFSD: end of grace period\n");
nfsd4_recdir_purge_old();
nfsd4_record_grace_done(&init_net, boot_time);
locks_end_grace(&nfsd4_manager);
/*
* Now that every NFSv4 client has had the chance to recover and
Expand Down Expand Up @@ -3208,7 +3208,7 @@ nfs4_laundromat(void)
clp = list_entry(pos, struct nfs4_client, cl_lru);
dprintk("NFSD: purging unused client (clientid %08x)\n",
clp->cl_clientid.cl_id);
nfsd4_remove_clid_dir(clp);
nfsd4_client_record_remove(clp);
expire_client(clp);
}
spin_lock(&recall_lock);
Expand Down Expand Up @@ -3639,7 +3639,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));

nfsd4_create_clid_dir(oo->oo_owner.so_client);
nfsd4_client_record_create(oo->oo_owner.so_client);
status = nfs_ok;
out:
if (!cstate->replay_owner)
Expand Down Expand Up @@ -4481,7 +4481,7 @@ nfs4_client_to_reclaim(const char *name)
return 1;
}

static void
void
nfs4_release_reclaim(void)
{
struct nfs4_client_reclaim *crp = NULL;
Expand All @@ -4501,7 +4501,7 @@ nfs4_release_reclaim(void)

/*
* called from OPEN, CLAIM_PREVIOUS with a new clientid. */
static struct nfs4_client_reclaim *
struct nfs4_client_reclaim *
nfsd4_find_reclaim_client(struct nfs4_client *clp)
{
unsigned int strhashval;
Expand All @@ -4521,22 +4521,6 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
return NULL;
}

static int
nfsd4_client_record_check(struct nfs4_client *clp)
{
/* did we already find that this client is stable? */
if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
return 0;

/* look for it in the reclaim hashtable otherwise */
if (nfsd4_find_reclaim_client(clp)) {
set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
return 0;
}

return -ENOENT;
}

/*
* Called from OPEN. Look for clientid in reclaim list.
*/
Expand All @@ -4562,7 +4546,7 @@ void nfsd_forget_clients(u64 num)

nfs4_lock_state();
list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
nfsd4_remove_clid_dir(clp);
nfsd4_client_record_remove(clp);
expire_client(clp);
if (++count == num)
break;
Expand Down Expand Up @@ -4697,19 +4681,6 @@ nfs4_state_init(void)
reclaim_str_hashtbl_size = 0;
}

static void
nfsd4_load_reboot_recovery_data(void)
{
int status;

nfs4_lock_state();
nfsd4_init_recdir();
status = nfsd4_recdir_load();
nfs4_unlock_state();
if (status)
printk("NFSD: Failure reading reboot recovery data\n");
}

/*
* Since the lifetime of a delegation isn't limited to that of an open, a
* client may quite reasonably hang on to a delegation as long as it has
Expand Down Expand Up @@ -4738,7 +4709,15 @@ nfs4_state_start(void)
{
int ret;

nfsd4_load_reboot_recovery_data();
/*
* FIXME: For now, we hang most of the pernet global stuff off of
* init_net until nfsd is fully containerized. Eventually, we'll
* need to pass a net pointer into this function, take a reference
* to that instead and then do most of the rest of this on a per-net
* basis.
*/
get_net(&init_net);
nfsd4_client_tracking_init(&init_net);
boot_time = get_seconds();
locks_start_grace(&nfsd4_manager);
printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
Expand All @@ -4762,8 +4741,8 @@ nfs4_state_start(void)
out_free_laundry:
destroy_workqueue(laundry_wq);
out_recovery:
nfs4_release_reclaim();
nfsd4_shutdown_recdir();
nfsd4_client_tracking_exit(&init_net);
put_net(&init_net);
return ret;
}

Expand Down Expand Up @@ -4797,7 +4776,8 @@ __nfs4_state_shutdown(void)
unhash_delegation(dp);
}

nfsd4_shutdown_recdir();
nfsd4_client_tracking_exit(&init_net);
put_net(&init_net);
}

void
Expand All @@ -4807,7 +4787,6 @@ nfs4_state_shutdown(void)
destroy_workqueue(laundry_wq);
locks_end_grace(&nfsd4_manager);
nfs4_lock_state();
nfs4_release_reclaim();
__nfs4_state_shutdown();
nfs4_unlock_state();
nfsd4_destroy_callback_queue();
Expand Down
Loading

0 comments on commit 708e0b7

Please sign in to comment.