Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 18 May 2016 18:51:59 +0000 (11:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 18 May 2016 18:51:59 +0000 (11:51 -0700)
Pull misc vfs cleanups from Al Viro:
 "Assorted cleanups and fixes all over the place"

* 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  coredump: only charge written data against RLIMIT_CORE
  coredump: get rid of coredump_params->written
  ecryptfs_lookup(): try either only encrypted or plaintext name
  ecryptfs: avoid multiple aliases for directories
  bpf: reject invalid names right in ->lookup()
  __d_alloc(): treat NULL name as QSTR("/", 1)
  mtd: switch ubi_open_volume_path() to vfs_stat()
  mtd: switch open_mtd_by_chdev() to use of vfs_stat()

1  2 
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/dcache.c
fs/ecryptfs/inode.c
kernel/bpf/inode.c

diff --combined fs/binfmt_elf.c
@@@ -2273,7 -2273,7 +2273,7 @@@ static int elf_core_dump(struct coredum
                goto end_coredump;
  
        /* Align to page */
-       if (!dump_skip(cprm, dataoff - cprm->written))
+       if (!dump_skip(cprm, dataoff - cprm->file->f_pos))
                goto end_coredump;
  
        for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
                                void *kaddr = kmap(page);
                                stop = !dump_emit(cprm, kaddr, PAGE_SIZE);
                                kunmap(page);
 -                              page_cache_release(page);
 +                              put_page(page);
                        } else
                                stop = !dump_skip(cprm, PAGE_SIZE);
                        if (stop)
diff --combined fs/binfmt_elf_fdpic.c
@@@ -1533,7 -1533,7 +1533,7 @@@ static bool elf_fdpic_dump_segments(str
                                void *kaddr = kmap(page);
                                res = dump_emit(cprm, kaddr, PAGE_SIZE);
                                kunmap(page);
 -                              page_cache_release(page);
 +                              put_page(page);
                        } else {
                                res = dump_skip(cprm, PAGE_SIZE);
                        }
@@@ -1787,7 -1787,7 +1787,7 @@@ static int elf_fdpic_core_dump(struct c
                                goto end_coredump;
        }
  
-       if (!dump_skip(cprm, dataoff - cprm->written))
+       if (!dump_skip(cprm, dataoff - cprm->file->f_pos))
                goto end_coredump;
  
        if (!elf_fdpic_dump_segments(cprm))
diff --combined fs/dcache.c
@@@ -111,17 -111,6 +111,17 @@@ static inline struct hlist_bl_head *d_h
        return dentry_hashtable + hash_32(hash, d_hash_shift);
  }
  
 +#define IN_LOOKUP_SHIFT 10
 +static struct hlist_bl_head in_lookup_hashtable[1 << IN_LOOKUP_SHIFT];
 +
 +static inline struct hlist_bl_head *in_lookup_hash(const struct dentry *parent,
 +                                      unsigned int hash)
 +{
 +      hash += (unsigned long) parent / L1_CACHE_BYTES;
 +      return in_lookup_hashtable + hash_32(hash, IN_LOOKUP_SHIFT);
 +}
 +
 +
  /* Statistics gathering. */
  struct dentry_stat_t dentry_stat = {
        .age_limit = 45,
@@@ -772,8 -761,6 +772,8 @@@ repeat
        /* Slow case: now with the dentry lock held */
        rcu_read_unlock();
  
 +      WARN_ON(d_in_lookup(dentry));
 +
        /* Unreachable? Get rid of it */
        if (unlikely(d_unhashed(dentry)))
                goto kill_it;
@@@ -1571,7 -1558,11 +1571,11 @@@ struct dentry *__d_alloc(struct super_b
         * be overwriting an internal NUL character
         */
        dentry->d_iname[DNAME_INLINE_LEN-1] = 0;
-       if (name->len > DNAME_INLINE_LEN-1) {
+       if (unlikely(!name)) {
+               static const struct qstr anon = QSTR_INIT("/", 1);
+               name = &anon;
+               dname = dentry->d_iname;
+       } else if (name->len > DNAME_INLINE_LEN-1) {
                size_t size = offsetof(struct external_name, name[1]);
                struct external_name *p = kmalloc(size + name->len,
                                                  GFP_KERNEL_ACCOUNT);
@@@ -1680,8 -1671,7 +1684,8 @@@ void d_set_d_op(struct dentry *dentry, 
                                DCACHE_OP_REVALIDATE    |
                                DCACHE_OP_WEAK_REVALIDATE       |
                                DCACHE_OP_DELETE        |
 -                              DCACHE_OP_SELECT_INODE));
 +                              DCACHE_OP_SELECT_INODE  |
 +                              DCACHE_OP_REAL));
        dentry->d_op = op;
        if (!op)
                return;
                dentry->d_flags |= DCACHE_OP_PRUNE;
        if (op->d_select_inode)
                dentry->d_flags |= DCACHE_OP_SELECT_INODE;
 +      if (op->d_real)
 +              dentry->d_flags |= DCACHE_OP_REAL;
  
  }
  EXPORT_SYMBOL(d_set_d_op);
@@@ -1759,7 -1747,6 +1763,7 @@@ type_determined
  static void __d_instantiate(struct dentry *dentry, struct inode *inode)
  {
        unsigned add_flags = d_flags_for_inode(inode);
 +      WARN_ON(d_in_lookup(dentry));
  
        spin_lock(&dentry->d_lock);
        hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
@@@ -1789,11 -1776,11 +1793,11 @@@ void d_instantiate(struct dentry *entry
  {
        BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
        if (inode) {
 +              security_d_instantiate(entry, inode);
                spin_lock(&inode->i_lock);
                __d_instantiate(entry, inode);
                spin_unlock(&inode->i_lock);
        }
 -      security_d_instantiate(entry, inode);
  }
  EXPORT_SYMBOL(d_instantiate);
  
@@@ -1810,7 -1797,6 +1814,7 @@@ int d_instantiate_no_diralias(struct de
  {
        BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
  
 +      security_d_instantiate(entry, inode);
        spin_lock(&inode->i_lock);
        if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) {
                spin_unlock(&inode->i_lock);
        }
        __d_instantiate(entry, inode);
        spin_unlock(&inode->i_lock);
 -      security_d_instantiate(entry, inode);
  
        return 0;
  }
@@@ -1829,9 -1816,7 +1833,7 @@@ struct dentry *d_make_root(struct inod
        struct dentry *res = NULL;
  
        if (root_inode) {
-               static const struct qstr name = QSTR_INIT("/", 1);
-               res = __d_alloc(root_inode->i_sb, &name);
+               res = __d_alloc(root_inode->i_sb, NULL);
                if (res)
                        d_instantiate(res, root_inode);
                else
@@@ -1872,7 -1857,6 +1874,6 @@@ EXPORT_SYMBOL(d_find_any_alias)
  
  static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected)
  {
-       static const struct qstr anonstring = QSTR_INIT("/", 1);
        struct dentry *tmp;
        struct dentry *res;
        unsigned add_flags;
        if (res)
                goto out_iput;
  
-       tmp = __d_alloc(inode->i_sb, &anonstring);
+       tmp = __d_alloc(inode->i_sb, NULL);
        if (!tmp) {
                res = ERR_PTR(-ENOMEM);
                goto out_iput;
        }
  
 +      security_d_instantiate(tmp, inode);
        spin_lock(&inode->i_lock);
        res = __d_find_any_alias(inode);
        if (res) {
        hlist_bl_unlock(&tmp->d_sb->s_anon);
        spin_unlock(&tmp->d_lock);
        spin_unlock(&inode->i_lock);
 -      security_d_instantiate(tmp, inode);
  
        return tmp;
  
   out_iput:
 -      if (res && !IS_ERR(res))
 -              security_d_instantiate(res, inode);
        iput(inode);
        return res;
  }
@@@ -1987,36 -1973,28 +1988,36 @@@ EXPORT_SYMBOL(d_obtain_root)
  struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
                        struct qstr *name)
  {
 -      struct dentry *found;
 -      struct dentry *new;
 +      struct dentry *found, *res;
  
        /*
         * First check if a dentry matching the name already exists,
         * if not go ahead and create it now.
         */
        found = d_hash_and_lookup(dentry->d_parent, name);
 -      if (!found) {
 -              new = d_alloc(dentry->d_parent, name);
 -              if (!new) {
 -                      found = ERR_PTR(-ENOMEM);
 -              } else {
 -                      found = d_splice_alias(inode, new);
 -                      if (found) {
 -                              dput(new);
 -                              return found;
 -                      }
 -                      return new;
 +      if (found) {
 +              iput(inode);
 +              return found;
 +      }
 +      if (d_in_lookup(dentry)) {
 +              found = d_alloc_parallel(dentry->d_parent, name,
 +                                      dentry->d_wait);
 +              if (IS_ERR(found) || !d_in_lookup(found)) {
 +                      iput(inode);
 +                      return found;
                }
 +      } else {
 +              found = d_alloc(dentry->d_parent, name);
 +              if (!found) {
 +                      iput(inode);
 +                      return ERR_PTR(-ENOMEM);
 +              } 
 +      }
 +      res = d_splice_alias(inode, found);
 +      if (res) {
 +              dput(found);
 +              return res;
        }
 -      iput(inode);
        return found;
  }
  EXPORT_SYMBOL(d_add_ci);
@@@ -2383,194 -2361,17 +2384,194 @@@ void d_rehash(struct dentry * entry
  }
  EXPORT_SYMBOL(d_rehash);
  
 +static inline unsigned start_dir_add(struct inode *dir)
 +{
 +
 +      for (;;) {
 +              unsigned n = dir->i_dir_seq;
 +              if (!(n & 1) && cmpxchg(&dir->i_dir_seq, n, n + 1) == n)
 +                      return n;
 +              cpu_relax();
 +      }
 +}
 +
 +static inline void end_dir_add(struct inode *dir, unsigned n)
 +{
 +      smp_store_release(&dir->i_dir_seq, n + 2);
 +}
 +
 +static void d_wait_lookup(struct dentry *dentry)
 +{
 +      if (d_in_lookup(dentry)) {
 +              DECLARE_WAITQUEUE(wait, current);
 +              add_wait_queue(dentry->d_wait, &wait);
 +              do {
 +                      set_current_state(TASK_UNINTERRUPTIBLE);
 +                      spin_unlock(&dentry->d_lock);
 +                      schedule();
 +                      spin_lock(&dentry->d_lock);
 +              } while (d_in_lookup(dentry));
 +      }
 +}
 +
 +struct dentry *d_alloc_parallel(struct dentry *parent,
 +                              const struct qstr *name,
 +                              wait_queue_head_t *wq)
 +{
 +      unsigned int len = name->len;
 +      unsigned int hash = name->hash;
 +      const unsigned char *str = name->name;
 +      struct hlist_bl_head *b = in_lookup_hash(parent, hash);
 +      struct hlist_bl_node *node;
 +      struct dentry *new = d_alloc(parent, name);
 +      struct dentry *dentry;
 +      unsigned seq, r_seq, d_seq;
 +
 +      if (unlikely(!new))
 +              return ERR_PTR(-ENOMEM);
 +
 +retry:
 +      rcu_read_lock();
 +      seq = smp_load_acquire(&parent->d_inode->i_dir_seq) & ~1;
 +      r_seq = read_seqbegin(&rename_lock);
 +      dentry = __d_lookup_rcu(parent, name, &d_seq);
 +      if (unlikely(dentry)) {
 +              if (!lockref_get_not_dead(&dentry->d_lockref)) {
 +                      rcu_read_unlock();
 +                      goto retry;
 +              }
 +              if (read_seqcount_retry(&dentry->d_seq, d_seq)) {
 +                      rcu_read_unlock();
 +                      dput(dentry);
 +                      goto retry;
 +              }
 +              rcu_read_unlock();
 +              dput(new);
 +              return dentry;
 +      }
 +      if (unlikely(read_seqretry(&rename_lock, r_seq))) {
 +              rcu_read_unlock();
 +              goto retry;
 +      }
 +      hlist_bl_lock(b);
 +      if (unlikely(parent->d_inode->i_dir_seq != seq)) {
 +              hlist_bl_unlock(b);
 +              rcu_read_unlock();
 +              goto retry;
 +      }
 +      rcu_read_unlock();
 +      /*
 +       * No changes for the parent since the beginning of d_lookup().
 +       * Since all removals from the chain happen with hlist_bl_lock(),
 +       * any potential in-lookup matches are going to stay here until
 +       * we unlock the chain.  All fields are stable in everything
 +       * we encounter.
 +       */
 +      hlist_bl_for_each_entry(dentry, node, b, d_u.d_in_lookup_hash) {
 +              if (dentry->d_name.hash != hash)
 +                      continue;
 +              if (dentry->d_parent != parent)
 +                      continue;
 +              if (d_unhashed(dentry))
 +                      continue;
 +              if (parent->d_flags & DCACHE_OP_COMPARE) {
 +                      int tlen = dentry->d_name.len;
 +                      const char *tname = dentry->d_name.name;
 +                      if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
 +                              continue;
 +              } else {
 +                      if (dentry->d_name.len != len)
 +                              continue;
 +                      if (dentry_cmp(dentry, str, len))
 +                              continue;
 +              }
 +              dget(dentry);
 +              hlist_bl_unlock(b);
 +              /* somebody is doing lookup for it right now; wait for it */
 +              spin_lock(&dentry->d_lock);
 +              d_wait_lookup(dentry);
 +              /*
 +               * it's not in-lookup anymore; in principle we should repeat
 +               * everything from dcache lookup, but it's likely to be what
 +               * d_lookup() would've found anyway.  If it is, just return it;
 +               * otherwise we really have to repeat the whole thing.
 +               */
 +              if (unlikely(dentry->d_name.hash != hash))
 +                      goto mismatch;
 +              if (unlikely(dentry->d_parent != parent))
 +                      goto mismatch;
 +              if (unlikely(d_unhashed(dentry)))
 +                      goto mismatch;
 +              if (parent->d_flags & DCACHE_OP_COMPARE) {
 +                      int tlen = dentry->d_name.len;
 +                      const char *tname = dentry->d_name.name;
 +                      if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
 +                              goto mismatch;
 +              } else {
 +                      if (unlikely(dentry->d_name.len != len))
 +                              goto mismatch;
 +                      if (unlikely(dentry_cmp(dentry, str, len)))
 +                              goto mismatch;
 +              }
 +              /* OK, it *is* a hashed match; return it */
 +              spin_unlock(&dentry->d_lock);
 +              dput(new);
 +              return dentry;
 +      }
 +      /* we can't take ->d_lock here; it's OK, though. */
 +      new->d_flags |= DCACHE_PAR_LOOKUP;
 +      new->d_wait = wq;
 +      hlist_bl_add_head_rcu(&new->d_u.d_in_lookup_hash, b);
 +      hlist_bl_unlock(b);
 +      return new;
 +mismatch:
 +      spin_unlock(&dentry->d_lock);
 +      dput(dentry);
 +      goto retry;
 +}
 +EXPORT_SYMBOL(d_alloc_parallel);
 +
 +void __d_lookup_done(struct dentry *dentry)
 +{
 +      struct hlist_bl_head *b = in_lookup_hash(dentry->d_parent,
 +                                               dentry->d_name.hash);
 +      hlist_bl_lock(b);
 +      dentry->d_flags &= ~DCACHE_PAR_LOOKUP;
 +      __hlist_bl_del(&dentry->d_u.d_in_lookup_hash);
 +      wake_up_all(dentry->d_wait);
 +      dentry->d_wait = NULL;
 +      hlist_bl_unlock(b);
 +      INIT_HLIST_NODE(&dentry->d_u.d_alias);
 +      INIT_LIST_HEAD(&dentry->d_lru);
 +}
 +EXPORT_SYMBOL(__d_lookup_done);
  
  /* inode->i_lock held if inode is non-NULL */
  
  static inline void __d_add(struct dentry *dentry, struct inode *inode)
  {
 +      struct inode *dir = NULL;
 +      unsigned n;
 +      spin_lock(&dentry->d_lock);
 +      if (unlikely(d_in_lookup(dentry))) {
 +              dir = dentry->d_parent->d_inode;
 +              n = start_dir_add(dir);
 +              __d_lookup_done(dentry);
 +      }
        if (inode) {
 -              __d_instantiate(dentry, inode);
 -              spin_unlock(&inode->i_lock);
 +              unsigned add_flags = d_flags_for_inode(inode);
 +              hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
 +              raw_write_seqcount_begin(&dentry->d_seq);
 +              __d_set_inode_and_type(dentry, inode, add_flags);
 +              raw_write_seqcount_end(&dentry->d_seq);
 +              __fsnotify_d_instantiate(dentry);
        }
 -      security_d_instantiate(dentry, inode);
 -      d_rehash(dentry);
 +      _d_rehash(dentry);
 +      if (dir)
 +              end_dir_add(dir, n);
 +      spin_unlock(&dentry->d_lock);
 +      if (inode)
 +              spin_unlock(&inode->i_lock);
  }
  
  /**
  
  void d_add(struct dentry *entry, struct inode *inode)
  {
 -      if (inode)
 +      if (inode) {
 +              security_d_instantiate(entry, inode);
                spin_lock(&inode->i_lock);
 +      }
        __d_add(entry, inode);
  }
  EXPORT_SYMBOL(d_add);
@@@ -2797,8 -2596,6 +2798,8 @@@ static void dentry_unlock_for_move(stru
  static void __d_move(struct dentry *dentry, struct dentry *target,
                     bool exchange)
  {
 +      struct inode *dir = NULL;
 +      unsigned n;
        if (!dentry->d_inode)
                printk(KERN_WARNING "VFS: moving negative dcache entry\n");
  
        BUG_ON(d_ancestor(target, dentry));
  
        dentry_lock_for_move(dentry, target);
 +      if (unlikely(d_in_lookup(target))) {
 +              dir = target->d_parent->d_inode;
 +              n = start_dir_add(dir);
 +              __d_lookup_done(target);
 +      }
  
        write_seqcount_begin(&dentry->d_seq);
        write_seqcount_begin_nested(&target->d_seq, DENTRY_D_LOCK_NESTED);
        write_seqcount_end(&target->d_seq);
        write_seqcount_end(&dentry->d_seq);
  
 +      if (dir)
 +              end_dir_add(dir, n);
        dentry_unlock_for_move(dentry, target);
  }
  
@@@ -2932,8 -2722,7 +2933,8 @@@ struct dentry *d_ancestor(struct dentr
  static int __d_unalias(struct inode *inode,
                struct dentry *dentry, struct dentry *alias)
  {
 -      struct mutex *m1 = NULL, *m2 = NULL;
 +      struct mutex *m1 = NULL;
 +      struct rw_semaphore *m2 = NULL;
        int ret = -ESTALE;
  
        /* If alias and dentry share a parent, then no extra locks required */
        if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
                goto out_err;
        m1 = &dentry->d_sb->s_vfs_rename_mutex;
 -      if (!inode_trylock(alias->d_parent->d_inode))
 +      if (!inode_trylock_shared(alias->d_parent->d_inode))
                goto out_err;
 -      m2 = &alias->d_parent->d_inode->i_mutex;
 +      m2 = &alias->d_parent->d_inode->i_rwsem;
  out_unalias:
        __d_move(alias, dentry, false);
        ret = 0;
  out_err:
        if (m2)
 -              mutex_unlock(m2);
 +              up_read(m2);
        if (m1)
                mutex_unlock(m1);
        return ret;
@@@ -2991,7 -2780,6 +2992,7 @@@ struct dentry *d_splice_alias(struct in
        if (!inode)
                goto out;
  
 +      security_d_instantiate(dentry, inode);
        spin_lock(&inode->i_lock);
        if (S_ISDIR(inode->i_mode)) {
                struct dentry *new = __d_find_any_alias(inode);
                        } else {
                                __d_move(new, dentry, false);
                                write_sequnlock(&rename_lock);
 -                              security_d_instantiate(new, inode);
                        }
                        iput(inode);
                        return new;
diff --combined fs/ecryptfs/inode.c
@@@ -324,9 -324,8 +324,8 @@@ static int ecryptfs_i_size_read(struct 
  /**
   * ecryptfs_lookup_interpose - Dentry interposition for a lookup
   */
- static int ecryptfs_lookup_interpose(struct dentry *dentry,
-                                    struct dentry *lower_dentry,
-                                    struct inode *dir_inode)
+ static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry,
+                                    struct dentry *lower_dentry)
  {
        struct inode *inode, *lower_inode = d_inode(lower_dentry);
        struct ecryptfs_dentry_info *dentry_info;
                       "to allocate ecryptfs_dentry_info struct\n",
                        __func__);
                dput(lower_dentry);
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
        }
  
        lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
-       fsstack_copy_attr_atime(dir_inode, d_inode(lower_dentry->d_parent));
+       fsstack_copy_attr_atime(d_inode(dentry->d_parent),
+                               d_inode(lower_dentry->d_parent));
        BUG_ON(!d_count(lower_dentry));
  
        ecryptfs_set_dentry_private(dentry, dentry_info);
        if (d_really_is_negative(lower_dentry)) {
                /* We want to add because we couldn't find in lower */
                d_add(dentry, NULL);
-               return 0;
+               return NULL;
        }
-       inode = __ecryptfs_get_inode(lower_inode, dir_inode->i_sb);
+       inode = __ecryptfs_get_inode(lower_inode, dentry->d_sb);
        if (IS_ERR(inode)) {
                printk(KERN_ERR "%s: Error interposing; rc = [%ld]\n",
                       __func__, PTR_ERR(inode));
-               return PTR_ERR(inode);
+               return ERR_CAST(inode);
        }
        if (S_ISREG(inode->i_mode)) {
                rc = ecryptfs_i_size_read(dentry, inode);
                if (rc) {
                        make_bad_inode(inode);
-                       return rc;
+                       return ERR_PTR(rc);
                }
        }
  
        if (inode->i_state & I_NEW)
                unlock_new_inode(inode);
-       d_add(dentry, inode);
-       return rc;
+       return d_splice_alias(inode, dentry);
  }
  
  /**
@@@ -390,55 -388,42 +388,42 @@@ static struct dentry *ecryptfs_lookup(s
                                      unsigned int flags)
  {
        char *encrypted_and_encoded_name = NULL;
-       size_t encrypted_and_encoded_name_size;
-       struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
+       struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
        struct dentry *lower_dir_dentry, *lower_dentry;
+       const char *name = ecryptfs_dentry->d_name.name;
+       size_t len = ecryptfs_dentry->d_name.len;
+       struct dentry *res;
        int rc = 0;
  
        lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent);
-       lower_dentry = lookup_one_len_unlocked(ecryptfs_dentry->d_name.name,
-                                     lower_dir_dentry,
-                                     ecryptfs_dentry->d_name.len);
-       if (IS_ERR(lower_dentry)) {
-               rc = PTR_ERR(lower_dentry);
-               ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
-                               "[%d] on lower_dentry = [%pd]\n", __func__, rc,
-                               ecryptfs_dentry);
-               goto out;
-       }
-       if (d_really_is_positive(lower_dentry))
-               goto interpose;
        mount_crypt_stat = &ecryptfs_superblock_to_private(
                                ecryptfs_dentry->d_sb)->mount_crypt_stat;
-       if (!(mount_crypt_stat
-           && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)))
-               goto interpose;
-       dput(lower_dentry);
-       rc = ecryptfs_encrypt_and_encode_filename(
-               &encrypted_and_encoded_name, &encrypted_and_encoded_name_size,
-               mount_crypt_stat, ecryptfs_dentry->d_name.name,
-               ecryptfs_dentry->d_name.len);
-       if (rc) {
-               printk(KERN_ERR "%s: Error attempting to encrypt and encode "
-                      "filename; rc = [%d]\n", __func__, rc);
-               goto out;
+       if (mount_crypt_stat
+           && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) {
+               rc = ecryptfs_encrypt_and_encode_filename(
+                       &encrypted_and_encoded_name, &len,
+                       mount_crypt_stat, name, len);
+               if (rc) {
+                       printk(KERN_ERR "%s: Error attempting to encrypt and encode "
+                              "filename; rc = [%d]\n", __func__, rc);
+                       return ERR_PTR(rc);
+               }
+               name = encrypted_and_encoded_name;
        }
-       lower_dentry = lookup_one_len_unlocked(encrypted_and_encoded_name,
-                                     lower_dir_dentry,
-                                     encrypted_and_encoded_name_size);
+       lower_dentry = lookup_one_len_unlocked(name, lower_dir_dentry, len);
        if (IS_ERR(lower_dentry)) {
-               rc = PTR_ERR(lower_dentry);
                ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
-                               "[%d] on lower_dentry = [%s]\n", __func__, rc,
-                               encrypted_and_encoded_name);
-               goto out;
+                               "[%ld] on lower_dentry = [%s]\n", __func__,
+                               PTR_ERR(lower_dentry),
+                               name);
+               res = ERR_CAST(lower_dentry);
+       } else {
+               res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry);
        }
- interpose:
-       rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry,
-                                      ecryptfs_dir_inode);
- out:
        kfree(encrypted_and_encoded_name);
-       return ERR_PTR(rc);
+       return res;
  }
  
  static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
@@@ -763,10 -748,10 +748,10 @@@ static int truncate_upper(struct dentr
        } else { /* ia->ia_size < i_size_read(inode) */
                /* We're chopping off all the pages down to the page
                 * in which ia->ia_size is located. Fill in the end of
 -               * that page from (ia->ia_size & ~PAGE_CACHE_MASK) to
 -               * PAGE_CACHE_SIZE with zeros. */
 -              size_t num_zeros = (PAGE_CACHE_SIZE
 -                                  - (ia->ia_size & ~PAGE_CACHE_MASK));
 +               * that page from (ia->ia_size & ~PAGE_MASK) to
 +               * PAGE_SIZE with zeros. */
 +              size_t num_zeros = (PAGE_SIZE
 +                                  - (ia->ia_size & ~PAGE_MASK));
  
                if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
                        truncate_setsize(inode, ia->ia_size);
@@@ -898,11 -883,8 +883,11 @@@ static int ecryptfs_setattr(struct dent
        struct ecryptfs_crypt_stat *crypt_stat;
  
        crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat;
 -      if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
 -              ecryptfs_init_crypt_stat(crypt_stat);
 +      if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) {
 +              rc = ecryptfs_init_crypt_stat(crypt_stat);
 +              if (rc)
 +                      return rc;
 +      }
        inode = d_inode(dentry);
        lower_inode = ecryptfs_inode_to_lower(inode);
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
  }
  
  ssize_t
 -ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name,
 -                      void *value, size_t size)
 +ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
 +                      const char *name, void *value, size_t size)
  {
        int rc = 0;
  
 -      if (!d_inode(lower_dentry)->i_op->getxattr) {
 +      if (!lower_inode->i_op->getxattr) {
                rc = -EOPNOTSUPP;
                goto out;
        }
 -      inode_lock(d_inode(lower_dentry));
 -      rc = d_inode(lower_dentry)->i_op->getxattr(lower_dentry, name, value,
 -                                                 size);
 -      inode_unlock(d_inode(lower_dentry));
 +      inode_lock(lower_inode);
 +      rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
 +                                       name, value, size);
 +      inode_unlock(lower_inode);
  out:
        return rc;
  }
  
  static ssize_t
 -ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
 -                size_t size)
 +ecryptfs_getxattr(struct dentry *dentry, struct inode *inode,
 +                const char *name, void *value, size_t size)
  {
 -      return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), name,
 -                                     value, size);
 +      return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry),
 +                                     ecryptfs_inode_to_lower(inode),
 +                                     name, value, size);
  }
  
  static ssize_t
diff --combined kernel/bpf/inode.c
@@@ -31,10 -31,10 +31,10 @@@ static void *bpf_any_get(void *raw, enu
  {
        switch (type) {
        case BPF_TYPE_PROG:
 -              atomic_inc(&((struct bpf_prog *)raw)->aux->refcnt);
 +              raw = bpf_prog_inc(raw);
                break;
        case BPF_TYPE_MAP:
 -              bpf_map_inc(raw, true);
 +              raw = bpf_map_inc(raw, true);
                break;
        default:
                WARN_ON_ONCE(1);
@@@ -119,18 -119,10 +119,10 @@@ static int bpf_inode_type(const struct 
        return 0;
  }
  
- static bool bpf_dname_reserved(const struct dentry *dentry)
- {
-       return strchr(dentry->d_name.name, '.');
- }
  static int bpf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
  {
        struct inode *inode;
  
-       if (bpf_dname_reserved(dentry))
-               return -EPERM;
        inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFDIR);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
@@@ -152,9 -144,6 +144,6 @@@ static int bpf_mkobj_ops(struct inode *
  {
        struct inode *inode;
  
-       if (bpf_dname_reserved(dentry))
-               return -EPERM;
        inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFREG);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
@@@ -187,31 -176,21 +176,21 @@@ static int bpf_mkobj(struct inode *dir
        }
  }
  
- static int bpf_link(struct dentry *old_dentry, struct inode *dir,
                  struct dentry *new_dentry)
+ static struct dentry *
bpf_lookup(struct inode *dir, struct dentry *dentry, unsigned flags)
  {
-       if (bpf_dname_reserved(new_dentry))
-               return -EPERM;
-       return simple_link(old_dentry, dir, new_dentry);
- }
- static int bpf_rename(struct inode *old_dir, struct dentry *old_dentry,
-                     struct inode *new_dir, struct dentry *new_dentry)
- {
-       if (bpf_dname_reserved(new_dentry))
-               return -EPERM;
-       return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
+       if (strchr(dentry->d_name.name, '.'))
+               return ERR_PTR(-EPERM);
+       return simple_lookup(dir, dentry, flags);
  }
  
  static const struct inode_operations bpf_dir_iops = {
-       .lookup         = simple_lookup,
+       .lookup         = bpf_lookup,
        .mknod          = bpf_mkobj,
        .mkdir          = bpf_mkdir,
        .rmdir          = simple_rmdir,
-       .rename         = bpf_rename,
-       .link           = bpf_link,
+       .rename         = simple_rename,
+       .link           = simple_link,
        .unlink         = simple_unlink,
  };
  
@@@ -297,8 -276,7 +276,8 @@@ static void *bpf_obj_do_get(const struc
                goto out;
  
        raw = bpf_any_get(inode->i_private, *type);
 -      touch_atime(&path);
 +      if (!IS_ERR(raw))
 +              touch_atime(&path);
  
        path_put(&path);
        return raw;