X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flvfs%2Flvfs_common.c;h=aa4d3f3def66eb1690717b3ab65dd0ed17bc3dd2;hb=f24218109154516e02e9a60df1e5a6f078c5e63f;hp=caa6e01215a41a181e7437b405f43765c67950b2;hpb=9d4b898b1c1c7c318fda5f0c345ed726c774c06a;p=fs%2Flustre-release.git diff --git a/lustre/lvfs/lvfs_common.c b/lustre/lvfs/lvfs_common.c index caa6e01..aa4d3f3 100644 --- a/lustre/lvfs/lvfs_common.c +++ b/lustre/lvfs/lvfs_common.c @@ -25,6 +25,8 @@ #define DEBUG_SUBSYSTEM S_FILTER +#include +#include #include struct dentry *lvfs_id2dentry(struct lvfs_run_ctxt *ctxt, __u64 id, @@ -33,3 +35,117 @@ struct dentry *lvfs_id2dentry(struct lvfs_run_ctxt *ctxt, __u64 id, return ctxt->cb_ops.l_id2dentry(id, gen, gr, data); } EXPORT_SYMBOL(lvfs_id2dentry); + +static struct list_head lvfs_context_list; + +void lvfs_mount_list_init(void) +{ + INIT_LIST_HEAD(&lvfs_context_list); +} + +void lvfs_mount_list_cleanup(void) +{ + struct list_head *tmp; + + if (list_empty(&lvfs_context_list)) + return; + + list_for_each(tmp, &lvfs_context_list) { + struct lvfs_obd_ctxt *data = + list_entry(tmp, struct lvfs_obd_ctxt, loc_list); + CERROR("device %s still mounted with refcount %d\n", + data->loc_name, atomic_read(&data->loc_refcount)); + } +} + +static inline +struct lvfs_obd_ctxt *get_lvfs_mount(struct lvfs_obd_ctxt *lvfs_ctxt) +{ + atomic_inc(&lvfs_ctxt->loc_refcount); + return lvfs_ctxt; +} + +static struct lvfs_obd_ctxt *add_lvfs_mount(struct vfsmount *mnt, char *name) +{ + struct lvfs_obd_ctxt *lvfs_ctxt; + ENTRY; + + OBD_ALLOC(lvfs_ctxt, sizeof(*lvfs_ctxt)); + if (!lvfs_ctxt) { + CERROR("No Memory\n"); + RETURN(NULL); + } + + if (name) { + int length = strlen(name) + 1; + + OBD_ALLOC(lvfs_ctxt->loc_name, length); + if (!lvfs_ctxt->loc_name) { + CERROR("No Memory\n"); + OBD_FREE(lvfs_ctxt, sizeof(*lvfs_ctxt)); + RETURN(NULL); + } + memcpy(lvfs_ctxt->loc_name, name, length); + } + lvfs_ctxt->loc_mnt = mnt; + list_add(&lvfs_ctxt->loc_list, &lvfs_context_list); + atomic_set(&lvfs_ctxt->loc_refcount, 1); + RETURN(lvfs_ctxt); +} + +void lvfs_umount_fs(struct lvfs_obd_ctxt *lvfs_ctxt) +{ + if (lvfs_ctxt && atomic_dec_and_test(&lvfs_ctxt->loc_refcount)) { + struct vfsmount *mnt = lvfs_ctxt->loc_mnt; + ll_sbdev_type save_dev = ll_sbdev(mnt->mnt_sb); + + list_del(&lvfs_ctxt->loc_list); + if (atomic_read(&mnt->mnt_count) > 2) + CERROR("mount busy, mnt %p mnt_count %d != 2\n", mnt, + atomic_read(&mnt->mnt_count)); + + mntput(mnt); + if (lvfs_ctxt->loc_name) + OBD_FREE(lvfs_ctxt->loc_name, + strlen(lvfs_ctxt->loc_name) + 1); + OBD_FREE(lvfs_ctxt, sizeof(*lvfs_ctxt)); + ll_clear_rdonly(save_dev); + } +} +EXPORT_SYMBOL(lvfs_umount_fs); + +int lvfs_mount_fs(char *name, char *fstype, char *options, int flags, + struct lvfs_obd_ctxt **lvfs_ctxt) +{ + struct vfsmount *mnt = NULL; + struct list_head *tmp; + int rc = 0; + ENTRY; + + list_for_each(tmp, &lvfs_context_list) { + struct lvfs_obd_ctxt *data = + list_entry(tmp, struct lvfs_obd_ctxt, loc_list); + if (strcmp(data->loc_name, name) == 0) { + *lvfs_ctxt = get_lvfs_mount(data); + RETURN(0); + } + } + mnt = do_kern_mount(fstype, flags, name, options); + + if (IS_ERR(mnt)) { + rc = PTR_ERR(mnt); + CERROR("do_kern_mount failed: rc = %d\n", rc); + GOTO(out, rc); + } + CDEBUG(D_SUPER, "%s: mnt = %p\n", name, mnt); + /*add this lvfs context to the lvfs_mount_list*/ + *lvfs_ctxt = add_lvfs_mount(mnt, name); + if (!*lvfs_ctxt) { + mntput(mnt); + CERROR("add_lvfs_mount failed\n"); + GOTO(out, rc = -EINVAL); + } +out: + RETURN(rc); +} +EXPORT_SYMBOL(lvfs_mount_fs);