patch-2.1.58 linux/fs/proc/generic.c
Next file: linux/fs/proc/inode.c
Previous file: linux/fs/proc/base.c
Back to the patch index
Back to the overall index
- Lines: 145
- Date:
Sun Oct 12 10:16:38 1997
- Orig file:
v2.1.57/linux/fs/proc/generic.c
- Orig date:
Tue Sep 23 16:48:49 1997
diff -u --recursive --new-file v2.1.57/linux/fs/proc/generic.c linux/fs/proc/generic.c
@@ -16,11 +16,13 @@
#include <linux/stat.h>
#include <asm/bitops.h>
+extern struct inode_operations proc_dyna_dir_inode_operations;
+
static long proc_file_read(struct inode * inode, struct file * file,
char * buf, unsigned long nbytes);
static long proc_file_write(struct inode * inode, struct file * file,
const char * buffer, unsigned long count);
-static long long proc_file_lseek(struct file * file, long long offset, int orig);
+static long long proc_file_lseek(struct file *, long long, int);
int proc_match(int len, const char *name,struct proc_dir_entry * de)
{
@@ -44,17 +46,14 @@
NULL /* can't fsync */
};
-/*
- * proc files can do almost nothing..
- */
struct inode_operations proc_file_inode_operations = {
- &proc_file_operations, /* default proc file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
+ &proc_file_operations, /* default proc file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
@@ -240,57 +239,77 @@
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent)
{
- struct proc_dir_entry *ent;
- const char *fn;
+ struct proc_dir_entry *ent = NULL;
+ const char *fn = name;
+ int len;
- if (parent)
- fn = name;
- else {
- if (xlate_proc_name(name, &parent, &fn))
- return NULL;
- }
+ if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+ goto out;
+ len = strlen(fn);
- ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+ ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
if (!ent)
- return NULL;
+ goto out;
memset(ent, 0, sizeof(struct proc_dir_entry));
+ memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
+ ent->name = ((char *) ent) + sizeof(*ent);
+ ent->namelen = len;
- if (mode == S_IFDIR)
+ if (mode == S_IFDIR) {
mode |= S_IRUGO | S_IXUGO;
- else if (mode == 0)
- mode = S_IFREG | S_IRUGO;
-
- ent->name = fn;
- ent->namelen = strlen(fn);
- ent->mode = mode;
- if (S_ISDIR(mode))
+ ent->ops = &proc_dyna_dir_inode_operations;
ent->nlink = 2;
- else
+ }
+ else if (mode == 0) {
+ mode = S_IFREG | S_IRUGO;
ent->nlink = 1;
+ }
+ ent->mode = mode;
proc_register(parent, ent);
+out:
return ent;
}
+extern void free_proc_entry(struct proc_dir_entry *);
+void free_proc_entry(struct proc_dir_entry *de)
+{
+ kfree(de);
+}
+
+/*
+ * Remove a /proc entry and free it if it's not currently in use.
+ * If it is in use, we set the 'deleted' flag.
+ */
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
{
struct proc_dir_entry *de;
- const char *fn;
+ const char *fn = name;
int len;
- if (parent)
- fn = name;
- else
- if (xlate_proc_name(name, &parent, &fn))
- return;
+ if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+ goto out;
len = strlen(fn);
for (de = parent->subdir; de ; de = de->next) {
if (proc_match(len, fn, de))
break;
}
- if (de)
+
+ if (de) {
+printk("remove_proc_entry: parent nlink=%d, file nlink=%d\n",
+parent->nlink, de->nlink);
proc_unregister(parent, de->low_ino);
- kfree(de);
+ de->nlink = 0;
+ de->deleted = 1;
+ if (!de->count)
+ free_proc_entry(de);
+ else {
+ printk("remove_proc_entry: %s/%s busy, count=%d\n",
+ parent->name, de->name, de->count);
+ }
+ }
+out:
+ return;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov