#include <linux/stat.h>
#include <linux/module.h>
#include <linux/mount.h>
-#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/idr.h>
#include <linux/namei.h>
#define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
static ssize_t
-proc_file_read(struct file *file, char __user *buf, size_t nbytes,
+__proc_file_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)
{
struct inode * inode = file->f_path.dentry->d_inode;
}
static ssize_t
+proc_file_read(struct file *file, char __user *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ ssize_t rv = -EIO;
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ spin_unlock(&pde->pde_unload_lock);
+
+ rv = __proc_file_read(file, buf, nbytes, ppos);
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+static ssize_t
proc_file_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_path.dentry->d_inode;
- struct proc_dir_entry * dp;
-
- dp = PDE(inode);
-
- if (!dp->write_proc)
- return -EIO;
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ ssize_t rv = -EIO;
+
+ if (pde->write_proc) {
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ spin_unlock(&pde->pde_unload_lock);
- /* FIXME: does this routine need ppos? probably... */
- return dp->write_proc(file, buffer, count, dp->data);
+ /* FIXME: does this routine need ppos? probably... */
+ rv = pde->write_proc(file, buffer, count, pde->data);
+ pde_users_dec(pde);
+ }
+ return rv;
}
/*
* Return an inode number between PROC_DYNAMIC_FIRST and
* 0xffffffff, or zero on failure.
+ *
+ * Current inode allocations in the proc-fs (hex-numbers):
+ *
+ * 00000000 reserved
+ * 00000001-00000fff static entries (goners)
+ * 001 root-ino
+ *
+ * 00001000-00001fff unused
+ * 0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff
+ * 80000000-efffffff unused
+ * f0000000-ffffffff dynamic entries
+ *
+ * Goal:
+ * Once we split the thing into several virtual filesystems,
+ * we will get rid of magical ranges (and this comment, BTW).
*/
static unsigned int get_inode_number(void)
{
return 1;
}
-static struct dentry_operations proc_dentry_operations =
+static const struct dentry_operations proc_dentry_operations =
{
.d_delete = proc_delete_dentry,
};
struct inode *inode = NULL;
int error = -ENOENT;
- lock_kernel();
spin_lock(&proc_subdir_lock);
for (de = de->subdir; de ; de = de->next) {
if (de->namelen != dentry->d_name.len)
}
spin_unlock(&proc_subdir_lock);
out_unlock:
- unlock_kernel();
if (inode) {
dentry->d_op = &proc_dentry_operations;
struct inode *inode = filp->f_path.dentry->d_inode;
int ret = 0;
- lock_kernel();
-
ino = inode->i_ino;
i = filp->f_pos;
switch (i) {
spin_unlock(&proc_subdir_lock);
}
ret = 1;
-out: unlock_kernel();
+out:
return ret;
}
* the /proc directory.
*/
static const struct file_operations proc_dir_operations = {
+ .llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = proc_readdir,
};
for (tmp = dir->subdir; tmp; tmp = tmp->next)
if (strcmp(tmp->name, dp->name) == 0) {
- printk(KERN_WARNING "proc_dir_entry '%s/%s' already registered\n",
+ WARN(1, KERN_WARNING "proc_dir_entry '%s/%s' already registered\n",
dir->name, dp->name);
- dump_stack();
break;
}