#define DEBUG_SUBSYSTEM S_FILTER
+#include <linux/obd.h>
+#include <linux/obd_support.h>
#include <linux/lvfs.h>
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);