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