X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=fs%2Fproc%2Fbase.c;h=a3a3eecef68946110f8f2641959af78eff7be428;hb=f27f0a045b79de5729d064497e21a70871f1d6fe;hp=634355e169869c3369959acbe5261542bb4cacb6;hpb=2ecc26b87a2b3e8650d3c7fe3fc85a8c73d5560d;p=powerpc.git diff --git a/fs/proc/base.c b/fs/proc/base.c index 634355e169..a3a3eecef6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -103,6 +104,7 @@ enum pid_directory_inos { PROC_TGID_MAPS, PROC_TGID_NUMA_MAPS, PROC_TGID_MOUNTS, + PROC_TGID_MOUNTSTATS, PROC_TGID_WCHAN, #ifdef CONFIG_MMU PROC_TGID_SMAPS, @@ -143,6 +145,7 @@ enum pid_directory_inos { PROC_TID_MAPS, PROC_TID_NUMA_MAPS, PROC_TID_MOUNTS, + PROC_TID_MOUNTSTATS, PROC_TID_WCHAN, #ifdef CONFIG_MMU PROC_TID_SMAPS, @@ -200,6 +203,7 @@ static struct pid_entry tgid_base_stuff[] = { E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), + E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR), #ifdef CONFIG_MMU E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), #endif @@ -530,12 +534,15 @@ static int proc_oom_score(struct task_struct *task, char *buffer) /* If the process being read is separated by chroot from the reading process, * don't let the reader access the threads. + * + * note: this does dput(root) and mntput(vfsmnt) on exit. */ static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt) { struct dentry *de, *base; struct vfsmount *our_vfsmnt, *mnt; int res = 0; + read_lock(¤t->fs->lock); our_vfsmnt = mntget(current->fs->rootmnt); base = dget(current->fs->root); @@ -545,11 +552,11 @@ static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt) de = root; mnt = vfsmnt; - while (vfsmnt != our_vfsmnt) { - if (vfsmnt == vfsmnt->mnt_parent) + while (mnt != our_vfsmnt) { + if (mnt == mnt->mnt_parent) goto out; - de = vfsmnt->mnt_mountpoint; - vfsmnt = vfsmnt->mnt_parent; + de = mnt->mnt_mountpoint; + mnt = mnt->mnt_parent; } if (!is_subdir(de, base)) @@ -560,7 +567,7 @@ exit: dput(base); mntput(our_vfsmnt); dput(root); - mntput(mnt); + mntput(vfsmnt); return res; out: spin_unlock(&vfsmount_lock); @@ -731,6 +738,38 @@ static struct file_operations proc_mounts_operations = { .poll = mounts_poll, }; +extern struct seq_operations mountstats_op; +static int mountstats_open(struct inode *inode, struct file *file) +{ + struct task_struct *task = proc_task(inode); + int ret = seq_open(file, &mountstats_op); + + if (!ret) { + struct seq_file *m = file->private_data; + struct namespace *namespace; + task_lock(task); + namespace = task->namespace; + if (namespace) + get_namespace(namespace); + task_unlock(task); + + if (namespace) + m->private = namespace; + else { + seq_release(inode, file); + ret = -EINVAL; + } + } + return ret; +} + +static struct file_operations proc_mountstats_operations = { + .open = mountstats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mounts_release, +}; + #define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ static ssize_t proc_info_read(struct file * file, char __user * buf, @@ -1729,6 +1768,10 @@ static struct dentry *proc_pident_lookup(struct inode *dir, inode->i_fop = &proc_smaps_operations; break; #endif + case PROC_TID_MOUNTSTATS: + case PROC_TGID_MOUNTSTATS: + inode->i_fop = &proc_mountstats_operations; + break; #ifdef CONFIG_SECURITY case PROC_TID_ATTR: inode->i_nlink = 2;