Hi Eric,

Today's linux-next merge of the userns tree got a conflict in fs/dcache.c
between commit 84550b9356af ("RCU'd vfsmounts") from the vfs tree and
commit 40216baa0101 ("vfs: Lazily remove mounts on unlinked files and
directories. v2") from the userns tree.

I fixed it up (I think - see below) and can carry the fix as necessary
(no action is required).

Al, I do have to wonder why a commit whose whole commit message is:

"RCU'd vfsmounts
    
_very_ preliminary, barely tested."

is in linux-next as is not being kept over for v3.14 at this point.
-- 
Cheers,
Stephen Rothwell                    s...@canb.auug.org.au

diff --cc fs/dcache.c
index 6f418c540f76,1e9bf96b0132..000000000000
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@@ -1362,110 -1478,17 +1362,101 @@@ void shrink_dcache_parent(struct dentr
  }
  EXPORT_SYMBOL(shrink_dcache_parent);
  
 +static enum d_walk_ret umount_collect(void *_data, struct dentry *dentry)
 +{
 +      struct select_data *data = _data;
 +      enum d_walk_ret ret = D_WALK_CONTINUE;
 +
 +      if (dentry->d_lockref.count) {
 +              dentry_lru_del(dentry);
 +              if (likely(!list_empty(&dentry->d_subdirs)))
 +                      goto out;
 +              if (dentry == data->start && dentry->d_lockref.count == 1)
 +                      goto out;
 +              printk(KERN_ERR
 +                     "BUG: Dentry %p{i=%lx,n=%s}"
 +                     " still in use (%d)"
 +                     " [unmount of %s %s]\n",
 +                     dentry,
 +                     dentry->d_inode ?
 +                     dentry->d_inode->i_ino : 0UL,
 +                     dentry->d_name.name,
 +                     dentry->d_lockref.count,
 +                     dentry->d_sb->s_type->name,
 +                     dentry->d_sb->s_id);
 +              BUG();
 +      } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
 +              /*
 +               * We can't use d_lru_shrink_move() because we
 +               * need to get the global LRU lock and do the
 +               * LRU accounting.
 +               */
 +              d_lru_del(dentry);
 +              d_shrink_add(dentry, &data->dispose);
 +              data->found++;
 +              ret = D_WALK_NORETRY;
 +      }
 +out:
 +      if (data->found && need_resched())
 +              ret = D_WALK_QUIT;
 +      return ret;
 +}
 +
 +/*
 + * destroy the dentries attached to a superblock on unmounting
 + */
 +void shrink_dcache_for_umount(struct super_block *sb)
 +{
 +      struct dentry *dentry;
 +
 +      if (down_read_trylock(&sb->s_umount))
 +              BUG();
 +
 +      dentry = sb->s_root;
 +      sb->s_root = NULL;
 +      for (;;) {
 +              struct select_data data;
 +
 +              INIT_LIST_HEAD(&data.dispose);
 +              data.start = dentry;
 +              data.found = 0;
 +
 +              d_walk(dentry, &data, umount_collect, NULL);
 +              if (!data.found)
 +                      break;
 +
 +              shrink_dentry_list(&data.dispose);
 +              cond_resched();
 +      }
 +      d_drop(dentry);
 +      dput(dentry);
 +
 +      while (!hlist_bl_empty(&sb->s_anon)) {
 +              struct select_data data;
 +              dentry = hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct 
dentry, d_hash);
 +
 +              INIT_LIST_HEAD(&data.dispose);
 +              data.start = NULL;
 +              data.found = 0;
 +
 +              d_walk(dentry, &data, umount_collect, NULL);
 +              if (data.found)
 +                      shrink_dentry_list(&data.dispose);
 +              cond_resched();
 +      }
 +}
 +
- static enum d_walk_ret check_and_collect(void *_data, struct dentry *dentry)
+ struct detach_data {
+       struct dentry *found;
+ };
+ static enum d_walk_ret do_detach_submounts(void *ptr, struct dentry *dentry)
  {
-       struct select_data *data = _data;
+       struct detach_data *data = ptr;
  
-       if (d_mountpoint(dentry)) {
-               data->found = -EBUSY;
-               return D_WALK_QUIT;
-       }
+       if (d_mountpoint(dentry))
+               data->found = dentry;
  
-       return select_collect(_data, dentry);
- }
- 
- static void check_and_drop(void *_data)
- {
-       struct select_data *data = _data;
- 
-       if (d_mountpoint(data->start))
-               data->found = -EBUSY;
-       if (!data->found)
-               __d_drop(data->start);
+       return data->found ? D_WALK_QUIT : D_WALK_CONTINUE;
  }
  
  /**

Attachment: pgpj1OjZ3JpGO.pgp
Description: PGP signature

Reply via email to