lkml.org 
[lkml]   [2005]   [May]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[RFC][PATCH] /proc/dead_mounts support (Was: [RFC][PATCH] rbind across ...)
    From
    Date
    > I have a better idea:
    >
    > - create a "dead_mounts" namespace.
    > - chain each detached mount's ->mnt_list on dead_mounts->list
    > - set mnt_namespace to dead_mounts
    > - export the list via proc through the usual mount list interface
    >
    > The last would be a nice bonus: I've always wanted to see the list of
    > detached, but not-yet destroyed mounts.

    Here's a patch that does this. It needs all the other namespace
    patches, so I made a diff against 2.6.12-rc4-mm2 in case anybody wants
    to try it:

    http://www.inf.bme.hu/~mszeredi/patches/patch-2.6.12-rc4-mm2-szm1

    It works for me(TM).

    Miklos

    Index: linux/include/linux/proc_fs.h
    ===================================================================
    --- linux.orig/include/linux/proc_fs.h 2005-05-22 16:09:37.000000000 +0200
    +++ linux/include/linux/proc_fs.h 2005-05-22 16:09:45.000000000 +0200
    @@ -127,6 +127,7 @@ extern struct dentry *proc_lookup(struct
    extern struct file_operations proc_kcore_operations;
    extern struct file_operations proc_kmsg_operations;
    extern struct file_operations ppc_htab_operations;
    +extern struct file_operations proc_dead_mounts_operations;

    /*
    * proc_tty.c
    Index: linux/fs/proc/proc_misc.c
    ===================================================================
    --- linux.orig/fs/proc/proc_misc.c 2005-05-22 16:09:37.000000000 +0200
    +++ linux/fs/proc/proc_misc.c 2005-05-22 16:09:45.000000000 +0200
    @@ -652,6 +652,9 @@ void __init proc_misc_init(void)
    create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);

    proc_symlink("mounts", NULL, "self/mounts");
    + entry = create_proc_entry("dead_mounts", S_IRUSR, &proc_root);
    + if (entry)
    + entry->proc_fops = &proc_dead_mounts_operations;

    /* And now for trickier ones */
    entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
    Index: linux/fs/namespace.c
    ===================================================================
    --- linux.orig/fs/namespace.c 2005-05-22 16:09:45.000000000 +0200
    +++ linux/fs/namespace.c 2005-05-22 16:12:23.000000000 +0200
    @@ -42,6 +42,7 @@ static inline int sysfs_init(void)
    static struct list_head *mount_hashtable;
    static int hash_mask, hash_bits;
    static kmem_cache_t *mnt_cache;
    +static struct namespace *dead_mounts;

    static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
    {
    @@ -175,6 +176,8 @@ clone_mnt(struct vfsmount *old, struct d
    void __mntput(struct vfsmount *mnt)
    {
    struct super_block *sb = mnt->mnt_sb;
    + list_del(&mnt->mnt_list);
    + spin_unlock(&vfsmount_lock);
    dput(mnt->mnt_root);
    free_vfsmnt(mnt);
    deactivate_super(sb);
    @@ -240,7 +243,10 @@ static int show_vfsmnt(struct seq_file *

    mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
    seq_putc(m, ' ');
    - seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
    + if (mnt->mnt_namespace != dead_mounts)
    + seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
    + else
    + seq_puts(m, "(detached)");
    seq_putc(m, ' ');
    mangle(m, mnt->mnt_sb->s_type->name);
    seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
    @@ -265,6 +271,71 @@ struct seq_operations mounts_op = {
    .show = show_vfsmnt
    };

    +/* /proc/dead_mounts needs slightly different handling than above */
    +static void *dead_m_start(struct seq_file *m, loff_t *pos)
    +{
    + struct namespace *n = m->private;
    + struct vfsmount *res = NULL;
    + struct list_head *p;
    + loff_t l = *pos;
    +
    + spin_lock(&vfsmount_lock);
    + list_for_each(p, &n->list)
    + if (!l--) {
    + res = mntget(list_entry(p, struct vfsmount, mnt_list));
    + break;
    + }
    + spin_unlock(&vfsmount_lock);
    + return res;
    +}
    +
    +static void *dead_m_next(struct seq_file *m, void *v, loff_t *pos)
    +{
    + struct namespace *n = m->private;
    + struct vfsmount *curr = v;
    + struct vfsmount *res = NULL;
    + struct list_head *p;
    +
    + (*pos)++;
    + spin_lock(&vfsmount_lock);
    + p = curr->mnt_list.next;
    + if (p != &n->list)
    + res = mntget(list_entry(p, struct vfsmount, mnt_list));
    + spin_unlock(&vfsmount_lock);
    + mntput(curr);
    + return res;
    +}
    +
    +static void dead_m_stop(struct seq_file *m, void *v)
    +{
    + struct vfsmount *curr = v;
    + mntput(curr);
    +}
    +
    +static struct seq_operations dead_mounts_op = {
    + .start = dead_m_start,
    + .next = dead_m_next,
    + .stop = dead_m_stop,
    + .show = show_vfsmnt
    +};
    +
    +static int dead_mounts_open(struct inode *inode, struct file *file)
    +{
    + int ret = seq_open(file, &dead_mounts_op);
    + if (!ret) {
    + struct seq_file *m = file->private_data;
    + m->private = dead_mounts;
    + }
    + return ret;
    +}
    +
    +struct file_operations proc_dead_mounts_operations = {
    + .open = dead_mounts_open,
    + .read = seq_read,
    + .llseek = seq_lseek,
    + .release = seq_release,
    +};
    +
    /**
    * may_umount_tree - check if a mount tree is busy
    * @mnt: root of mount tree
    @@ -343,14 +414,13 @@ static void umount_tree(struct vfsmount
    LIST_HEAD(kill);

    for (p = mnt; p; p = next_mnt(p, mnt)) {
    - list_del(&p->mnt_list);
    - list_add(&p->mnt_list, &kill);
    - p->mnt_namespace = NULL;
    + list_move(&p->mnt_list, &kill);
    + p->mnt_namespace = dead_mounts;
    }

    while (!list_empty(&kill)) {
    mnt = list_entry(kill.next, struct vfsmount, mnt_list);
    - list_del_init(&mnt->mnt_list);
    + list_move_tail(&mnt->mnt_list, &dead_mounts->list);
    list_del_init(&mnt->mnt_fslink);
    if (mnt->mnt_parent == mnt) {
    spin_unlock(&vfsmount_lock);
    @@ -447,7 +517,7 @@ static int do_umount(struct vfsmount *mn
    }
    retval = -EBUSY;
    if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
    - if (!list_empty(&mnt->mnt_list))
    + if (mnt->mnt_namespace != dead_mounts)
    umount_tree(mnt);
    retval = 0;
    }
    @@ -842,8 +912,8 @@ static void expire_mount(struct vfsmount
    struct nameidata old_nd;

    /* delete from the namespace */
    - list_del_init(&mnt->mnt_list);
    - mnt->mnt_namespace = NULL;
    + list_move_tail(&mnt->mnt_list, &dead_mounts->list);
    + mnt->mnt_namespace = dead_mounts;
    detach_mnt(mnt, &old_nd);
    spin_unlock(&vfsmount_lock);
    path_release(&old_nd);
    @@ -1387,6 +1457,14 @@ static void __init init_mount_tree(void)
    namespace->root = mnt;
    mnt->mnt_namespace = namespace;

    + dead_mounts = kmalloc(sizeof(struct namespace), GFP_KERNEL);
    + if (!dead_mounts)
    + panic("Can't allocate dead_mounts namespace");
    + atomic_set(&dead_mounts->count, 1);
    + INIT_LIST_HEAD(&dead_mounts->list);
    + init_rwsem(&dead_mounts->sem);
    + dead_mounts->root = NULL;
    +
    init_task.namespace = namespace;
    read_lock(&tasklist_lock);
    do_each_thread(g, p) {
    Index: linux/include/linux/mount.h
    ===================================================================
    --- linux.orig/include/linux/mount.h 2005-05-22 16:09:37.000000000 +0200
    +++ linux/include/linux/mount.h 2005-05-22 16:09:45.000000000 +0200
    @@ -46,11 +46,12 @@ static inline struct vfsmount *mntget(st
    }

    extern void __mntput(struct vfsmount *mnt);
    +extern spinlock_t vfsmount_lock;

    static inline void _mntput(struct vfsmount *mnt)
    {
    if (mnt) {
    - if (atomic_dec_and_test(&mnt->mnt_count))
    + if (atomic_dec_and_lock(&mnt->mnt_count, &vfsmount_lock))
    __mntput(mnt);
    }
    }
    @@ -75,7 +76,5 @@ extern int do_add_mount(struct vfsmount

    extern void mark_mounts_for_expiry(struct list_head *mounts);

    -extern spinlock_t vfsmount_lock;
    -
    #endif
    #endif /* _LINUX_MOUNT_H */
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-05-22 19:27    [W:0.047 / U:2.076 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site