Commit 3a073369 authored by Stanislav Kinsbursky's avatar Stanislav Kinsbursky Committed by J. Bruce Fields

nfsd: recovery - make rec_file per net

Opening and closing of this file is done in client tracking init and exit
operations.
Client tracking is done in network namespace context already. So let's make
this file opened and closed per network context - this will simlify it's
management.
Signed-off-by: default avatarStanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent f252bc68
...@@ -84,6 +84,8 @@ struct nfsd_net { ...@@ -84,6 +84,8 @@ struct nfsd_net {
/* client_lock protects the client lru list and session hash table */ /* client_lock protects the client lru list and session hash table */
spinlock_t client_lock; spinlock_t client_lock;
struct file *rec_file;
}; };
extern int nfsd_net_id; extern int nfsd_net_id;
......
...@@ -62,7 +62,6 @@ struct nfsd4_client_tracking_ops { ...@@ -62,7 +62,6 @@ struct nfsd4_client_tracking_ops {
}; };
/* Globals */ /* Globals */
static struct file *rec_file;
static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
static struct nfsd4_client_tracking_ops *client_tracking_ops; static struct nfsd4_client_tracking_ops *client_tracking_ops;
static bool in_grace; static bool in_grace;
...@@ -182,7 +181,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) ...@@ -182,7 +181,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
return; return;
if (!rec_file) if (!nn->rec_file)
return; return;
status = nfs4_make_rec_clidname(dname, &clp->cl_name); status = nfs4_make_rec_clidname(dname, &clp->cl_name);
...@@ -193,11 +192,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) ...@@ -193,11 +192,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
if (status < 0) if (status < 0)
return; return;
status = mnt_want_write_file(rec_file); status = mnt_want_write_file(nn->rec_file);
if (status) if (status)
return; return;
dir = rec_file->f_path.dentry; dir = nn->rec_file->f_path.dentry;
/* lock the parent */ /* lock the parent */
mutex_lock(&dir->d_inode->i_mutex); mutex_lock(&dir->d_inode->i_mutex);
...@@ -227,14 +226,14 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) ...@@ -227,14 +226,14 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
if (crp) if (crp)
crp->cr_clp = clp; crp->cr_clp = clp;
} }
vfs_fsync(rec_file, 0); vfs_fsync(nn->rec_file, 0);
} else { } else {
printk(KERN_ERR "NFSD: failed to write recovery record" printk(KERN_ERR "NFSD: failed to write recovery record"
" (err %d); please check that %s exists" " (err %d); please check that %s exists"
" and is writeable", status, " and is writeable", status,
user_recovery_dirname); user_recovery_dirname);
} }
mnt_drop_write_file(rec_file); mnt_drop_write_file(nn->rec_file);
nfs4_reset_creds(original_cred); nfs4_reset_creds(original_cred);
} }
...@@ -267,7 +266,7 @@ static int ...@@ -267,7 +266,7 @@ static int
nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
{ {
const struct cred *original_cred; const struct cred *original_cred;
struct dentry *dir = rec_file->f_path.dentry; struct dentry *dir = nn->rec_file->f_path.dentry;
LIST_HEAD(names); LIST_HEAD(names);
int status; int status;
...@@ -275,13 +274,13 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) ...@@ -275,13 +274,13 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
if (status < 0) if (status < 0)
return status; return status;
status = vfs_llseek(rec_file, 0, SEEK_SET); status = vfs_llseek(nn->rec_file, 0, SEEK_SET);
if (status < 0) { if (status < 0) {
nfs4_reset_creds(original_cred); nfs4_reset_creds(original_cred);
return status; return status;
} }
status = vfs_readdir(rec_file, nfsd4_build_namelist, &names); status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names);
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
while (!list_empty(&names)) { while (!list_empty(&names)) {
struct name_list *entry; struct name_list *entry;
...@@ -305,14 +304,14 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) ...@@ -305,14 +304,14 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
} }
static int static int
nfsd4_unlink_clid_dir(char *name, int namlen) nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
{ {
struct dentry *dir, *dentry; struct dentry *dir, *dentry;
int status; int status;
dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
dir = rec_file->f_path.dentry; dir = nn->rec_file->f_path.dentry;
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_one_len(name, dir, namlen); dentry = lookup_one_len(name, dir, namlen);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
...@@ -339,14 +338,14 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) ...@@ -339,14 +338,14 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
int status; int status;
struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
return; return;
status = nfs4_make_rec_clidname(dname, &clp->cl_name); status = nfs4_make_rec_clidname(dname, &clp->cl_name);
if (status) if (status)
return legacy_recdir_name_error(status); return legacy_recdir_name_error(status);
status = mnt_want_write_file(rec_file); status = mnt_want_write_file(nn->rec_file);
if (status) if (status)
goto out; goto out;
clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
...@@ -355,10 +354,10 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) ...@@ -355,10 +354,10 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
if (status < 0) if (status < 0)
goto out_drop_write; goto out_drop_write;
status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1); status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn);
nfs4_reset_creds(original_cred); nfs4_reset_creds(original_cred);
if (status == 0) { if (status == 0) {
vfs_fsync(rec_file, 0); vfs_fsync(nn->rec_file, 0);
if (in_grace) { if (in_grace) {
/* remove reclaim record */ /* remove reclaim record */
crp = nfsd4_find_reclaim_client(dname, nn); crp = nfsd4_find_reclaim_client(dname, nn);
...@@ -367,7 +366,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) ...@@ -367,7 +366,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
} }
} }
out_drop_write: out_drop_write:
mnt_drop_write_file(rec_file); mnt_drop_write_file(nn->rec_file);
out: out:
if (status) if (status)
printk("NFSD: Failed to remove expired client state directory" printk("NFSD: Failed to remove expired client state directory"
...@@ -396,20 +395,20 @@ nfsd4_recdir_purge_old(struct nfsd_net *nn, time_t boot_time) ...@@ -396,20 +395,20 @@ nfsd4_recdir_purge_old(struct nfsd_net *nn, time_t boot_time)
int status; int status;
in_grace = false; in_grace = false;
if (!rec_file) if (!nn->rec_file)
return; return;
status = mnt_want_write_file(rec_file); status = mnt_want_write_file(nn->rec_file);
if (status) if (status)
goto out; goto out;
status = nfsd4_list_rec_dir(purge_old, nn); status = nfsd4_list_rec_dir(purge_old, nn);
if (status == 0) if (status == 0)
vfs_fsync(rec_file, 0); vfs_fsync(nn->rec_file, 0);
mnt_drop_write_file(rec_file); mnt_drop_write_file(nn->rec_file);
out: out:
nfs4_release_reclaim(nn); nfs4_release_reclaim(nn);
if (status) if (status)
printk("nfsd4: failed to purge old clients from recovery" printk("nfsd4: failed to purge old clients from recovery"
" directory %s\n", rec_file->f_path.dentry->d_name.name); " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
} }
static int static int
...@@ -430,13 +429,13 @@ nfsd4_recdir_load(struct net *net) { ...@@ -430,13 +429,13 @@ nfsd4_recdir_load(struct net *net) {
int status; int status;
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
if (!rec_file) if (!nn->rec_file)
return 0; return 0;
status = nfsd4_list_rec_dir(load_recdir, nn); status = nfsd4_list_rec_dir(load_recdir, nn);
if (status) if (status)
printk("nfsd4: failed loading clients from recovery" printk("nfsd4: failed loading clients from recovery"
" directory %s\n", rec_file->f_path.dentry->d_name.name); " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
return status; return status;
} }
...@@ -445,15 +444,16 @@ nfsd4_recdir_load(struct net *net) { ...@@ -445,15 +444,16 @@ nfsd4_recdir_load(struct net *net) {
*/ */
static int static int
nfsd4_init_recdir(void) nfsd4_init_recdir(struct net *net)
{ {
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
const struct cred *original_cred; const struct cred *original_cred;
int status; int status;
printk("NFSD: Using %s as the NFSv4 state recovery directory\n", printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
user_recovery_dirname); user_recovery_dirname);
BUG_ON(rec_file); BUG_ON(nn->rec_file);
status = nfs4_save_creds(&original_cred); status = nfs4_save_creds(&original_cred);
if (status < 0) { if (status < 0) {
...@@ -463,12 +463,12 @@ nfsd4_init_recdir(void) ...@@ -463,12 +463,12 @@ nfsd4_init_recdir(void)
return status; return status;
} }
rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
if (IS_ERR(rec_file)) { if (IS_ERR(nn->rec_file)) {
printk("NFSD: unable to find recovery directory %s\n", printk("NFSD: unable to find recovery directory %s\n",
user_recovery_dirname); user_recovery_dirname);
status = PTR_ERR(rec_file); status = PTR_ERR(nn->rec_file);
rec_file = NULL; nn->rec_file = NULL;
} }
nfs4_reset_creds(original_cred); nfs4_reset_creds(original_cred);
...@@ -509,7 +509,7 @@ nfsd4_load_reboot_recovery_data(struct net *net) ...@@ -509,7 +509,7 @@ nfsd4_load_reboot_recovery_data(struct net *net)
{ {
int status; int status;
status = nfsd4_init_recdir(); status = nfsd4_init_recdir(net);
if (!status) if (!status)
status = nfsd4_recdir_load(net); status = nfsd4_recdir_load(net);
if (status) if (status)
...@@ -544,12 +544,12 @@ nfsd4_legacy_tracking_init(struct net *net) ...@@ -544,12 +544,12 @@ nfsd4_legacy_tracking_init(struct net *net)
} }
static void static void
nfsd4_shutdown_recdir(void) nfsd4_shutdown_recdir(struct nfsd_net *nn)
{ {
if (!rec_file) if (!nn->rec_file)
return; return;
fput(rec_file); fput(nn->rec_file);
rec_file = NULL; nn->rec_file = NULL;
} }
static void static void
...@@ -558,7 +558,7 @@ nfsd4_legacy_tracking_exit(struct net *net) ...@@ -558,7 +558,7 @@ nfsd4_legacy_tracking_exit(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
nfs4_release_reclaim(nn); nfs4_release_reclaim(nn);
nfsd4_shutdown_recdir(); nfsd4_shutdown_recdir(nn);
nfs4_legacy_state_shutdown(net); nfs4_legacy_state_shutdown(net);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment