[BACK]Return to xfs_vfs.c CVS log [TXT][DIR] Up to [Development] / linux-2.6-xfs / mainline-patches / linux-2.6

File: [Development] / linux-2.6-xfs / mainline-patches / linux-2.6 / xfs_vfs.c (download)

Revision 1.3, Tue Jan 16 14:56:58 2007 UTC (10 years, 9 months ago) by vapo.longdrop.melbourne.sgi.com
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +210 -0 lines

Merge of 2.6.x-xfs-melb:linux:27935a by kenmcd.

  Reinstate delete file.

Definition of vfs_get_inode for ioops module.
Add behaviour module support.

--- /tmp/diff_prompt.12865.update_only	2006-12-15 22:49:16.949849328 +1100
+++ linux-2.6/xfs_vfs.c	2006-12-15 17:48:29.000000000 +1100
@@ -183,6 +183,19 @@
 	return ((*bhvtovfsops(next)->vfs_quotactl)(next, cmd, id, addr));
 }
 
+struct inode *
+vfs_get_inode(
+	struct bhv_desc		*bdp,
+	xfs_ino_t		ino,
+	int			fl)
+{
+	struct bhv_desc		*next = bdp;
+
+	while (! (bhvtovfsops(next))->vfs_get_inode)
+		next = BHV_NEXTNULL(next);
+	return ((*bhvtovfsops(next)->vfs_get_inode)(next, ino, fl));
+}
+
 void
 vfs_init_vnode(
 	struct bhv_desc		*bdp,
@@ -262,18 +275,6 @@
 }
 
 void
-vfs_insertops(
-	struct bhv_vfs		*vfsp,
-	struct bhv_module_vfsops *vfsops)
-{
-	struct bhv_desc		*bdp;
-
-	bdp = kmem_alloc(sizeof(struct bhv_desc), KM_SLEEP);
-	bhv_desc_init(bdp, NULL, vfsp, vfsops);
-	bhv_insert(&vfsp->vfs_bh, bdp);
-}
-
-void
 vfs_insertbhv(
 	struct bhv_vfs		*vfsp,
 	struct bhv_desc		*bdp,
@@ -284,6 +285,99 @@
 	bhv_insert_initial(&vfsp->vfs_bh, bdp);
 }
 
+/*
+ * Implementation for behaviours-as-modules
+ */
+
+typedef struct bhv_module_list {
+	struct list_head	bm_list;
+	struct module *		bm_module;
+	const char *		bm_name;
+	void *			bm_ops;
+} bhv_module_list_t;
+
+static DEFINE_SPINLOCK(bhv_lock);
+static struct list_head bhv_list = LIST_HEAD_INIT(bhv_list);
+
+void
+bhv_module_init(
+	const char		*name,
+	struct module		*module,
+	const void		*ops)
+{
+	bhv_module_list_t	*bm, *entry, *n;
+
+	bm = kmem_alloc(sizeof(struct bhv_module_list), KM_SLEEP);
+	INIT_LIST_HEAD(&bm->bm_list);
+	bm->bm_module = module;
+	bm->bm_name = name;
+	bm->bm_ops = (void *)ops;
+
+	spin_lock(&bhv_lock);
+	list_for_each_entry_safe(entry, n, &bhv_list, bm_list)
+		BUG_ON(strcmp(entry->bm_name, name) == 0);
+	list_add(&bm->bm_list, &bhv_list);
+	spin_unlock(&bhv_lock);
+}
+
+void
+bhv_module_exit(
+	const char		*name)
+{
+	bhv_module_list_t	*entry, *n;
+
+	spin_lock(&bhv_lock);
+	list_for_each_entry_safe(entry, n, &bhv_list, bm_list)
+		if (strcmp(entry->bm_name, name) == 0)
+			list_del(&entry->bm_list);
+	spin_unlock(&bhv_lock);
+}
+
+STATIC void *
+bhv_insert_module(
+	const char		*name,
+	const char		*modname)
+{
+	bhv_module_list_t	*entry, *n;
+	void			*ops = NULL;
+
+	spin_lock(&bhv_lock);
+	list_for_each_entry_safe(entry, n, &bhv_list, bm_list)
+		if (strcmp(entry->bm_name, name) == 0 &&
+		    try_module_get(entry->bm_module))
+			ops = entry->bm_ops;
+	spin_unlock(&bhv_lock);
+	return ops;
+}
+
+STATIC void
+bhv_remove_module(
+	const char		*name)
+{
+	bhv_module_list_t	*entry, *n;
+
+	spin_lock(&bhv_lock);
+	list_for_each_entry_safe(entry, n, &bhv_list, bm_list)
+		if (strcmp(entry->bm_name, name) == 0)
+		    module_put(entry->bm_module);
+	spin_unlock(&bhv_lock);
+}
+
+STATIC void *
+bhv_lookup_module(
+	const char		*name,
+	const char		*module)
+{
+	void			*ops;
+
+	ops = bhv_insert_module(name, module);
+	if (!ops && module) {
+		request_module("%s", module);
+		ops = bhv_insert_module(name, module);
+	}
+	return ops;
+}
+
 void
 bhv_remove_vfsops(
 	struct bhv_vfs		*vfsp,
@@ -292,10 +386,14 @@
 	struct bhv_desc		*bhv;
 
 	bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos);
-	if (!bhv)
-		return;
-	bhv_remove(&vfsp->vfs_bh, bhv);
-	kmem_free(bhv, sizeof(*bhv));
+	if (bhv) {
+		struct bhv_module	*bm;
+
+		bm = (bhv_module_t *) BHV_PDATA(bhv);
+		bhv_remove(&vfsp->vfs_bh, bhv);
+		bhv_remove_module(bm->bm_name);
+		kmem_free(bhv, sizeof(*bhv));
+	}
 }
 
 void
@@ -307,6 +405,7 @@
 
 	bhv_remove_vfsops(vfsp, VFS_POSITION_QM);
 	bhv_remove_vfsops(vfsp, VFS_POSITION_DM);
+	bhv_remove_vfsops(vfsp, VFS_POSITION_IO);
 	if (!freebase)
 		return;
 	mp = XFS_VFSTOM(vfsp);
@@ -315,6 +414,25 @@
 }
 
 void
+bhv_get_vfsops(
+	struct bhv_vfs		*vfsp,
+	const char		*name,
+	const char		*module)
+{
+	struct bhv_vfsops	*ops;
+
+	ops = (struct bhv_vfsops *) bhv_lookup_module(name, module);
+	if (ops) {
+		struct bhv_module	*bm;
+
+		bm = kmem_alloc(sizeof(struct bhv_module), KM_SLEEP);
+		bm->bm_name = name;
+		bhv_desc_init(&bm->bm_desc, bm, vfsp, ops);
+		bhv_insert(&vfsp->vfs_bh, &bm->bm_desc);
+	}
+}
+
+void
 bhv_insert_all_vfsops(
 	struct bhv_vfs		*vfsp)
 {
@@ -322,6 +440,10 @@
 
 	mp = xfs_mount_init();
 	vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
-	vfs_insertdmapi(vfsp);
-	vfs_insertquota(vfsp);
+	bhv_get_vfsops(vfsp, XFS_DMOPS,
+		xfs_probe_dmapi ? XFS_DM_MODULE : NULL);
+	bhv_get_vfsops(vfsp, XFS_QMOPS,
+		xfs_probe_quota ? XFS_QM_MODULE : NULL);
+	bhv_get_vfsops(vfsp, XFS_IOOPS,
+		xfs_probe_ioops ? XFS_IO_MODULE : NULL);
 }