Miklos,

        You have removed the code that checked if the peer or
        master mount was in the same namespace before reporting their
        corresponding mount-ids. One downside of that approach is the
        user will see an mount_id in the output with no corresponding
        line to explain the details of the mount_id.  

        And reporting the mount-id of a mount is some other namespace
        could subtly mean information-leak?


        One other comment I had received offline from Steve French was
        that the patch did not consider the following case:

        "Have you thought about whether this could handle the case in which 
cifs mounts with 
        a relative path e.g. currently
                mount -t cifs //server/share /mnt

        can not be distinguished from
                mount -t cifs //server/share/subdirectory /mnt

        when you run the mount command (ie the cifs "prefixpath" in this case 
        "/subdirectory" is not displayed)"


thanks for driving this patch further and sorry; have not been active on this 
work for a while,
RP


On Sat, 2008-01-19 at 12:05 +0100, Miklos Szeredi wrote:
> Seems, most people would be happier with a new file, instead of
> extending /proc/mounts.
> 
> This patch is the first attempt at doing that, as well as fixing the
> issues found in the previous submission.
> 
> Thanks,
> Miklos
> 
> ---
> From: Ram Pai <[EMAIL PROTECTED]>
> 
> /proc/mounts in its current state fail to disambiguate bind mounts, especially
> when the bind mount is subrooted. Also it does not capture propagation state 
> of
> the mounts(shared-subtree). The following patch addresses the problem.
> 
> The patch adds '/proc/<pid>/mountinfo' which contains a superset of
> the fields in '/proc/<pid>/mounts'. The following additional fields
> are added:
> 
> mntid -- is a unique identifier of the mount
> parent -- the id of the parent mount
> major:minor -- value of st_dev for files on that filesystem
> dir -- the subdir in the filesystem which forms the root of this mount
> propagation-type in the form of <propagation_flag>[:<mntid>][,...]
>       note: 'shared' flag is followed by the mntid of its peer mount
>             'slave' flag is followed by the mntid of its master mount
>             'private' flag stands by itself
>             'unbindable' flag stands by itself
> 
> Also mount options are split into two fileds, the first containing the
> per mount flags, the second the per super block options.
> 
> Here is a sample cat /proc/mounts after execution the following commands:
> 
> mount --bind /mnt /mnt
> mount --make-shared /mnt
> mount --bind /mnt/1 /var
> mount --make-slave /var
> mount --make-shared /var
> mount --bind /var/abc /tmp
> mount --make-unbindable /proc
> 
> 2 2 0:1 rootfs rootfs / / rw rw private
> 16 2 98:0 ext2 /dev/root / / rw rw private
> 17 16 0:3 proc /proc / /proc rw rw unbindable
> 18 16 0:10 devpts devpts /dev/pts / rw rw private
> 19 16 98:0 ext2 /dev/root /mnt /mnt rw rw shared:19
> 20 16 98:0 ext2 /dev/root /mnt/1 /var rw rw shared:21,slave:19
> 21 16 98:0 ext2 /dev/root /mnt/1/abc /tmp rw rw shared:20,slave:19
> 
> For example, the last line indicates that:
> 
> 1) The mount is a shared mount.
> 2) Its peer mount of mount with id 20
> 3) It is also a slave mount of the master-mount with the id  19
> 4) The filesystem on device with major/minor number 98:0 and subdirectory
>       mnt/1/abc makes the root directory of this mount.
> 5) And finally the mount with id 16 is its parent.
> 
> 
> [EMAIL PROTECTED]:
> 
> - new file, rearrange fields
> - for mount ID's use IDA (from the IDR library) instead of a 32bit
>   counter, which could overflow
> - print canonical ID's (smallest one within the peer group) for peers
>   and master, this is more useful, than a random ID within the same namespace
> - fix a couple of small bugs
> - remove inlines
> - style fixes
> 
> Signed-off-by: Ram Pai <[EMAIL PROTECTED]>
> Signed-off-by: Miklos Szeredi <[EMAIL PROTECTED]>
> ---
> 
> Index: linux/fs/dcache.c
> ===================================================================
> --- linux.orig/fs/dcache.c    2008-01-18 19:21:38.000000000 +0100
> +++ linux/fs/dcache.c 2008-01-18 19:22:27.000000000 +0100
> @@ -1890,6 +1890,60 @@ char *dynamic_dname(struct dentry *dentr
>       return memcpy(buffer, temp, sz);
>  }
> 
> +static int prepend(char **buffer, int *buflen, const char *str,
> +                       int namelen)
> +{
> +     *buflen -= namelen;
> +     if (*buflen < 0)
> +             return 1;
> +     *buffer -= namelen;
> +     memcpy(*buffer, str, namelen);
> +     return 0;
> +}
> +
> +/*
> + * Write full pathname from the root of the filesystem into the buffer.
> + */
> +char *dentry_path(struct dentry *dentry, char *buf, int buflen)
> +{
> +     char *end = buf + buflen;
> +     char *retval;
> +
> +     spin_lock(&dcache_lock);
> +     prepend(&end, &buflen, "\0", 1);
> +     if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
> +             if (prepend(&end, &buflen, "//deleted", 9))
> +                     goto Elong;
> +     }
> +     if (buflen < 1)
> +             goto Elong;
> +     /* Get '/' right */
> +     retval = end-1;
> +     *retval = '/';
> +
> +     for (;;) {
> +             struct dentry *parent;
> +             if (IS_ROOT(dentry))
> +                     break;
> +
> +             parent = dentry->d_parent;
> +             prefetch(parent);
> +
> +             if (prepend(&end, &buflen, dentry->d_name.name,
> +                             dentry->d_name.len) ||
> +                 prepend(&end, &buflen, "/", 1))
> +                     goto Elong;
> +
> +             retval = end;
> +             dentry = parent;
> +     }
> +     spin_unlock(&dcache_lock);
> +     return retval;
> +Elong:
> +     spin_unlock(&dcache_lock);
> +     return ERR_PTR(-ENAMETOOLONG);
> +}
> +
>  /*
>   * NOTE! The user-level library version returns a
>   * character pointer. The kernel system call just
> Index: linux/fs/namespace.c
> ===================================================================
> --- linux.orig/fs/namespace.c 2008-01-18 19:21:38.000000000 +0100
> +++ linux/fs/namespace.c      2008-01-18 23:39:35.000000000 +0100
> @@ -27,6 +27,7 @@
>  #include <linux/mount.h>
>  #include <linux/ramfs.h>
>  #include <linux/log2.h>
> +#include <linux/idr.h>
>  #include <asm/uaccess.h>
>  #include <asm/unistd.h>
>  #include "pnode.h"
> @@ -39,6 +40,7 @@
>  __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
> 
>  static int event;
> +static DEFINE_IDA(mnt_id_ida);
> 
>  static struct list_head *mount_hashtable __read_mostly;
>  static struct kmem_cache *mnt_cache __read_mostly;
> @@ -58,10 +60,41 @@ static inline unsigned long hash(struct 
> 
>  #define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16)
> 
> +static int mnt_alloc_id(struct vfsmount *mnt)
> +{
> +     int res;
> +
> + retry:
> +     spin_lock(&vfsmount_lock);
> +     res = ida_get_new(&mnt_id_ida, &mnt->mnt_id);
> +     spin_unlock(&vfsmount_lock);
> +     if (res == -EAGAIN) {
> +             if (ida_pre_get(&mnt_id_ida, GFP_KERNEL))
> +                     goto retry;
> +             res = -ENOMEM;
> +     }
> +     return res;
> +}
> +
> +static void mnt_free_id(struct vfsmount *mnt)
> +{
> +     spin_lock(&vfsmount_lock);
> +     ida_remove(&mnt_id_ida, mnt->mnt_id);
> +     spin_unlock(&vfsmount_lock);
> +}
> +
>  struct vfsmount *alloc_vfsmnt(const char *name)
>  {
>       struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
>       if (mnt) {
> +             int err;
> +
> +             err = mnt_alloc_id(mnt);
> +             if (err) {
> +                     kmem_cache_free(mnt_cache, mnt);
> +                     return NULL;
> +             }
> +
>               atomic_set(&mnt->mnt_count, 1);
>               INIT_LIST_HEAD(&mnt->mnt_hash);
>               INIT_LIST_HEAD(&mnt->mnt_child);
> @@ -338,6 +371,7 @@ EXPORT_SYMBOL(simple_set_mnt);
>  void free_vfsmnt(struct vfsmount *mnt)
>  {
>       kfree(mnt->mnt_devname);
> +     mnt_free_id(mnt);
>       kmem_cache_free(mnt_cache, mnt);
>  }
> 
> @@ -601,28 +635,29 @@ static inline void mangle(struct seq_fil
>       seq_escape(m, s, " \t\n\\");
>  }
> 
> +static struct proc_fs_info {
> +     int flag;
> +     char *str;
> +} fs_info[] = {
> +     { MS_SYNCHRONOUS, ",sync" },
> +     { MS_DIRSYNC, ",dirsync" },
> +     { MS_MANDLOCK, ",mand" },
> +     { 0, NULL }
> +};
> +static struct proc_fs_info mnt_info[] = {
> +     { MNT_NOSUID, ",nosuid" },
> +     { MNT_NODEV, ",nodev" },
> +     { MNT_NOEXEC, ",noexec" },
> +     { MNT_NOATIME, ",noatime" },
> +     { MNT_NODIRATIME, ",nodiratime" },
> +     { MNT_RELATIME, ",relatime" },
> +     { 0, NULL }
> +};
> +
>  static int show_vfsmnt(struct seq_file *m, void *v)
>  {
>       struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
>       int err = 0;
> -     static struct proc_fs_info {
> -             int flag;
> -             char *str;
> -     } fs_info[] = {
> -             { MS_SYNCHRONOUS, ",sync" },
> -             { MS_DIRSYNC, ",dirsync" },
> -             { MS_MANDLOCK, ",mand" },
> -             { 0, NULL }
> -     };
> -     static struct proc_fs_info mnt_info[] = {
> -             { MNT_NOSUID, ",nosuid" },
> -             { MNT_NODEV, ",nodev" },
> -             { MNT_NOEXEC, ",noexec" },
> -             { MNT_NOATIME, ",noatime" },
> -             { MNT_NODIRATIME, ",nodiratime" },
> -             { MNT_RELATIME, ",relatime" },
> -             { 0, NULL }
> -     };
>       struct proc_fs_info *fs_infop;
>       struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
> 
> @@ -657,6 +692,63 @@ struct seq_operations mounts_op = {
>       .show   = show_vfsmnt
>  };
> 
> +static int show_mountinfo(struct seq_file *m, void *v)
> +{
> +     struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
> +     struct super_block *sb = mnt->mnt_sb;
> +     struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
> +     struct proc_fs_info *fs_infop;
> +     int err = 0;
> +
> +     seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id,
> +                MAJOR(sb->s_dev), MINOR(sb->s_dev));
> +     mangle(m, sb->s_type->name);
> +     if (sb->s_subtype && sb->s_subtype[0]) {
> +             seq_putc(m, '.');
> +             mangle(m, sb->s_subtype);
> +     }
> +     seq_putc(m, ' ');
> +     mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
> +     seq_putc(m, ' ');
> +     seq_dentry(m, mnt->mnt_root, " \t\n\\");
> +     seq_putc(m, ' ');
> +     seq_path(m, &mnt_path, " \t\n\\");
> +     seq_putc(m, ' ');
> +     seq_puts(m, mnt->mnt_flags & MNT_READONLY ? "ro" : "rw");
> +     for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
> +             if (mnt->mnt_flags & fs_infop->flag)
> +                     seq_puts(m, fs_infop->str);
> +     }
> +     seq_putc(m, ' ');
> +     seq_puts(m, sb->s_flags & MS_RDONLY ? "ro" : "rw");
> +     for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
> +             if (sb->s_flags & fs_infop->flag)
> +                     seq_puts(m, fs_infop->str);
> +     }
> +     if (sb->s_op->show_options)
> +             err = sb->s_op->show_options(m, mnt);
> +     if (IS_MNT_SHARED(mnt)) {
> +             seq_printf(m, " shared:%i", get_peer_group_id(mnt));
> +             if (IS_MNT_SLAVE(mnt))
> +                     seq_printf(m, ",slave:%i", get_master_id(mnt));
> +     } else if (IS_MNT_SLAVE(mnt)) {
> +             seq_printf(m, " slave:%i", get_master_id(mnt));
> +     } else if (IS_MNT_UNBINDABLE(mnt)) {
> +             seq_printf(m, " unbindable");
> +     } else {
> +             seq_printf(m, " private");
> +     }
> +     seq_putc(m, '\n');
> +     return err;
> +}
> +
> +struct seq_operations mountinfo_op = {
> +     .start  = m_start,
> +     .next   = m_next,
> +     .stop   = m_stop,
> +     .show   = show_mountinfo,
> +};
> +
>  static int show_vfsstat(struct seq_file *m, void *v)
>  {
>       struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
> Index: linux/fs/seq_file.c
> ===================================================================
> --- linux.orig/fs/seq_file.c  2008-01-18 19:21:38.000000000 +0100
> +++ linux/fs/seq_file.c       2008-01-18 19:22:27.000000000 +0100
> @@ -349,28 +349,40 @@ int seq_printf(struct seq_file *m, const
>  }
>  EXPORT_SYMBOL(seq_printf);
> 
> +static char *mangle_path(char *s, char *p, char *esc)
> +{
> +     while (s <= p) {
> +             char c = *p++;
> +             if (!c) {
> +                     return s;
> +             } else if (!strchr(esc, c)) {
> +                     *s++ = c;
> +             } else if (s + 4 > p) {
> +                     break;
> +             } else {
> +                     *s++ = '\\';
> +                     *s++ = '0' + ((c & 0300) >> 6);
> +                     *s++ = '0' + ((c & 070) >> 3);
> +                     *s++ = '0' + (c & 07);
> +             }
> +     }
> +     return NULL;
> +}
> +
> +/*
> + * return the absolute path of 'dentry' residing in mount 'mnt'.
> + */
>  int seq_path(struct seq_file *m, struct path *path, char *esc)
>  {
>       if (m->count < m->size) {
>               char *s = m->buf + m->count;
>               char *p = d_path(path, s, m->size - m->count);
>               if (!IS_ERR(p)) {
> -                     while (s <= p) {
> -                             char c = *p++;
> -                             if (!c) {
> -                                     p = m->buf + m->count;
> -                                     m->count = s - m->buf;
> -                                     return s - p;
> -                             } else if (!strchr(esc, c)) {
> -                                     *s++ = c;
> -                             } else if (s + 4 > p) {
> -                                     break;
> -                             } else {
> -                                     *s++ = '\\';
> -                                     *s++ = '0' + ((c & 0300) >> 6);
> -                                     *s++ = '0' + ((c & 070) >> 3);
> -                                     *s++ = '0' + (c & 07);
> -                             }
> +                     s = mangle_path(s, p, esc);
> +                     if (s) {
> +                             p = m->buf + m->count;
> +                             m->count = s - m->buf;
> +                             return s - p;
>                       }
>               }
>       }
> @@ -379,6 +391,28 @@ int seq_path(struct seq_file *m, struct 
>  }
>  EXPORT_SYMBOL(seq_path);
> 
> +/*
> + * returns the path of the 'dentry' from the root of its filesystem.
> + */
> +int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc)
> +{
> +     if (m->count < m->size) {
> +             char *s = m->buf + m->count;
> +             char *p = dentry_path(dentry, s, m->size - m->count);
> +             if (!IS_ERR(p)) {
> +                     s = mangle_path(s, p, esc);
> +                     if (s) {
> +                             p = m->buf + m->count;
> +                             m->count = s - m->buf;
> +                             return s - p;
> +                     }
> +             }
> +     }
> +     m->count = m->size;
> +     return -1;
> +}
> +EXPORT_SYMBOL(seq_dentry);
> +
>  static void *single_start(struct seq_file *p, loff_t *pos)
>  {
>       return NULL + (*pos == 0);
> Index: linux/include/linux/dcache.h
> ===================================================================
> --- linux.orig/include/linux/dcache.h 2008-01-18 19:21:38.000000000 +0100
> +++ linux/include/linux/dcache.h      2008-01-18 19:22:27.000000000 +0100
> @@ -302,6 +302,7 @@ extern int d_validate(struct dentry *, s
>  extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
> 
>  extern char *d_path(struct path *, char *, int);
> +extern char *dentry_path(struct dentry *, char *, int);
> 
>  /* Allocation counts.. */
> 
> Index: linux/include/linux/seq_file.h
> ===================================================================
> --- linux.orig/include/linux/seq_file.h       2008-01-18 19:21:38.000000000 
> +0100
> +++ linux/include/linux/seq_file.h    2008-01-18 19:22:27.000000000 +0100
> @@ -10,6 +10,7 @@ struct seq_operations;
>  struct file;
>  struct path;
>  struct inode;
> +struct dentry;
> 
>  struct seq_file {
>       char *buf;
> @@ -43,6 +44,7 @@ int seq_printf(struct seq_file *, const 
>       __attribute__ ((format (printf,2,3)));
> 
>  int seq_path(struct seq_file *, struct path *, char *);
> +int seq_dentry(struct seq_file *, struct dentry *, char *);
> 
>  int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
>  int single_release(struct inode *, struct file *);
> Index: linux/fs/pnode.c
> ===================================================================
> --- linux.orig/fs/pnode.c     2008-01-18 19:21:38.000000000 +0100
> +++ linux/fs/pnode.c  2008-01-18 19:22:27.000000000 +0100
> @@ -27,6 +27,41 @@ static inline struct vfsmount *next_slav
>       return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave);
>  }
> 
> +static int __peer_group_id(struct vfsmount *mnt)
> +{
> +     struct vfsmount *m;
> +     int id = mnt->mnt_id;
> +
> +     for (m = next_peer(mnt); m != mnt; m = next_peer(m))
> +             id = min(id, m->mnt_id);
> +
> +     return id;
> +}
> +
> +/* return the smallest ID within the peer group */
> +int get_peer_group_id(struct vfsmount *mnt)
> +{
> +     int id;
> +
> +     spin_lock(&vfsmount_lock);
> +     id = __peer_group_id(mnt);
> +     spin_unlock(&vfsmount_lock);
> +
> +     return id;
> +}
> +
> +/* return the smallest ID within the master's peer group */
> +int get_master_id(struct vfsmount *mnt)
> +{
> +     int id;
> +
> +     spin_lock(&vfsmount_lock);
> +     id = __peer_group_id(mnt->mnt_master);
> +     spin_unlock(&vfsmount_lock);
> +
> +     return id;
> +}
> +
>  static int do_make_slave(struct vfsmount *mnt)
>  {
>       struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master;
> Index: linux/fs/pnode.h
> ===================================================================
> --- linux.orig/fs/pnode.h     2008-01-18 19:21:38.000000000 +0100
> +++ linux/fs/pnode.h  2008-01-18 23:39:35.000000000 +0100
> @@ -35,4 +35,6 @@ int propagate_mnt(struct vfsmount *, str
>               struct list_head *);
>  int propagate_umount(struct list_head *);
>  int propagate_mount_busy(struct vfsmount *, int);
> +int get_peer_group_id(struct vfsmount *);
> +int get_master_id(struct vfsmount *);
>  #endif /* _LINUX_PNODE_H */
> Index: linux/include/linux/mount.h
> ===================================================================
> --- linux.orig/include/linux/mount.h  2008-01-18 19:21:38.000000000 +0100
> +++ linux/include/linux/mount.h       2008-01-18 23:39:35.000000000 +0100
> @@ -56,6 +56,7 @@ struct vfsmount {
>       struct list_head mnt_slave;     /* slave list entry */
>       struct vfsmount *mnt_master;    /* slave is on master->mnt_slave_list */
>       struct mnt_namespace *mnt_ns;   /* containing namespace */
> +     int mnt_id;                     /* mount identifier */
>       /*
>        * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
>        * to let these frequently modified fields in a separate cache line
> Index: linux/fs/proc/base.c
> ===================================================================
> --- linux.orig/fs/proc/base.c 2008-01-18 19:21:38.000000000 +0100
> +++ linux/fs/proc/base.c      2008-01-18 19:22:27.000000000 +0100
> @@ -435,13 +435,13 @@ static const struct inode_operations pro
>       .setattr        = proc_setattr,
>  };
> 
> -extern struct seq_operations mounts_op;
>  struct proc_mounts {
>       struct seq_file m;
>       int event;
>  };
> 
> -static int mounts_open(struct inode *inode, struct file *file)
> +static int mounts_open_common(struct inode *inode, struct file *file,
> +                           struct seq_operations *op)
>  {
>       struct task_struct *task = get_proc_task(inode);
>       struct nsproxy *nsp;
> @@ -467,7 +467,7 @@ static int mounts_open(struct inode *ino
>               p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
>               if (p) {
>                       file->private_data = &p->m;
> -                     ret = seq_open(file, &mounts_op);
> +                     ret = seq_open(file, op);
>                       if (!ret) {
>                               p->m.private = ns;
>                               p->event = ns->event;
> @@ -506,6 +506,11 @@ static unsigned mounts_poll(struct file 
>       return res;
>  }
> 
> +static int mounts_open(struct inode *inode, struct file *file)
> +{
> +     return mounts_open_common(inode, file, &mounts_op);
> +}
> +
>  static const struct file_operations proc_mounts_operations = {
>       .open           = mounts_open,
>       .read           = seq_read,
> @@ -514,38 +519,22 @@ static const struct file_operations proc
>       .poll           = mounts_poll,
>  };
> 
> -extern struct seq_operations mountstats_op;
> -static int mountstats_open(struct inode *inode, struct file *file)
> +static int mountinfo_open(struct inode *inode, struct file *file)
>  {
> -     int ret = seq_open(file, &mountstats_op);
> -
> -     if (!ret) {
> -             struct seq_file *m = file->private_data;
> -             struct nsproxy *nsp;
> -             struct mnt_namespace *mnt_ns = NULL;
> -             struct task_struct *task = get_proc_task(inode);
> -
> -             if (task) {
> -                     rcu_read_lock();
> -                     nsp = task_nsproxy(task);
> -                     if (nsp) {
> -                             mnt_ns = nsp->mnt_ns;
> -                             if (mnt_ns)
> -                                     get_mnt_ns(mnt_ns);
> -                     }
> -                     rcu_read_unlock();
> +     return mounts_open_common(inode, file, &mountinfo_op);
> +}
> 
> -                     put_task_struct(task);
> -             }
> +static const struct file_operations proc_mountinfo_operations = {
> +     .open           = mountinfo_open,
> +     .read           = seq_read,
> +     .llseek         = seq_lseek,
> +     .release        = mounts_release,
> +     .poll           = mounts_poll,
> +};
> 
> -             if (mnt_ns)
> -                     m->private = mnt_ns;
> -             else {
> -                     seq_release(inode, file);
> -                     ret = -EINVAL;
> -             }
> -     }
> -     return ret;
> +static int mountstats_open(struct inode *inode, struct file *file)
> +{
> +     return mounts_open_common(inode, file, &mountstats_op);
>  }
> 
>  static const struct file_operations proc_mountstats_operations = {
> @@ -2220,6 +2209,7 @@ static const struct pid_entry tgid_base_
>       LNK("root",       root),
>       LNK("exe",        exe),
>       REG("mounts",     S_IRUGO, mounts),
> +     REG("mountinfo",  S_IRUGO, mountinfo),
>       REG("mountstats", S_IRUSR, mountstats),
>  #ifdef CONFIG_PROC_PAGE_MONITOR
>       REG("clear_refs", S_IWUSR, clear_refs),
> @@ -2548,6 +2538,7 @@ static const struct pid_entry tid_base_s
>       LNK("root",      root),
>       LNK("exe",       exe),
>       REG("mounts",    S_IRUGO, mounts),
> +     REG("mountinfo",  S_IRUGO, mountinfo),
>  #ifdef CONFIG_PROC_PAGE_MONITOR
>       REG("clear_refs", S_IWUSR, clear_refs),
>       REG("smaps",     S_IRUGO, smaps),
> Index: linux/include/linux/mnt_namespace.h
> ===================================================================
> --- linux.orig/include/linux/mnt_namespace.h  2008-01-18 19:21:38.000000000 
> +0100
> +++ linux/include/linux/mnt_namespace.h       2008-01-18 19:22:27.000000000 
> +0100
> @@ -37,5 +37,9 @@ static inline void get_mnt_ns(struct mnt
>       atomic_inc(&ns->count);
>  }
> 
> +extern struct seq_operations mounts_op;
> +extern struct seq_operations mountinfo_op;
> +extern struct seq_operations mountstats_op;
> +
>  #endif
>  #endif
> Index: linux/fs/proc/proc_misc.c
> ===================================================================
> --- linux.orig/fs/proc/proc_misc.c    2008-01-18 19:21:38.000000000 +0100
> +++ linux/fs/proc/proc_misc.c 2008-01-19 11:56:33.000000000 +0100
> @@ -980,6 +980,7 @@ void __init proc_misc_init(void)
>               create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
> 
>       proc_symlink("mounts", NULL, "self/mounts");
> +     proc_symlink("mountinfo", NULL, "self/mountinfo");
> 
>       /* And now for trickier ones */
>  #ifdef CONFIG_PRINTK

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to