Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=2793274298c4423d79701e9a8190f2940bf3c785
Commit:     2793274298c4423d79701e9a8190f2940bf3c785
Parent:     c5141e6d64ab5c48a5e31413c7a6cdda84ac1d52
Author:     Miklos Szeredi <[EMAIL PROTECTED]>
AuthorDate: Tue May 8 00:26:17 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue May 8 11:15:03 2007 -0700

    add file position info to proc
    
    Add support for finding out the current file position, open flags and
    possibly other info in the future.
    
    These new entries are added:
    
      /proc/PID/fdinfo/FD
      /proc/PID/task/TID/fdinfo/FD
    
    For each fd the information is provided in the following format:
    
    pos:        1234
    flags:      0100002
    
    [EMAIL PROTECTED]: make struct proc_fdinfo_file_operations static]
    Signed-off-by: Miklos Szeredi <[EMAIL PROTECTED]>
    Cc: Alexey Dobriyan <[EMAIL PROTECTED]>
    Signed-off-by: Adrian Bunk <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/proc/base.c |  132 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 114 insertions(+), 18 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index be94dde..0697fd0 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1238,7 +1238,10 @@ out:
        return ~0U;
 }
 
-static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+#define PROC_FDINFO_MAX 64
+
+static int proc_fd_info(struct inode *inode, struct dentry **dentry,
+                       struct vfsmount **mnt, char *info)
 {
        struct task_struct *task = get_proc_task(inode);
        struct files_struct *files = NULL;
@@ -1257,8 +1260,16 @@ static int proc_fd_link(struct inode *inode, struct 
dentry **dentry, struct vfsm
                spin_lock(&files->file_lock);
                file = fcheck_files(files, fd);
                if (file) {
-                       *mnt = mntget(file->f_path.mnt);
-                       *dentry = dget(file->f_path.dentry);
+                       if (mnt)
+                               *mnt = mntget(file->f_path.mnt);
+                       if (dentry)
+                               *dentry = dget(file->f_path.dentry);
+                       if (info)
+                               snprintf(info, PROC_FDINFO_MAX,
+                                        "pos:\t%lli\n"
+                                        "flags:\t0%o\n",
+                                        (long long) file->f_pos,
+                                        file->f_flags);
                        spin_unlock(&files->file_lock);
                        put_files_struct(files);
                        return 0;
@@ -1269,6 +1280,12 @@ static int proc_fd_link(struct inode *inode, struct 
dentry **dentry, struct vfsm
        return -ENOENT;
 }
 
+static int proc_fd_link(struct inode *inode, struct dentry **dentry,
+                       struct vfsmount **mnt)
+{
+       return proc_fd_info(inode, dentry, mnt, NULL);
+}
+
 static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
@@ -1364,7 +1381,9 @@ out_iput:
        goto out;
 }
 
-static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * 
dentry, struct nameidata *nd)
+static struct dentry *proc_lookupfd_common(struct inode *dir,
+                                          struct dentry *dentry,
+                                          instantiate_t instantiate)
 {
        struct task_struct *task = get_proc_task(dir);
        unsigned fd = name_to_int(dentry);
@@ -1375,23 +1394,15 @@ static struct dentry *proc_lookupfd(struct inode * dir, 
struct dentry * dentry,
        if (fd == ~0U)
                goto out;
 
-       result = proc_fd_instantiate(dir, dentry, task, &fd);
+       result = instantiate(dir, dentry, task, &fd);
 out:
        put_task_struct(task);
 out_no_task:
        return result;
 }
 
-static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t 
filldir,
-       struct task_struct *task, int fd)
-{
-       char name[PROC_NUMBUF];
-       int len = snprintf(name, sizeof(name), "%d", fd);
-       return proc_fill_cache(filp, dirent, filldir, name, len,
-                               proc_fd_instantiate, task, &fd);
-}
-
-static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
+static int proc_readfd_common(struct file * filp, void * dirent,
+                             filldir_t filldir, instantiate_t instantiate)
 {
        struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
@@ -1427,12 +1438,17 @@ static int proc_readfd(struct file * filp, void * 
dirent, filldir_t filldir)
                        for (fd = filp->f_pos-2;
                             fd < fdt->max_fds;
                             fd++, filp->f_pos++) {
+                               char name[PROC_NUMBUF];
+                               int len;
 
                                if (!fcheck_files(files, fd))
                                        continue;
                                rcu_read_unlock();
 
-                               if (proc_fd_fill_cache(filp, dirent, filldir, 
p, fd) < 0) {
+                               len = snprintf(name, sizeof(name), "%d", fd);
+                               if (proc_fill_cache(filp, dirent, filldir,
+                                                   name, len, instantiate,
+                                                   p, &fd) < 0) {
                                        rcu_read_lock();
                                        break;
                                }
@@ -1447,6 +1463,32 @@ out_no_task:
        return retval;
 }
 
+static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
+                                   struct nameidata *nd)
+{
+       return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
+}
+
+static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir)
+{
+       return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate);
+}
+
+static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
+                                     size_t len, loff_t *ppos)
+{
+       char tmp[PROC_FDINFO_MAX];
+       int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, NULL, tmp);
+       if (!err)
+               err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp));
+       return err;
+}
+
+static const struct file_operations proc_fdinfo_file_operations = {
+       .open           = nonseekable_open,
+       .read           = proc_fdinfo_read,
+};
+
 static const struct file_operations proc_fd_operations = {
        .read           = generic_read_dir,
        .readdir        = proc_readfd,
@@ -1478,6 +1520,58 @@ static const struct inode_operations 
proc_fd_inode_operations = {
        .setattr        = proc_setattr,
 };
 
+static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
+       struct dentry *dentry, struct task_struct *task, const void *ptr)
+{
+       unsigned fd = *(unsigned *)ptr;
+       struct inode *inode;
+       struct proc_inode *ei;
+       struct dentry *error = ERR_PTR(-ENOENT);
+
+       inode = proc_pid_make_inode(dir->i_sb, task);
+       if (!inode)
+               goto out;
+       ei = PROC_I(inode);
+       ei->fd = fd;
+       inode->i_mode = S_IFREG | S_IRUSR;
+       inode->i_fop = &proc_fdinfo_file_operations;
+       dentry->d_op = &tid_fd_dentry_operations;
+       d_add(dentry, inode);
+       /* Close the race of the process dying before we return the dentry */
+       if (tid_fd_revalidate(dentry, NULL))
+               error = NULL;
+
+ out:
+       return error;
+}
+
+static struct dentry *proc_lookupfdinfo(struct inode *dir,
+                                       struct dentry *dentry,
+                                       struct nameidata *nd)
+{
+       return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
+}
+
+static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
+{
+       return proc_readfd_common(filp, dirent, filldir,
+                                 proc_fdinfo_instantiate);
+}
+
+static const struct file_operations proc_fdinfo_operations = {
+       .read           = generic_read_dir,
+       .readdir        = proc_readfdinfo,
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+static const struct inode_operations proc_fdinfo_inode_operations = {
+       .lookup         = proc_lookupfdinfo,
+       .setattr        = proc_setattr,
+};
+
+
 static struct dentry *proc_pident_instantiate(struct inode *dir,
        struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
@@ -1888,6 +1982,7 @@ static const struct inode_operations 
proc_task_inode_operations;
 static const struct pid_entry tgid_base_stuff[] = {
        DIR("task",       S_IRUGO|S_IXUGO, task),
        DIR("fd",         S_IRUSR|S_IXUSR, fd),
+       DIR("fdinfo",     S_IRUSR|S_IXUSR, fdinfo),
        INF("environ",    S_IRUSR, pid_environ),
        INF("auxv",       S_IRUSR, pid_auxv),
        INF("status",     S_IRUGO, pid_status),
@@ -2041,7 +2136,7 @@ static struct dentry *proc_pid_instantiate(struct inode 
*dir,
        inode->i_op = &proc_tgid_base_inode_operations;
        inode->i_fop = &proc_tgid_base_operations;
        inode->i_flags|=S_IMMUTABLE;
-       inode->i_nlink = 4;
+       inode->i_nlink = 5;
 #ifdef CONFIG_SECURITY
        inode->i_nlink += 1;
 #endif
@@ -2171,6 +2266,7 @@ out_no_task:
  */
 static const struct pid_entry tid_base_stuff[] = {
        DIR("fd",        S_IRUSR|S_IXUSR, fd),
+       DIR("fdinfo",    S_IRUSR|S_IXUSR, fdinfo),
        INF("environ",   S_IRUSR, pid_environ),
        INF("auxv",      S_IRUSR, pid_auxv),
        INF("status",    S_IRUGO, pid_status),
@@ -2251,7 +2347,7 @@ static struct dentry *proc_task_instantiate(struct inode 
*dir,
        inode->i_op = &proc_tid_base_inode_operations;
        inode->i_fop = &proc_tid_base_operations;
        inode->i_flags|=S_IMMUTABLE;
-       inode->i_nlink = 3;
+       inode->i_nlink = 4;
 #ifdef CONFIG_SECURITY
        inode->i_nlink += 1;
 #endif
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to