Commit 259f529f authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] pin_fs/release_fs

	A couple of helpers - simple_pin_fs() and simple_release_fs().
My fault - that code should've been put into libfs.c from the very
beginning.  As it is, it got copied all over the place (binfmt_misc,
capifs, usbfs, usbdevfs, rpc_pipefs).
	Taken to libfs.c and cleaned up.
parent deddb7cb
......@@ -153,39 +153,17 @@ static struct file_system_type capifs_fs_type = {
.kill_sb = kill_anon_super,
};
static spinlock_t entries_lock = SPIN_LOCK_UNLOCKED;
static struct vfsmount *capifs_mnt;
static int entry_count = 0;
static int entry_count;
static struct vfsmount *grab_instance(void)
static int grab_instance(void)
{
struct vfsmount *mnt = NULL;
spin_lock(&entries_lock);
if (!capifs_mnt) {
spin_unlock(&entries_lock);
mnt = kern_mount(&capifs_fs_type);
if (IS_ERR(mnt))
return NULL;
spin_lock(&entries_lock);
if (!capifs_mnt)
capifs_mnt = mnt;
}
mntget(capifs_mnt);
entry_count++;
spin_unlock(&entries_lock);
mntput(mnt);
return capifs_mnt;
return simple_pin_fs("capifs", &capifs_mnt, &entry_count);
}
static void drop_instance(void)
{
struct vfsmount *mnt;
spin_lock(&entries_lock);
mnt = capifs_mnt;
if (!--entry_count)
capifs_mnt = NULL;
spin_unlock(&entries_lock);
mntput(mnt);
return simple_release_fs(&capifs_mnt, &entry_count);
}
static struct dentry *get_node(int type, int num)
......@@ -207,7 +185,7 @@ void capifs_new_ncci(char type, unsigned int num, dev_t device)
struct dentry *dentry;
struct inode *inode;
if (!grab_instance())
if (grab_instance() < 0)
return;
sb = capifs_mnt->mnt_sb;
inode = new_inode(sb);
......@@ -232,7 +210,7 @@ void capifs_new_ncci(char type, unsigned int num, dev_t device)
void capifs_free_ncci(char type, unsigned int num)
{
if (grab_instance()) {
if (grab_instance() == 0) {
struct dentry *dentry = get_node(type, num);
if (!IS_ERR(dentry)) {
struct inode *inode = dentry->d_inode;
......
......@@ -45,7 +45,6 @@ static struct file_operations default_file_operations;
static struct inode_operations usbfs_dir_inode_operations;
static struct vfsmount *usbdevfs_mount;
static struct vfsmount *usbfs_mount;
static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
static int usbdevfs_mount_count; /* = 0 */
static int usbfs_mount_count; /* = 0 */
......@@ -514,69 +513,20 @@ static struct file_system_type usb_fs_type = {
};
/* --------------------------------------------------------------------- */
static int get_mount (struct file_system_type *fs_type, struct vfsmount **mount, int *mount_count)
{
struct vfsmount *mnt;
spin_lock (&mount_lock);
if (*mount) {
mntget(*mount);
++(*mount_count);
spin_unlock (&mount_lock);
goto go_ahead;
}
spin_unlock (&mount_lock);
mnt = kern_mount (fs_type);
if (IS_ERR(mnt)) {
err ("could not mount the fs...erroring out!\n");
return -ENODEV;
}
spin_lock (&mount_lock);
if (!*mount) {
*mount = mnt;
++(*mount_count);
spin_unlock (&mount_lock);
goto go_ahead;
}
mntget(*mount);
++(*mount_count);
spin_unlock (&mount_lock);
mntput(mnt);
go_ahead:
dbg("mount_count = %d", *mount_count);
return 0;
}
static void put_mount (struct vfsmount **mount, int *mount_count)
{
struct vfsmount *mnt;
spin_lock (&mount_lock);
mnt = *mount;
--(*mount_count);
if (!(*mount_count))
*mount = NULL;
spin_unlock (&mount_lock);
mntput(mnt);
dbg("mount_count = %d", *mount_count);
}
static int create_special_files (void)
{
struct dentry *parent;
int retval = 0;
int retval;
/* create the devices special file */
retval = get_mount (&usbdevice_fs_type, &usbdevfs_mount, &usbdevfs_mount_count);
retval = simple_pin_fs("usbdevfs", &usbdevfs_mount, &usbdevfs_mount_count);
if (retval) {
err ("Unable to get usbdevfs mount");
goto exit;
}
retval = get_mount (&usb_fs_type, &usbfs_mount, &usbfs_mount_count);
retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count);
if (retval) {
err ("Unable to get usbfs mount");
goto error_clean_usbdevfs_mount;
......@@ -611,10 +561,10 @@ static int create_special_files (void)
devices_usbfs_dentry = NULL;
error_clean_mounts:
put_mount (&usbfs_mount, &usbfs_mount_count);
simple_release_fs(&usbfs_mount, &usbfs_mount_count);
error_clean_usbdevfs_mount:
put_mount (&usbdevfs_mount, &usbdevfs_mount_count);
simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count);
exit:
return retval;
......@@ -628,8 +578,8 @@ static void remove_special_files (void)
fs_remove_file (devices_usbfs_dentry);
devices_usbdevfs_dentry = NULL;
devices_usbfs_dentry = NULL;
put_mount (&usbdevfs_mount, &usbdevfs_mount_count);
put_mount (&usbfs_mount, &usbfs_mount_count);
simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count);
simple_release_fs(&usbfs_mount, &usbfs_mount_count);
}
void usbfs_update_special (void)
......
......@@ -53,7 +53,7 @@ typedef struct {
static rwlock_t entries_lock __attribute__((unused)) = RW_LOCK_UNLOCKED;
static struct vfsmount *bm_mnt;
static int entry_count = 0;
static int entry_count;
/*
* Check if we support the binfmt
......@@ -399,19 +399,7 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
static void bm_clear_inode(struct inode *inode)
{
Node *e = inode->u.generic_ip;
if (e) {
struct vfsmount *mnt;
write_lock(&entries_lock);
list_del(&e->list);
mnt = bm_mnt;
if (!--entry_count)
bm_mnt = NULL;
write_unlock(&entries_lock);
kfree(e);
mntput(mnt);
}
kfree(inode->u.generic_ip);
}
static void kill_node(Node *e)
......@@ -430,6 +418,7 @@ static void kill_node(Node *e)
dentry->d_inode->i_nlink--;
d_drop(dentry);
dput(dentry);
simple_release_fs(&bm_mnt, &entry_count);
}
}
......@@ -498,8 +487,6 @@ static struct file_operations bm_entry_operations = {
.write = bm_entry_write,
};
static struct file_system_type bm_fs_type;
/* /register */
static ssize_t bm_register_write(struct file *file, const char *buffer,
......@@ -507,7 +494,6 @@ static ssize_t bm_register_write(struct file *file, const char *buffer,
{
Node *e;
struct inode *inode;
struct vfsmount *mnt = NULL;
struct dentry *root, *dentry;
struct super_block *sb = file->f_vfsmnt->mnt_sb;
int err = 0;
......@@ -534,32 +520,22 @@ static ssize_t bm_register_write(struct file *file, const char *buffer,
if (!inode)
goto out2;
write_lock(&entries_lock);
if (!bm_mnt) {
write_unlock(&entries_lock);
mnt = kern_mount(&bm_fs_type);
if (IS_ERR(mnt)) {
err = PTR_ERR(mnt);
iput(inode);
inode = NULL;
goto out2;
}
write_lock(&entries_lock);
if (!bm_mnt)
bm_mnt = mnt;
err = simple_pin_fs("binfmt_misc", &bm_mnt, &entry_count);
if (err) {
iput(inode);
inode = NULL;
goto out2;
}
mntget(bm_mnt);
entry_count++;
e->dentry = dget(dentry);
inode->u.generic_ip = e;
inode->i_fop = &bm_entry_operations;
d_instantiate(dentry, inode);
write_lock(&entries_lock);
d_instantiate(dentry, inode);
list_add(&e->list, &entries);
write_unlock(&entries_lock);
mntput(mnt);
err = 0;
out2:
dput(dentry);
......
......@@ -4,8 +4,11 @@
*/
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/vfs.h>
extern struct vfsmount *do_kern_mount(const char *, int, char *, void *);
int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
......@@ -390,3 +393,36 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
dput(root);
return -ENOMEM;
}
static spinlock_t pin_fs_lock = SPIN_LOCK_UNLOCKED;
int simple_pin_fs(char *name, struct vfsmount **mount, int *count)
{
struct vfsmount *mnt = NULL;
spin_lock(&pin_fs_lock);
if (unlikely(!*mount)) {
spin_unlock(&pin_fs_lock);
mnt = do_kern_mount(name, 0, name, NULL);
if (IS_ERR(mnt))
return PTR_ERR(mnt);
spin_lock(&pin_fs_lock);
if (!*mount)
*mount = mnt;
}
mntget(*mount);
++*count;
spin_unlock(&pin_fs_lock);
mntput(mnt);
return 0;
}
void simple_release_fs(struct vfsmount **mount, int *count)
{
struct vfsmount *mnt;
spin_lock(&pin_fs_lock);
mnt = *mount;
if (!--*count)
*mount = NULL;
spin_unlock(&pin_fs_lock);
mntput(mnt);
}
......@@ -1294,6 +1294,8 @@ extern struct file_operations simple_dir_operations;
extern struct inode_operations simple_dir_inode_operations;
struct tree_descr { char *name; struct file_operations *ops; int mode; };
extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
extern void simple_release_fs(struct vfsmount **mount, int *count);
#ifdef CONFIG_BLK_DEV_INITRD
extern unsigned int real_root_dev;
......
......@@ -314,6 +314,8 @@ EXPORT_SYMBOL(simple_prepare_write);
EXPORT_SYMBOL(simple_commit_write);
EXPORT_SYMBOL(simple_empty);
EXPORT_SYMBOL(simple_fill_super);
EXPORT_SYMBOL(simple_pin_fs);
EXPORT_SYMBOL(simple_release_fs);
EXPORT_SYMBOL(fd_install);
EXPORT_SYMBOL(put_unused_fd);
EXPORT_SYMBOL(get_sb_bdev);
......
......@@ -29,7 +29,6 @@
#include <linux/sunrpc/rpc_pipe_fs.h>
static struct vfsmount *rpc_mount;
static spinlock_t rpc_mount_lock = SPIN_LOCK_UNLOCKED;
static int rpc_mount_count;
static struct file_system_type rpc_pipe_fs_type;
......@@ -379,46 +378,13 @@ static struct rpc_filelist authfiles[] = {
static int
rpc_get_mount(void)
{
struct vfsmount * mnt = NULL;
spin_lock(&rpc_mount_lock);
if (rpc_mount)
goto out_get;
spin_unlock(&rpc_mount_lock);
mnt = kern_mount(&rpc_pipe_fs_type);
if (IS_ERR(mnt))
return -ENODEV;
spin_lock(&rpc_mount_lock);
if (!rpc_mount) {
rpc_mount = mnt;
mnt = NULL;
goto out_dontget;
}
out_get:
mntget(rpc_mount);
out_dontget:
++rpc_mount_count;
spin_unlock(&rpc_mount_lock);
if (mnt)
mntput(mnt);
return 0;
return simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
}
static void
rpc_put_mount(void)
{
struct vfsmount *mnt;
spin_lock(&rpc_mount_lock);
mnt = rpc_mount;
--rpc_mount_count;
if (rpc_mount_count == 0)
rpc_mount = NULL;
else
mnt = NULL;
spin_unlock(&rpc_mount_lock);
if (mnt)
mntput(mnt);
simple_release_fs(&rpc_mount, &rpc_mount_count);
}
static int
......
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