mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
nfsd4: add a client info file
Add a new nfsd/clients/#/info file with some basic information about each NFSv4 client. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
116
fs/nfsd/nfsctl.c
116
fs/nfsd/nfsctl.c
@@ -1208,14 +1208,116 @@ out_err:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* on success, returns positive number unique to that client. */
|
||||
struct dentry *nfsd_client_mkdir(struct nfsd_net *nn, struct nfsdfs_client *ncl, u32 id)
|
||||
static void clear_ncl(struct inode *inode)
|
||||
{
|
||||
struct nfsdfs_client *ncl = inode->i_private;
|
||||
|
||||
inode->i_private = NULL;
|
||||
synchronize_rcu();
|
||||
kref_put(&ncl->cl_ref, ncl->cl_release);
|
||||
}
|
||||
|
||||
|
||||
struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode)
|
||||
{
|
||||
struct nfsdfs_client *nc = inode->i_private;
|
||||
|
||||
if (nc)
|
||||
kref_get(&nc->cl_ref);
|
||||
return nc;
|
||||
}
|
||||
|
||||
struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
|
||||
{
|
||||
struct nfsdfs_client *nc;
|
||||
|
||||
rcu_read_lock();
|
||||
nc = __get_nfsdfs_client(inode);
|
||||
rcu_read_unlock();
|
||||
return nc;
|
||||
}
|
||||
/* from __rpc_unlink */
|
||||
static void nfsdfs_remove_file(struct inode *dir, struct dentry *dentry)
|
||||
{
|
||||
int ret;
|
||||
|
||||
clear_ncl(d_inode(dentry));
|
||||
dget(dentry);
|
||||
ret = simple_unlink(dir, dentry);
|
||||
d_delete(dentry);
|
||||
dput(dentry);
|
||||
WARN_ON_ONCE(ret);
|
||||
}
|
||||
|
||||
static void nfsdfs_remove_files(struct dentry *root)
|
||||
{
|
||||
struct dentry *dentry, *tmp;
|
||||
|
||||
list_for_each_entry_safe(dentry, tmp, &root->d_subdirs, d_child) {
|
||||
if (!simple_positive(dentry)) {
|
||||
WARN_ON_ONCE(1); /* I think this can't happen? */
|
||||
continue;
|
||||
}
|
||||
nfsdfs_remove_file(d_inode(root), dentry);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: cut'n'paste from simple_fill_super; figure out if we could share
|
||||
* code instead. */
|
||||
static int nfsdfs_create_files(struct dentry *root,
|
||||
const struct tree_descr *files)
|
||||
{
|
||||
struct inode *dir = d_inode(root);
|
||||
struct inode *inode;
|
||||
struct dentry *dentry;
|
||||
int i;
|
||||
|
||||
inode_lock(dir);
|
||||
for (i = 0; files->name && files->name[0]; i++, files++) {
|
||||
if (!files->name)
|
||||
continue;
|
||||
dentry = d_alloc_name(root, files->name);
|
||||
if (!dentry)
|
||||
goto out;
|
||||
inode = nfsd_get_inode(d_inode(root)->i_sb,
|
||||
S_IFREG | files->mode);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
goto out;
|
||||
}
|
||||
inode->i_fop = files->ops;
|
||||
inode->i_private = __get_nfsdfs_client(dir);
|
||||
d_add(dentry, inode);
|
||||
fsnotify_create(dir, dentry);
|
||||
}
|
||||
inode_unlock(dir);
|
||||
return 0;
|
||||
out:
|
||||
nfsdfs_remove_files(root);
|
||||
inode_unlock(dir);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* on success, returns positive number unique to that client. */
|
||||
struct dentry *nfsd_client_mkdir(struct nfsd_net *nn,
|
||||
struct nfsdfs_client *ncl, u32 id,
|
||||
const struct tree_descr *files)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
char name[11];
|
||||
int ret;
|
||||
|
||||
sprintf(name, "%u", id);
|
||||
|
||||
return nfsd_mkdir(nn->nfsd_client_dir, ncl, name);
|
||||
dentry = nfsd_mkdir(nn->nfsd_client_dir, ncl, name);
|
||||
if (IS_ERR(dentry)) /* XXX: tossing errors? */
|
||||
return NULL;
|
||||
ret = nfsdfs_create_files(dentry, files);
|
||||
if (ret) {
|
||||
nfsd_client_rmdir(dentry);
|
||||
return NULL;
|
||||
}
|
||||
return dentry;
|
||||
}
|
||||
|
||||
/* Taken from __rpc_rmdir: */
|
||||
@@ -1223,16 +1325,16 @@ void nfsd_client_rmdir(struct dentry *dentry)
|
||||
{
|
||||
struct inode *dir = d_inode(dentry->d_parent);
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct nfsdfs_client *ncl = inode->i_private;
|
||||
int ret;
|
||||
|
||||
inode->i_private = NULL;
|
||||
synchronize_rcu();
|
||||
kref_put(&ncl->cl_ref, ncl->cl_release);
|
||||
inode_lock(dir);
|
||||
nfsdfs_remove_files(dentry);
|
||||
clear_ncl(inode);
|
||||
dget(dentry);
|
||||
ret = simple_rmdir(dir, dentry);
|
||||
WARN_ON_ONCE(ret);
|
||||
d_delete(dentry);
|
||||
inode_unlock(dir);
|
||||
}
|
||||
|
||||
static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
|
||||
|
Reference in New Issue
Block a user