lookup_fdget_rcu() has two callers - there's rcu_read_lock(); file = lookup_fdget_rcu(*fd); rcu_read_unlock(); in arch/powerpc/platforms/cell/spufs/coredump.c:coredump_next_context() and rcu_read_lock(); f = lookup_fdget_rcu(fd); rcu_read_unlock(); in fs/notify/dnotify/dnotify.c:fcntl_dirnotify() Now, look at the lookup_fdget_rcu() definition: struct file *lookup_fdget_rcu(unsigned int fd) { return __fget_files_rcu(current->files, fd, 0); } and compare with this: struct file *fget_raw(unsigned int fd) { return __fget(fd, 0); } static inline struct file *__fget(unsigned int fd, fmode_t mask) { return __fget_files(current->files, fd, mask); } static struct file *__fget_files(struct files_struct *files, unsigned int fd, fmode_t mask) { struct file *file; rcu_read_lock(); file = __fget_files_rcu(files, fd, mask); rcu_read_unlock(); return file; } In other words, both calls are weirdly spelled fget_raw(). While we are at it, all callers of task_lookup_fdget_rcu() and task_lookup_next_fdget_rcu() could bloody well have rcu_read_lock()/ rcu_read_unlock() immediately surrounding those, with the obvious next step being to push those in. At that point calls of task_lookup_fdget_rcu() turn into fget_task(), BTW. That stuff had been added in "file: convert to SLAB_TYPESAFE_BY_RCU" as replacements of lookup_fd_rcu() and friends. The old ones did not grab file reference; their replacements do (with good reasons). But that had pretty much killed the rationale behind separate "we are under rcu_read_lock(), so we don't need to mess with refcounts" family of helpers. I might be missing something subtle here; if not, tomorrow morning I'm going to throw a patch pushing those rcu_read_lock() in (and killing {task_,}lookup_fdget_rcu()) into the rebased fdtable series from the last cycle...