From 08f3d07ddd53ca3bf322ddebc0f8992e3112520f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 30 Mar 2013 00:36:23 -0400 Subject: [PATCH] dgrp procfs fixes, part 4: get rid of sysctl-like machinery racy and very overblown... Signed-off-by: Al Viro --- drivers/staging/dgrp/dgrp_common.h | 55 ------ drivers/staging/dgrp/dgrp_specproc.c | 257 +++++---------------------- 2 files changed, 42 insertions(+), 270 deletions(-) diff --git a/drivers/staging/dgrp/dgrp_common.h b/drivers/staging/dgrp/dgrp_common.h index fde116236e98..99e231c3c602 100644 --- a/drivers/staging/dgrp/dgrp_common.h +++ b/drivers/staging/dgrp/dgrp_common.h @@ -76,61 +76,6 @@ extern void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c); extern void dgrp_remove_tty_sysfs(struct device *c); /* from dgrp_specproc.c */ -/* - * The list of DGRP entries with r/w capabilities. These - * magic numbers are used for identification purposes. - */ -enum { - DGRP_CONFIG = 1, /* Configure portservers */ - DGRP_NETDIR = 2, /* Directory for "net" devices */ - DGRP_MONDIR = 3, /* Directory for "mon" devices */ - DGRP_PORTSDIR = 4, /* Directory for "ports" devices */ - DGRP_INFO = 5, /* Get info. about the running module */ - DGRP_NODEINFO = 6, /* Get info. about the configured nodes */ - DGRP_DPADIR = 7, /* Directory for the "dpa" devices */ -}; - -/* - * Directions for proc handlers - */ -enum { - INBOUND = 1, /* Data being written to kernel */ - OUTBOUND = 2, /* Data being read from the kernel */ -}; - -/** - * dgrp_proc_entry: structure for dgrp proc dirs - * @id: ID number associated with this particular entry. Should be - * unique across all of DGRP. - * @name: text name associated with the /proc entry - * @mode: file access permisssions for the /proc entry - * @child: pointer to table describing a subdirectory for this entry - * @de: pointer to directory entry for this object once registered. Used - * to grab the handle of the object for unregistration - * @excl_sem: semaphore to provide exclusive to struct - * @excl_cnt: counter of current accesses - * - * Each entry in a DGRP proc directory is described with a - * dgrp_proc_entry structure. A collection of these - * entries (in an array) represents the members associated - * with a particular /proc directory, and is referred to - * as a table. All tables are terminated by an entry with - * zeros for every member. - */ -struct dgrp_proc_entry { - int id; /* Integer identifier */ - const char *name; /* ASCII identifier */ - umode_t mode; /* File access permissions */ - struct dgrp_proc_entry *child; /* Child pointer */ - - /* file ops to use, pass NULL to use default */ - struct file_operations *proc_file_ops; - - struct proc_dir_entry *de; /* proc entry pointer */ - struct semaphore excl_sem; /* Protects exclusive access var */ - int excl_cnt; /* Counts number of curr accesses */ -}; - extern void dgrp_unregister_proc(void); extern void dgrp_register_proc(void); diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c index 1ccf10ce85cd..caf4faccf42d 100644 --- a/drivers/staging/dgrp/dgrp_specproc.c +++ b/drivers/staging/dgrp/dgrp_specproc.c @@ -44,7 +44,6 @@ #include "dgrp_common.h" -static struct dgrp_proc_entry dgrp_table[]; static struct proc_dir_entry *dgrp_proc_dir_entry; static int dgrp_add_id(long id); @@ -63,16 +62,6 @@ static struct inode_operations proc_inode_ops = { }; -static void register_proc_table(struct dgrp_proc_entry *, - struct proc_dir_entry *); -static void unregister_proc_table(struct dgrp_proc_entry *, - struct proc_dir_entry *); - -static struct dgrp_proc_entry dgrp_net_table[]; -static struct dgrp_proc_entry dgrp_mon_table[]; -static struct dgrp_proc_entry dgrp_ports_table[]; -static struct dgrp_proc_entry dgrp_dpa_table[]; - static ssize_t dgrp_config_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos); @@ -106,72 +95,11 @@ static struct file_operations nodeinfo_proc_file_ops = { .release = seq_release, }; -static struct dgrp_proc_entry dgrp_table[] = { - { - .id = DGRP_CONFIG, - .name = "config", - .mode = 0644, - .proc_file_ops = &config_proc_file_ops, - }, - { - .id = DGRP_INFO, - .name = "info", - .mode = 0644, - .proc_file_ops = &info_proc_file_ops, - }, - { - .id = DGRP_NODEINFO, - .name = "nodeinfo", - .mode = 0644, - .proc_file_ops = &nodeinfo_proc_file_ops, - }, - { - .id = DGRP_NETDIR, - .name = "net", - .mode = 0500, - .child = dgrp_net_table - }, - { - .id = DGRP_MONDIR, - .name = "mon", - .mode = 0500, - .child = dgrp_mon_table - }, - { - .id = DGRP_PORTSDIR, - .name = "ports", - .mode = 0500, - .child = dgrp_ports_table - }, - { - .id = DGRP_DPADIR, - .name = "dpa", - .mode = 0500, - .child = dgrp_dpa_table - } -}; - static struct proc_dir_entry *net_entry_pointer; static struct proc_dir_entry *mon_entry_pointer; static struct proc_dir_entry *dpa_entry_pointer; static struct proc_dir_entry *ports_entry_pointer; -static struct dgrp_proc_entry dgrp_net_table[] = { - {0} -}; - -static struct dgrp_proc_entry dgrp_mon_table[] = { - {0} -}; - -static struct dgrp_proc_entry dgrp_ports_table[] = { - {0} -}; - -static struct dgrp_proc_entry dgrp_dpa_table[] = { - {0} -}; - void dgrp_unregister_proc(void) { net_entry_pointer = NULL; @@ -180,163 +108,62 @@ void dgrp_unregister_proc(void) ports_entry_pointer = NULL; if (dgrp_proc_dir_entry) { - unregister_proc_table(dgrp_table, dgrp_proc_dir_entry); - remove_proc_entry(dgrp_proc_dir_entry->name, - dgrp_proc_dir_entry->parent); + struct nd_struct *nd; + list_for_each_entry(nd, &nd_struct_list, list) { + if (nd->nd_net_de) { + unregister_dgrp_device(nd->nd_net_de); + dgrp_remove_node_class_sysfs_files(nd); + } + + if (nd->nd_mon_de) + unregister_dgrp_device(nd->nd_mon_de); + + if (nd->nd_dpa_de) + unregister_dgrp_device(nd->nd_dpa_de); + + if (nd->nd_ports_de) + unregister_dgrp_device(nd->nd_ports_de); + } + remove_proc_entry("dgrp/config", NULL); + remove_proc_entry("dgrp/info", NULL); + remove_proc_entry("dgrp/nodeinfo", NULL); + remove_proc_entry("dgrp/net", NULL); + remove_proc_entry("dgrp/mon", NULL); + remove_proc_entry("dgrp/dpa", NULL); + remove_proc_entry("dgrp/ports", NULL); + remove_proc_entry("dgrp", NULL); dgrp_proc_dir_entry = NULL; } - } void dgrp_register_proc(void) { + struct proc_dir_entry *de; /* * Register /proc/dgrp */ dgrp_proc_dir_entry = proc_mkdir("dgrp", NULL); - register_proc_table(dgrp_table, dgrp_proc_dir_entry); -} - -/* - * /proc/sys support - */ -static int dgrp_proc_match(int len, const char *name, struct proc_dir_entry *de) -{ - if (!de || !de->low_ino) - return 0; - if (de->namelen != len) - return 0; - return !memcmp(name, de->name, len); -} - - -/* - * Scan the entries in table and add them all to /proc at the position - * referred to by "root" - */ -static void register_proc_table(struct dgrp_proc_entry *table, - struct proc_dir_entry *root) -{ - struct proc_dir_entry *de; - int len; - umode_t mode; - - if (table == NULL) + if (!dgrp_proc_dir_entry) return; - if (root == NULL) - return; - - for (; table->id; table++) { - /* Can't do anything without a proc name. */ - if (!table->name) - continue; - - /* Maybe we can't do anything with it... */ - if (!table->proc_file_ops && - !table->child) { - pr_warn("dgrp: Can't register %s\n", - table->name); - continue; - } - - len = strlen(table->name); - mode = table->mode; - - de = NULL; - if (!table->child) - mode |= S_IFREG; - else { - mode |= S_IFDIR; - for (de = root->subdir; de; de = de->next) { - if (dgrp_proc_match(len, table->name, de)) - break; - } - /* If the subdir exists already, de is non-NULL */ - } - - if (!de) { - de = create_proc_entry(table->name, mode, root); - if (!de) - continue; - de->data = (void *) table; - if (!table->child) { - de->proc_iops = &proc_inode_ops; - de->proc_fops = table->proc_file_ops; - } - } - table->de = de; - if (de->mode & S_IFDIR) - register_proc_table(table->child, de); - - if (table->id == DGRP_NETDIR) - net_entry_pointer = de; - - if (table->id == DGRP_MONDIR) - mon_entry_pointer = de; - - if (table->id == DGRP_DPADIR) - dpa_entry_pointer = de; - - if (table->id == DGRP_PORTSDIR) - ports_entry_pointer = de; + de = create_proc_entry("dgrp/config", 0644, NULL); + if (de) { + de->proc_fops = &config_proc_file_ops; + de->proc_iops = &proc_inode_ops; } -} - -/* - * Unregister a /proc sysctl table and any subdirectories. - */ -static void unregister_proc_table(struct dgrp_proc_entry *table, - struct proc_dir_entry *root) -{ - struct proc_dir_entry *de; - struct nd_struct *tmp; - - if (table == NULL) - return; - - list_for_each_entry(tmp, &nd_struct_list, list) { - if ((table == dgrp_net_table) && (tmp->nd_net_de)) { - unregister_dgrp_device(tmp->nd_net_de); - dgrp_remove_node_class_sysfs_files(tmp); - } - - if ((table == dgrp_mon_table) && (tmp->nd_mon_de)) - unregister_dgrp_device(tmp->nd_mon_de); - - if ((table == dgrp_dpa_table) && (tmp->nd_dpa_de)) - unregister_dgrp_device(tmp->nd_dpa_de); - - if ((table == dgrp_ports_table) && (tmp->nd_ports_de)) - unregister_dgrp_device(tmp->nd_ports_de); + de = create_proc_entry("dgrp/info", 0644, NULL); + if (de) { + de->proc_fops = &info_proc_file_ops; + de->proc_iops = &proc_inode_ops; } - - for (; table->id; table++) { - de = table->de; - - if (!de) - continue; - if (de->mode & S_IFDIR) { - if (!table->child) { - pr_alert("dgrp: malformed sysctl tree on free\n"); - continue; - } - unregister_proc_table(table->child, de); - - /* Don't unregister directories which still have entries */ - if (de->subdir) - continue; - } - - /* Don't unregister proc entries that are still being used.. */ - if ((atomic_read(&de->count)) != 1) { - pr_alert("proc entry %s in use, not removing\n", - de->name); - continue; - } - - remove_proc_entry(de->name, de->parent); - table->de = NULL; + de = create_proc_entry("dgrp/nodeinfo", 0644, NULL); + if (de) { + de->proc_fops = &nodeinfo_proc_file_ops; + de->proc_iops = &proc_inode_ops; } + net_entry_pointer = proc_mkdir_mode("dgrp/net", 0500, NULL); + mon_entry_pointer = proc_mkdir_mode("dgrp/mon", 0500, NULL); + dpa_entry_pointer = proc_mkdir_mode("dgrp/dpa", 0500, NULL); + ports_entry_pointer = proc_mkdir_mode("dgrp/ports", 0500, NULL); } static void *dgrp_config_proc_start(struct seq_file *m, loff_t *pos)