patch-2.1.58 linux/fs/proc/inode.c
Next file: linux/fs/proc/root.c
Previous file: linux/fs/proc/generic.c
Back to the patch index
Back to the overall index
- Lines: 203
- Date:
Sun Oct 12 10:16:38 1997
- Orig file:
v2.1.57/linux/fs/proc/inode.c
- Orig date:
Thu Jul 17 10:06:07 1997
diff -u --recursive --new-file v2.1.57/linux/fs/proc/inode.c linux/fs/proc/inode.c
@@ -17,23 +17,66 @@
#include <asm/system.h>
#include <asm/uaccess.h>
+extern void free_proc_entry(struct proc_dir_entry *);
+
+struct proc_dir_entry * de_get(struct proc_dir_entry *de)
+{
+ if (de)
+ de->count++;
+ return de;
+}
+
+/*
+ * Decrements the use count and checks for deferred deletion.
+ */
+void de_put(struct proc_dir_entry *de)
+{
+ if (de) {
+ if (!de->count) {
+ printk("de_put: entry %s already free!\n", de->name);
+ return;
+ }
+
+ if (!--de->count) {
+ if (de->deleted) {
+ printk("de_put: deferred delete of %s\n",
+ de->name);
+ free_proc_entry(de);
+ }
+ }
+ }
+}
+
static void proc_put_inode(struct inode *inode)
{
#ifdef CONFIG_SUN_OPENPROMFS_MODULE
- if ((inode->i_ino >= PROC_OPENPROM_FIRST)
- && (inode->i_ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM)
- && proc_openprom_use)
+ if ((inode->i_ino >= PROC_OPENPROM_FIRST) &&
+ (inode->i_ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM) &&
+ proc_openprom_use)
(*proc_openprom_use)(inode, 0);
#endif
+ /*
+ * Kill off unused inodes ... VFS will unhash and
+ * delete the inode if we set i_nlink to zero.
+ */
+ if (inode->i_count == 1)
+ inode->i_nlink = 0;
}
/*
- * Does this ever happen?
+ * Decrement the use count of the proc_dir_entry.
*/
static void proc_delete_inode(struct inode *inode)
{
- printk("proc_delete_inode()?\n");
- inode->i_size = 0;
+ struct proc_dir_entry *de = inode->u.generic_ip;
+ if (de) {
+ /*
+ * Call the fill_inode hook to release module counts.
+ */
+ if (de->fill_inode)
+ de->fill_inode(inode, 0);
+ de_put(de);
+ }
}
static void proc_put_super(struct super_block *sb)
@@ -47,7 +90,7 @@
proc_read_inode,
proc_write_inode,
proc_put_inode,
- proc_delete_inode,
+ proc_delete_inode, /* delete_inode(struct inode *) */
NULL,
proc_put_super,
NULL,
@@ -85,9 +128,24 @@
return 1;
}
-struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_entry * de)
+struct inode * proc_get_inode(struct super_block * sb, int ino,
+ struct proc_dir_entry * de)
{
- struct inode * inode = iget(s, ino);
+ struct inode * inode;
+
+ /*
+ * Increment the use count so the dir entry can't disappear.
+ */
+ de_get(de);
+#if 1
+/* shouldn't ever happen */
+if (de && de->deleted)
+printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count);
+#endif
+
+ inode = iget(sb, ino);
+ if (!inode)
+ goto out_fail;
#ifdef CONFIG_SUN_OPENPROMFS_MODULE
if ((inode->i_ino >= PROC_OPENPROM_FIRST)
@@ -95,23 +153,29 @@
&& proc_openprom_use)
(*proc_openprom_use)(inode, 1);
#endif
- if (inode && inode->i_sb == s) {
- inode->u.generic_ip = (void *) de;
- if (de) {
- if (de->mode) {
- inode->i_mode = de->mode;
- inode->i_uid = de->uid;
- inode->i_gid = de->gid;
- }
- if (de->size)
- inode->i_size = de->size;
- if (de->ops)
- inode->i_op = de->ops;
- if (de->nlink)
- inode->i_nlink = de->nlink;
- if (de->fill_inode)
- de->fill_inode(inode);
+ /* N.B. How can this test ever fail?? */
+ if (inode->i_sb != sb)
+ printk("proc_get_inode: inode fubar\n");
+
+ inode->u.generic_ip = (void *) de;
+ if (de) {
+ if (de->mode) {
+ inode->i_mode = de->mode;
+ inode->i_uid = de->uid;
+ inode->i_gid = de->gid;
}
+ if (de->size)
+ inode->i_size = de->size;
+ if (de->ops)
+ inode->i_op = de->ops;
+ if (de->nlink)
+ inode->i_nlink = de->nlink;
+ /*
+ * The fill_inode routine should use this call
+ * to increment module counts, if necessary.
+ */
+ if (de->fill_inode)
+ de->fill_inode(inode, 1);
}
/*
* Fixup the root inode's nlink value
@@ -126,26 +190,40 @@
}
read_unlock(&tasklist_lock);
}
+out:
return inode;
+
+out_fail:
+ de_put(de);
+ goto out;
}
struct super_block *proc_read_super(struct super_block *s,void *data,
int silent)
{
+ struct inode * root_inode;
+
lock_super(s);
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->s_magic = PROC_SUPER_MAGIC;
s->s_op = &proc_sops;
+ root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
+ if (!root_inode)
+ goto out_no_root;
+ s->s_root = d_alloc_root(root_inode, NULL);
+ if (!s->s_root)
+ goto out_no_root;
+ parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
unlock_super(s);
- s->s_root = d_alloc_root(proc_get_inode(s, PROC_ROOT_INO, &proc_root), NULL);
- if (!s->s_root) {
- s->s_dev = 0;
- printk("get root inode failed\n");
- return NULL;
- }
- parse_options(data, &s->s_root->d_inode->i_uid, &s->s_root->d_inode->i_gid);
return s;
+
+out_no_root:
+ printk("proc_read_super: get root inode failed\n");
+ iput(root_inode);
+ s->s_dev = 0;
+ unlock_super(s);
+ return NULL;
}
int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov