Whamcloud - gitweb
- landed b_hd_cray_merge3
[fs/lustre-release.git] / lustre / lvfs / lvfs_common.c
index caa6e01..744b8fb 100644 (file)
@@ -25,6 +25,7 @@
 
 #define DEBUG_SUBSYSTEM S_FILTER
 
+#include <linux/obd.h>
 #include <linux/lvfs.h>
 
 struct dentry *lvfs_id2dentry(struct lvfs_run_ctxt *ctxt, __u64 id,
@@ -33,3 +34,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;
+
+                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));
+                dev_clear_rdonly(2);
+        }
+}
+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);