lkml.org 
[lkml]   [2010]   [Feb]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH tip/core/rcu 08/18] vfs: apply lockdep-based checking to rcu_dereference() uses
    Date
    Add lockdep-ified RCU primitives to alloc_fd(), files_fdtable() and
    fcheck_files().

    Cc: Alexander Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
    ---
    fs/file.c | 2 +-
    fs/proc/array.c | 2 ++
    fs/proc/base.c | 6 +++++-
    include/linux/fdtable.h | 8 ++++++--
    4 files changed, 14 insertions(+), 4 deletions(-)
    diff --git a/fs/file.c b/fs/file.c
    index 87e1290..38039af 100644
    --- a/fs/file.c
    +++ b/fs/file.c
    @@ -478,7 +478,7 @@ repeat:
    error = fd;
    #if 1
    /* Sanity check */
    - if (rcu_dereference(fdt->fd[fd]) != NULL) {
    + if (rcu_dereference_raw(fdt->fd[fd]) != NULL) {
    printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
    rcu_assign_pointer(fdt->fd[fd], NULL);
    }
    diff --git a/fs/proc/array.c b/fs/proc/array.c
    index 13b5d07..18e20fe 100644
    --- a/fs/proc/array.c
    +++ b/fs/proc/array.c
    @@ -270,7 +270,9 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
    blocked = p->blocked;
    collect_sigign_sigcatch(p, &ignored, &caught);
    num_threads = atomic_read(&p->signal->count);
    + rcu_read_lock(); /* FIXME: is this correct? */
    qsize = atomic_read(&__task_cred(p)->user->sigpending);
    + rcu_read_unlock();
    qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
    unlock_task_sighand(p, &flags);
    }
    diff --git a/fs/proc/base.c b/fs/proc/base.c
    index 18d5cc6..db19ca8 100644
    --- a/fs/proc/base.c
    +++ b/fs/proc/base.c
    @@ -1095,8 +1095,12 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
    if (!capable(CAP_AUDIT_CONTROL))
    return -EPERM;

    - if (current != pid_task(proc_pid(inode), PIDTYPE_PID))
    + rcu_read_lock();
    + if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
    + rcu_read_unlock();
    return -EPERM;
    + }
    + rcu_read_unlock();

    if (count >= PAGE_SIZE)
    count = PAGE_SIZE - 1;
    diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
    index a2ec74b..144412f 100644
    --- a/include/linux/fdtable.h
    +++ b/include/linux/fdtable.h
    @@ -57,7 +57,11 @@ struct files_struct {
    struct file * fd_array[NR_OPEN_DEFAULT];
    };

    -#define files_fdtable(files) (rcu_dereference((files)->fdt))
    +#define files_fdtable(files) \
    + (rcu_dereference_check((files)->fdt, \
    + rcu_read_lock_held() || \
    + lockdep_is_held(&(files)->file_lock) || \
    + atomic_read(&files->count) == 1))

    struct file_operations;
    struct vfsmount;
    @@ -78,7 +82,7 @@ static inline struct file * fcheck_files(struct files_struct *files, unsigned in
    struct fdtable *fdt = files_fdtable(files);

    if (fd < fdt->max_fds)
    - file = rcu_dereference(fdt->fd[fd]);
    + file = rcu_dereference_check(fdt->fd[fd], rcu_read_lock_held() || lockdep_is_held(&files->file_lock) || atomic_read(&files->count) == 1);
    return file;
    }

    --
    1.6.6


    \
     
     \ /
      Last update: 2010-02-17 21:35    [from the cache]
    ©2003-2011 Jasper Spaans