lkml.org 
[lkml]   [2003]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH][2.5.75] devfsd hangs on restart - is_devfsd_or_child() problem
    Date
    On Friday 11 July 2003 22:47, Andrey Borzenkov wrote:
    > I cannot believe it is so fragile ...
    >
    > is_devfsd_or_child() simplemindedly checks for pgrp:
    >
    > static int is_devfsd_or_child (struct fs_info *fs_info)
    > {
    > if (current == fs_info->devfsd_task) return (TRUE);
    > if (current->pgrp == fs_info->devfsd_pgrp) return (TRUE);
    > return (FALSE);
    > } /* End Function is_devfsd_or_child */
    >

    Andrew, one more for your collection :)

    The code that did proper check existed in 2.4 and was removed in 2.5 for
    whatever reason. The patch restores it slightly modified as below.

    2.4 code looks somewhat unclean in that

    - it traverses task list without lock.
    - is starts from current->real_parent but nothing prevents current be
    init_task itself. This hung for me on 2.5 during boot. May be 2.4 does
    something differently.

    Comments?

    regards

    -andrey

    This is trivially reproduced under 2.5 by using devfsd.conf lines

    LOOKUP ^foo$ EXECUTE /home/bor/tmp/devfsd/handler /dev/bar
    LOOKUP ^bar$ EXECUTE /home/bor/tmp/devfsd/handler /dev/foo

    and handler like

    -------- cut here ----------
    #include <unistd.h>

    int
    main(int argc, char **argv, char **envp)
    {
    if (argc <= 1)
    return 0;

    setpgrp();
    return access(argv[1], R_OK);
    }
    -------- cut here ----------

    and doing ls /dev/foo--- linux-2.5.75-smp/fs/devfs/base.c.devfsd_child 2003-07-11 19:41:46.000000000 +0400
    +++ linux-2.5.75-smp/fs/devfs/base.c 2003-07-12 13:51:49.000000000 +0400
    @@ -676,6 +676,7 @@
    #include <linux/smp.h>
    #include <linux/version.h>
    #include <linux/rwsem.h>
    +#include <linux/sched.h>

    #include <asm/uaccess.h>
    #include <asm/io.h>
    @@ -1325,8 +1326,20 @@ static void free_dentry (struct devfs_en

    static int is_devfsd_or_child (struct fs_info *fs_info)
    {
    - if (current == fs_info->devfsd_task) return (TRUE);
    - if (current->pgrp == fs_info->devfsd_pgrp) return (TRUE);
    + struct task_struct *p = current;
    +
    + if (p == fs_info->devfsd_task) return (TRUE);
    + if (p->pgrp == fs_info->devfsd_pgrp) return (TRUE);
    + read_lock(&tasklist_lock);
    + for ( ; p != &init_task; p = p->real_parent)
    + {
    + if (p == fs_info->devfsd_task)
    + {
    + read_unlock (&tasklist_lock);
    + return (TRUE);
    + }
    + }
    + read_unlock (&tasklist_lock);
    return (FALSE);
    } /* End Function is_devfsd_or_child */
    \
     
     \ /
      Last update: 2005-03-22 13:46    [W:2.521 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site