nfsd: add nfsd4_client_tracking_ops struct and a way to set it

Abstract out the mechanism that we use to track clients into a set of
client name tracking functions.

This gives us a mechanism to plug in a new set of client tracking
functions without disturbing the callers. It also gives us a way to
decide on what tracking scheme to use at runtime.

For now, this just looks like pointless abstraction, but later we'll
add a new alternate scheme for tracking clients on stable storage.

Note too that this patch anticipates the eventual containerization
of this code by passing in struct net pointers in places. No attempt
is made to containerize the legacy client tracker however.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
Jeff Layton
2012-03-21 16:42:43 -04:00
committed by J. Bruce Fields
부모 a52d726bbd
커밋 2a4317c554
3개의 변경된 파일156개의 추가작업 그리고 58개의 파일을 삭제

파일 보기

@@ -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)
@@ -117,7 +128,8 @@ out_no_tfm:
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;
@@ -264,7 +276,7 @@ out_unlock:
return status;
}
void
static void
nfsd4_remove_clid_dir(struct nfs4_client *clp)
{
const struct cred *original_cred;
@@ -291,7 +303,6 @@ out:
if (status)
printk("NFSD: Failed to remove expired client state directory"
" %.*s\n", HEXDIR_LEN, clp->cl_recdir);
return;
}
static int
@@ -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)
@@ -342,7 +354,7 @@ load_recdir(struct dentry *parent, struct dentry *child)
return 0;
}
int
static int
nfsd4_recdir_load(void) {
int status;
@@ -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;
@@ -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)
@@ -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.
*/
@@ -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);
}