]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/proc/generic.c
fs: remove dentry_lru_prune()
[karo-tx-linux.git] / fs / proc / generic.c
index 21e1a8f1659d097f455e196d0b775771d3904b2b..a2596afffae6dad430f8cb2727628e162c567876 100644 (file)
@@ -36,212 +36,6 @@ static int proc_match(unsigned int len, const char *name, struct proc_dir_entry
        return !memcmp(name, de->name, len);
 }
 
-/* buffer size is one page but our output routines use some slack for overruns */
-#define PROC_BLOCK_SIZE        (PAGE_SIZE - 1024)
-
-static ssize_t
-__proc_file_read(struct file *file, char __user *buf, size_t nbytes,
-              loff_t *ppos)
-{
-       struct inode * inode = file_inode(file);
-       char    *page;
-       ssize_t retval=0;
-       int     eof=0;
-       ssize_t n, count;
-       char    *start;
-       struct proc_dir_entry * dp;
-       unsigned long long pos;
-
-       /*
-        * Gaah, please just use "seq_file" instead. The legacy /proc
-        * interfaces cut loff_t down to off_t for reads, and ignore
-        * the offset entirely for writes..
-        */
-       pos = *ppos;
-       if (pos > MAX_NON_LFS)
-               return 0;
-       if (nbytes > MAX_NON_LFS - pos)
-               nbytes = MAX_NON_LFS - pos;
-
-       dp = PDE(inode);
-       if (!(page = (char*) __get_free_page(GFP_TEMPORARY)))
-               return -ENOMEM;
-
-       while ((nbytes > 0) && !eof) {
-               count = min_t(size_t, PROC_BLOCK_SIZE, nbytes);
-
-               start = NULL;
-               if (dp->read_proc) {
-                       /*
-                        * How to be a proc read function
-                        * ------------------------------
-                        * Prototype:
-                        *    int f(char *buffer, char **start, off_t offset,
-                        *          int count, int *peof, void *dat)
-                        *
-                        * Assume that the buffer is "count" bytes in size.
-                        *
-                        * If you know you have supplied all the data you
-                        * have, set *peof.
-                        *
-                        * You have three ways to return data:
-                        * 0) Leave *start = NULL.  (This is the default.)
-                        *    Put the data of the requested offset at that
-                        *    offset within the buffer.  Return the number (n)
-                        *    of bytes there are from the beginning of the
-                        *    buffer up to the last byte of data.  If the
-                        *    number of supplied bytes (= n - offset) is 
-                        *    greater than zero and you didn't signal eof
-                        *    and the reader is prepared to take more data
-                        *    you will be called again with the requested
-                        *    offset advanced by the number of bytes 
-                        *    absorbed.  This interface is useful for files
-                        *    no larger than the buffer.
-                        * 1) Set *start = an unsigned long value less than
-                        *    the buffer address but greater than zero.
-                        *    Put the data of the requested offset at the
-                        *    beginning of the buffer.  Return the number of
-                        *    bytes of data placed there.  If this number is
-                        *    greater than zero and you didn't signal eof
-                        *    and the reader is prepared to take more data
-                        *    you will be called again with the requested
-                        *    offset advanced by *start.  This interface is
-                        *    useful when you have a large file consisting
-                        *    of a series of blocks which you want to count
-                        *    and return as wholes.
-                        *    (Hack by Paul.Russell@rustcorp.com.au)
-                        * 2) Set *start = an address within the buffer.
-                        *    Put the data of the requested offset at *start.
-                        *    Return the number of bytes of data placed there.
-                        *    If this number is greater than zero and you
-                        *    didn't signal eof and the reader is prepared to
-                        *    take more data you will be called again with the
-                        *    requested offset advanced by the number of bytes
-                        *    absorbed.
-                        */
-                       n = dp->read_proc(page, &start, *ppos,
-                                         count, &eof, dp->data);
-               } else
-                       break;
-
-               if (n == 0)   /* end of file */
-                       break;
-               if (n < 0) {  /* error */
-                       if (retval == 0)
-                               retval = n;
-                       break;
-               }
-
-               if (start == NULL) {
-                       if (n > PAGE_SIZE)      /* Apparent buffer overflow */
-                               n = PAGE_SIZE;
-                       n -= *ppos;
-                       if (n <= 0)
-                               break;
-                       if (n > count)
-                               n = count;
-                       start = page + *ppos;
-               } else if (start < page) {
-                       if (n > PAGE_SIZE)      /* Apparent buffer overflow */
-                               n = PAGE_SIZE;
-                       if (n > count) {
-                               /*
-                                * Don't reduce n because doing so might
-                                * cut off part of a data block.
-                                */
-                               pr_warn("proc_file_read: count exceeded\n");
-                       }
-               } else /* start >= page */ {
-                       unsigned long startoff = (unsigned long)(start - page);
-                       if (n > (PAGE_SIZE - startoff)) /* buffer overflow? */
-                               n = PAGE_SIZE - startoff;
-                       if (n > count)
-                               n = count;
-               }
-               
-               n -= copy_to_user(buf, start < page ? page : start, n);
-               if (n == 0) {
-                       if (retval == 0)
-                               retval = -EFAULT;
-                       break;
-               }
-
-               *ppos += start < page ? (unsigned long)start : n;
-               nbytes -= n;
-               buf += n;
-               retval += n;
-       }
-       free_page((unsigned long) page);
-       return retval;
-}
-
-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_inode(file));
-       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 proc_dir_entry *pde = PDE(file_inode(file));
-       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... */
-               rv = pde->write_proc(file, buffer, count, pde->data);
-               pde_users_dec(pde);
-       }
-       return rv;
-}
-
-
-static loff_t
-proc_file_lseek(struct file *file, loff_t offset, int orig)
-{
-       loff_t retval = -EINVAL;
-       switch (orig) {
-       case 1:
-               offset += file->f_pos;
-       /* fallthrough */
-       case 0:
-               if (offset < 0 || offset > MAX_NON_LFS)
-                       break;
-               file->f_pos = retval = offset;
-       }
-       return retval;
-}
-
-static const struct file_operations proc_file_operations = {
-       .llseek         = proc_file_lseek,
-       .read           = proc_file_read,
-       .write          = proc_file_write,
-};
-
 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
 {
        struct inode *inode = dentry->d_inode;
@@ -371,7 +165,7 @@ void proc_free_inum(unsigned int inum)
 
 static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       nd_set_link(nd, PDE(dentry->d_inode)->data);
+       nd_set_link(nd, __PDE_DATA(dentry->d_inode));
        return NULL;
 }
 
@@ -541,19 +335,17 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
                return ret;
 
        if (S_ISDIR(dp->mode)) {
-               if (dp->proc_iops == NULL) {
-                       dp->proc_fops = &proc_dir_operations;
-                       dp->proc_iops = &proc_dir_inode_operations;
-               }
+               dp->proc_fops = &proc_dir_operations;
+               dp->proc_iops = &proc_dir_inode_operations;
                dir->nlink++;
        } else if (S_ISLNK(dp->mode)) {
-               if (dp->proc_iops == NULL)
-                       dp->proc_iops = &proc_link_inode_operations;
+               dp->proc_iops = &proc_link_inode_operations;
        } else if (S_ISREG(dp->mode)) {
-               if (dp->proc_fops == NULL)
-                       dp->proc_fops = &proc_file_operations;
-               if (dp->proc_iops == NULL)
-                       dp->proc_iops = &proc_file_inode_operations;
+               BUG_ON(dp->proc_fops == NULL);
+               dp->proc_iops = &proc_file_inode_operations;
+       } else {
+               WARN_ON(1);
+               return -EINVAL;
        }
 
        spin_lock(&proc_subdir_lock);
@@ -636,13 +428,17 @@ struct proc_dir_entry *proc_symlink(const char *name,
 }
 EXPORT_SYMBOL(proc_symlink);
 
-struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
-               struct proc_dir_entry *parent)
+struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
+               struct proc_dir_entry *parent, void *data)
 {
        struct proc_dir_entry *ent;
 
+       if (mode == 0)
+               mode = S_IRUGO | S_IXUGO;
+
        ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
        if (ent) {
+               ent->data = data;
                if (proc_register(parent, ent) < 0) {
                        kfree(ent);
                        ent = NULL;
@@ -650,82 +446,39 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
        }
        return ent;
 }
-EXPORT_SYMBOL(proc_mkdir_mode);
+EXPORT_SYMBOL_GPL(proc_mkdir_data);
 
-struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
-               struct proc_dir_entry *parent)
+struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
+                                      struct proc_dir_entry *parent)
 {
-       struct proc_dir_entry *ent;
-
-       ent = __proc_create(&parent, name, S_IFDIR | S_IRUGO | S_IXUGO, 2);
-       if (ent) {
-               ent->data = net;
-               if (proc_register(parent, ent) < 0) {
-                       kfree(ent);
-                       ent = NULL;
-               }
-       }
-       return ent;
+       return proc_mkdir_data(name, mode, parent, NULL);
 }
-EXPORT_SYMBOL_GPL(proc_net_mkdir);
+EXPORT_SYMBOL(proc_mkdir_mode);
 
 struct proc_dir_entry *proc_mkdir(const char *name,
                struct proc_dir_entry *parent)
 {
-       return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
+       return proc_mkdir_data(name, 0, parent, NULL);
 }
 EXPORT_SYMBOL(proc_mkdir);
 
-struct proc_dir_entry *create_proc_entry(const char *name, umode_t mode,
-                                        struct proc_dir_entry *parent)
-{
-       struct proc_dir_entry *ent;
-       nlink_t nlink;
-
-       if (S_ISDIR(mode)) {
-               if ((mode & S_IALLUGO) == 0)
-                       mode |= S_IRUGO | S_IXUGO;
-               nlink = 2;
-       } else {
-               if ((mode & S_IFMT) == 0)
-                       mode |= S_IFREG;
-               if ((mode & S_IALLUGO) == 0)
-                       mode |= S_IRUGO;
-               nlink = 1;
-       }
-
-       ent = __proc_create(&parent, name, mode, nlink);
-       if (ent) {
-               if (proc_register(parent, ent) < 0) {
-                       kfree(ent);
-                       ent = NULL;
-               }
-       }
-       return ent;
-}
-EXPORT_SYMBOL(create_proc_entry);
-
 struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
                                        struct proc_dir_entry *parent,
                                        const struct file_operations *proc_fops,
                                        void *data)
 {
        struct proc_dir_entry *pde;
-       nlink_t nlink;
+       if ((mode & S_IFMT) == 0)
+               mode |= S_IFREG;
 
-       if (S_ISDIR(mode)) {
-               if ((mode & S_IALLUGO) == 0)
-                       mode |= S_IRUGO | S_IXUGO;
-               nlink = 2;
-       } else {
-               if ((mode & S_IFMT) == 0)
-                       mode |= S_IFREG;
-               if ((mode & S_IALLUGO) == 0)
-                       mode |= S_IRUGO;
-               nlink = 1;
+       if (!S_ISREG(mode)) {
+               WARN_ON(1);     /* use proc_mkdir() */
+               return NULL;
        }
 
-       pde = __proc_create(&parent, name, mode, nlink);
+       if ((mode & S_IALLUGO) == 0)
+               mode |= S_IRUGO;
+       pde = __proc_create(&parent, name, mode, 1);
        if (!pde)
                goto out;
        pde->proc_fops = proc_fops;
@@ -739,6 +492,19 @@ out:
        return NULL;
 }
 EXPORT_SYMBOL(proc_create_data);
+void proc_set_size(struct proc_dir_entry *de, loff_t size)
+{
+       de->size = size;
+}
+EXPORT_SYMBOL(proc_set_size);
+
+void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
+{
+       de->uid = uid;
+       de->gid = gid;
+}
+EXPORT_SYMBOL(proc_set_user);
 
 static void free_proc_entry(struct proc_dir_entry *de)
 {
@@ -755,41 +521,6 @@ void pde_put(struct proc_dir_entry *pde)
                free_proc_entry(pde);
 }
 
-static void entry_rundown(struct proc_dir_entry *de)
-{
-       spin_lock(&de->pde_unload_lock);
-       /*
-        * Stop accepting new callers into module. If you're
-        * dynamically allocating ->proc_fops, save a pointer somewhere.
-        */
-       de->proc_fops = NULL;
-       /* Wait until all existing callers into module are done. */
-       if (de->pde_users > 0) {
-               DECLARE_COMPLETION_ONSTACK(c);
-
-               if (!de->pde_unload_completion)
-                       de->pde_unload_completion = &c;
-
-               spin_unlock(&de->pde_unload_lock);
-
-               wait_for_completion(de->pde_unload_completion);
-
-               spin_lock(&de->pde_unload_lock);
-       }
-
-       while (!list_empty(&de->pde_openers)) {
-               struct pde_opener *pdeo;
-
-               pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh);
-               list_del(&pdeo->lh);
-               spin_unlock(&de->pde_unload_lock);
-               pdeo->release(pdeo->inode, pdeo->file);
-               kfree(pdeo);
-               spin_lock(&de->pde_unload_lock);
-       }
-       spin_unlock(&de->pde_unload_lock);
-}
-
 /*
  * Remove a /proc entry and free it if it's not currently in use.
  */
@@ -821,7 +552,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
                return;
        }
 
-       entry_rundown(de);
+       proc_entry_rundown(de);
 
        if (S_ISDIR(de->mode))
                parent->nlink--;
@@ -870,7 +601,7 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
                }
                spin_unlock(&proc_subdir_lock);
 
-               entry_rundown(de);
+               proc_entry_rundown(de);
                next = de->parent;
                if (S_ISDIR(de->mode))
                        next->nlink--;
@@ -886,3 +617,23 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
        return 0;
 }
 EXPORT_SYMBOL(remove_proc_subtree);
+
+void *proc_get_parent_data(const struct inode *inode)
+{
+       struct proc_dir_entry *de = PDE(inode);
+       return de->parent->data;
+}
+EXPORT_SYMBOL_GPL(proc_get_parent_data);
+
+void proc_remove(struct proc_dir_entry *de)
+{
+       if (de)
+               remove_proc_subtree(de->name, de->parent);
+}
+EXPORT_SYMBOL(proc_remove);
+
+void *PDE_DATA(const struct inode *inode)
+{
+       return __PDE_DATA(inode);
+}
+EXPORT_SYMBOL(PDE_DATA);