... and the same for ipathfs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
index 4496f28..0db9c41 100644
--- a/drivers/infiniband/hw/ipath/Makefile
+++ b/drivers/infiniband/hw/ipath/Makefile
@@ -1,7 +1,7 @@
ccflags-y := -DIPATH_IDSTR='"QLogic kernel.org driver"' \
-DIPATH_KERN_TYPE=0
-obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o
+obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o ib_ipath_fs.o
ib_ipath-y := \
ipath_cq.o \
diff --git a/drivers/infiniband/hw/ipath/ib_ipath_fs.c b/drivers/infiniband/hw/ipath/ib_ipath_fs.c
new file mode 100644
index 0000000..bac0aac
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ib_ipath_fs.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+
+#include "ipath_kernel.h"
+
+#define IPATHFS_MAGIC 0x726a77
+
+struct infinipath_stats ipath_stats;
+EXPORT_SYMBOL(ipath_stats);
+static ssize_t atomic_stats_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return simple_read_from_buffer(buf, count, ppos, &ipath_stats,
+ sizeof ipath_stats);
+}
+
+static const struct file_operations atomic_stats_ops = {
+ .read = atomic_stats_read,
+ .llseek = default_llseek,
+};
+
+
+static int ipathfs_fill_super(struct super_block *sb, void *data,
+ int silent)
+{
+ static struct tree_descr files[] = {
+ [2] = {"atomic_stats", &atomic_stats_ops, S_IRUGO},
+ {""},
+ };
+
+ return simple_fill_super(sb, IPATHFS_MAGIC, files);
+}
+
+static struct dentry *ipathfs_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data)
+{
+ return mount_single(fs_type, flags, data, ipathfs_fill_super);
+}
+
+static struct file_system_type ipathfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "ipathfs",
+ .mount = ipathfs_mount,
+ .kill_sb = kill_litter_super,
+};
+
+static struct vfsmount *mnt;
+static int count;
+
+struct dentry *ipathfs_pin(void)
+{
+ int err = simple_pin_fs(&ipathfs_fs_type, &mnt, &count);
+ return err ? ERR_PTR(err) : mnt->mnt_root;
+}
+EXPORT_SYMBOL(ipathfs_pin);
+
+void ipathfs_unpin(void)
+{
+ simple_release_fs(&mnt, &count);
+}
+EXPORT_SYMBOL(ipathfs_unpin);
+
+static int __init ipath_init_ipathfs(void)
+{
+ return register_filesystem(&ipathfs_fs_type);
+}
+
+static void __exit ipath_exit_ipathfs(void)
+{
+ unregister_filesystem(&ipathfs_fs_type);
+}
+module_init(ipath_init_ipathfs)
+module_exit(ipath_exit_ipathfs)
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index bfca37b..95cca2c 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -2518,18 +2518,8 @@
goto bail_unit;
}
- ret = ipath_init_ipathfs();
- if (ret < 0) {
- printk(KERN_ERR IPATH_DRV_NAME ": Unable to create "
- "ipathfs: error %d\n", -ret);
- goto bail_pci;
- }
-
goto bail;
-bail_pci:
- pci_unregister_driver(&ipath_driver);
-
bail_unit:
idr_destroy(&unit_table);
@@ -2539,8 +2529,6 @@
static void __exit infinipath_cleanup(void)
{
- ipath_exit_ipathfs();
-
ipath_cdbg(VERBOSE, "Unregistering pci driver\n");
pci_unregister_driver(&ipath_driver);
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index a4de9d5..9ee3a2f 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -41,10 +41,6 @@
#include "ipath_kernel.h"
-#define IPATHFS_MAGIC 0x726a77
-
-static struct super_block *ipath_super;
-
static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
umode_t mode, const struct file_operations *fops,
void *data)
@@ -82,7 +78,6 @@
{
int error;
- *dentry = NULL;
mutex_lock(&parent->d_inode->i_mutex);
*dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(*dentry))
@@ -95,18 +90,6 @@
return error;
}
-static ssize_t atomic_stats_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- return simple_read_from_buffer(buf, count, ppos, &ipath_stats,
- sizeof ipath_stats);
-}
-
-static const struct file_operations atomic_stats_ops = {
- .read = atomic_stats_read,
- .llseek = default_llseek,
-};
-
static ssize_t atomic_counters_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -230,7 +213,7 @@
.llseek = default_llseek,
};
-static int create_device_files(struct super_block *sb,
+static int create_device_files(struct dentry *root,
struct ipath_devdata *dd)
{
struct dentry *dir, *tmp;
@@ -238,12 +221,13 @@
int ret;
snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
- ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
+ ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, root, &dir,
&simple_dir_operations, dd);
if (ret) {
printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret);
goto bail;
}
+ dd->ipathfs_dir = dir;
ret = create_file("atomic_counters", S_IFREG|S_IRUGO, dir, &tmp,
&atomic_counters_ops, dd);
@@ -295,128 +279,40 @@
return ret;
}
-static int remove_device_files(struct super_block *sb,
- struct ipath_devdata *dd)
+static int remove_device_files(struct ipath_devdata *dd)
{
- struct dentry *dir, *root;
- char unit[10];
+ struct dentry *dir = dd->ipathfs_dir;
+ struct dentry *root;
int ret;
- root = dget(sb->s_root);
+ if (!dir)
+ return 0;
+
+ root = dir->d_sb->s_root;
mutex_lock(&root->d_inode->i_mutex);
- snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
- dir = lookup_one_len(unit, root, strlen(unit));
-
- if (IS_ERR(dir)) {
- ret = PTR_ERR(dir);
- printk(KERN_ERR "Lookup of %s failed\n", unit);
- goto bail;
- }
-
remove_file(dir, "flash");
remove_file(dir, "atomic_counters");
d_delete(dir);
ret = simple_rmdir(root->d_inode, dir);
-
-bail:
mutex_unlock(&root->d_inode->i_mutex);
- dput(root);
- return ret;
-}
-
-static int ipathfs_fill_super(struct super_block *sb, void *data,
- int silent)
-{
- struct ipath_devdata *dd, *tmp;
- unsigned long flags;
- int ret;
-
- static struct tree_descr files[] = {
- [2] = {"atomic_stats", &atomic_stats_ops, S_IRUGO},
- {""},
- };
-
- ret = simple_fill_super(sb, IPATHFS_MAGIC, files);
- if (ret) {
- printk(KERN_ERR "simple_fill_super failed: %d\n", ret);
- goto bail;
- }
-
- spin_lock_irqsave(&ipath_devs_lock, flags);
-
- list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
- spin_unlock_irqrestore(&ipath_devs_lock, flags);
- ret = create_device_files(sb, dd);
- if (ret)
- goto bail;
- spin_lock_irqsave(&ipath_devs_lock, flags);
- }
-
- spin_unlock_irqrestore(&ipath_devs_lock, flags);
-
-bail:
- return ret;
-}
-
-static struct dentry *ipathfs_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
-{
- struct dentry *ret;
- ret = mount_single(fs_type, flags, data, ipathfs_fill_super);
- if (!IS_ERR(ret))
- ipath_super = ret->d_sb;
- return ret;
-}
-
-static void ipathfs_kill_super(struct super_block *s)
-{
- kill_litter_super(s);
- ipath_super = NULL;
-}
-
-int ipathfs_add_device(struct ipath_devdata *dd)
-{
- int ret;
-
- if (ipath_super == NULL) {
- ret = 0;
- goto bail;
- }
-
- ret = create_device_files(ipath_super, dd);
-
-bail:
return ret;
}
int ipathfs_remove_device(struct ipath_devdata *dd)
{
- int ret;
-
- if (ipath_super == NULL) {
- ret = 0;
- goto bail;
- }
-
- ret = remove_device_files(ipath_super, dd);
-
-bail:
+ int ret = remove_device_files(dd);
+ ipathfs_unpin();
return ret;
}
-static struct file_system_type ipathfs_fs_type = {
- .owner = THIS_MODULE,
- .name = "ipathfs",
- .mount = ipathfs_mount,
- .kill_sb = ipathfs_kill_super,
-};
-
-int __init ipath_init_ipathfs(void)
+int ipathfs_add_device(struct ipath_devdata *dd)
{
- return register_filesystem(&ipathfs_fs_type);
-}
-
-void __exit ipath_exit_ipathfs(void)
-{
- unregister_filesystem(&ipathfs_fs_type);
+ struct dentry *root = ipathfs_pin();
+ int ret = PTR_ERR(root);
+ if (!IS_ERR(root)) {
+ ret = create_device_files(root, dd);
+ if (ret)
+ ipathfs_remove_device(dd);
+ }
+ return ret;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 6559af6..9069779 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -828,6 +828,7 @@
*/
spinlock_t ipath_sdepb_lock;
u8 ipath_presets_needed; /* Set if presets to be restored next DOWN */
+ struct dentry *ipathfs_dir;
};
/* ipath_hol_state values (stopping/starting user proc, send flushing) */
@@ -1290,11 +1291,12 @@
void ipath_device_remove_group(struct device *, struct ipath_devdata *);
int ipath_expose_reset(struct device *);
-int ipath_init_ipathfs(void);
-void ipath_exit_ipathfs(void);
int ipathfs_add_device(struct ipath_devdata *);
int ipathfs_remove_device(struct ipath_devdata *);
+struct dentry *ipathfs_pin(void);
+void ipathfs_unpin(void);
+
/*
* dma_addr wrappers - all 0's invalid for hw
*/
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
index f63e143..5cab5e9 100644
--- a/drivers/infiniband/hw/ipath/ipath_stats.c
+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -33,8 +33,6 @@
#include "ipath_kernel.h"
-struct infinipath_stats ipath_stats;
-
/**
* ipath_snap_cntr - snapshot a chip counter
* @dd: the infinipath device