On Mon, Jul 08, 2019 at 11:06:33AM +1000, Stephen Rothwell wrote:
> Today's linux-next merge of the vfs tree got a conflict in:
> 
>   fs/nfsd/nfsctl.c
> 
> between commits:
> 
>   e8a79fb14f6b ("nfsd: add nfsd/clients directory")
> 
> from the nfsd tree and commit:
> 
>   96a374a35f82 ("vfs: Convert nfsctl to use the new mount API")

I did a fetch of

        git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

and looked at the "master" branch and couldn't find that vfs commit.  Am
I looking in the wrong place?

(I'm sure your resolution is fine, I just thought to be careful it might
be nice to run some tests on the merge.)

--b.

> 
> from the vfs tree.
> 
> I fixed it up (Maybe? see below) and can carry the fix as necessary.
> This is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging.  You may also want to consider cooperating
> with the maintainer of the conflicting tree to minimise any particularly
> complex conflicts.
> 
> -- 
> Cheers,
> Stephen Rothwell
> 
> diff --cc fs/nfsd/nfsctl.c
> index 4683ba5c69c7,bbff9c4ac49f..000000000000
> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@@ -1149,201 -1148,8 +1150,201 @@@ static ssize_t write_v4_end_grace(struc
>    *  populating the filesystem.
>    */
>   
>  +/* Basically copying rpc_get_inode. */
>  +static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode)
>  +{
>  +    struct inode *inode = new_inode(sb);
>  +    if (!inode)
>  +            return NULL;
>  +    /* Following advice from simple_fill_super documentation: */
>  +    inode->i_ino = iunique(sb, NFSD_MaxReserved);
>  +    inode->i_mode = mode;
>  +    inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
>  +    switch (mode & S_IFMT) {
>  +    case S_IFDIR:
>  +            inode->i_fop = &simple_dir_operations;
>  +            inode->i_op = &simple_dir_inode_operations;
>  +            inc_nlink(inode);
>  +    default:
>  +            break;
>  +    }
>  +    return inode;
>  +}
>  +
>  +static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t 
> mode)
>  +{
>  +    struct inode *inode;
>  +
>  +    inode = nfsd_get_inode(dir->i_sb, mode);
>  +    if (!inode)
>  +            return -ENOMEM;
>  +    d_add(dentry, inode);
>  +    inc_nlink(dir);
>  +    fsnotify_mkdir(dir, dentry);
>  +    return 0;
>  +}
>  +
>  +static struct dentry *nfsd_mkdir(struct dentry *parent, struct 
> nfsdfs_client *ncl, char *name)
>  +{
>  +    struct inode *dir = parent->d_inode;
>  +    struct dentry *dentry;
>  +    int ret = -ENOMEM;
>  +
>  +    inode_lock(dir);
>  +    dentry = d_alloc_name(parent, name);
>  +    if (!dentry)
>  +            goto out_err;
>  +    ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600);
>  +    if (ret)
>  +            goto out_err;
>  +    if (ncl) {
>  +            d_inode(dentry)->i_private = ncl;
>  +            kref_get(&ncl->cl_ref);
>  +    }
>  +out:
>  +    inode_unlock(dir);
>  +    return dentry;
>  +out_err:
>  +    dentry = ERR_PTR(ret);
>  +    goto out;
>  +}
>  +
>  +static void clear_ncl(struct inode *inode)
>  +{
>  +    struct nfsdfs_client *ncl = inode->i_private;
>  +
>  +    inode->i_private = NULL;
>  +    synchronize_rcu();
>  +    kref_put(&ncl->cl_ref, ncl->cl_release);
>  +}
>  +
>  +
>  +struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode)
>  +{
>  +    struct nfsdfs_client *nc = inode->i_private;
>  +
>  +    if (nc)
>  +            kref_get(&nc->cl_ref);
>  +    return nc;
>  +}
>  +
>  +struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
>  +{
>  +    struct nfsdfs_client *nc;
>  +
>  +    rcu_read_lock();
>  +    nc = __get_nfsdfs_client(inode);
>  +    rcu_read_unlock();
>  +    return nc;
>  +}
>  +/* from __rpc_unlink */
>  +static void nfsdfs_remove_file(struct inode *dir, struct dentry *dentry)
>  +{
>  +    int ret;
>  +
>  +    clear_ncl(d_inode(dentry));
>  +    dget(dentry);
>  +    ret = simple_unlink(dir, dentry);
>  +    d_delete(dentry);
>  +    dput(dentry);
>  +    WARN_ON_ONCE(ret);
>  +}
>  +
>  +static void nfsdfs_remove_files(struct dentry *root)
>  +{
>  +    struct dentry *dentry, *tmp;
>  +
>  +    list_for_each_entry_safe(dentry, tmp, &root->d_subdirs, d_child) {
>  +            if (!simple_positive(dentry)) {
>  +                    WARN_ON_ONCE(1); /* I think this can't happen? */
>  +                    continue;
>  +            }
>  +            nfsdfs_remove_file(d_inode(root), dentry);
>  +    }
>  +}
>  +
>  +/* XXX: cut'n'paste from simple_fill_super; figure out if we could share
>  + * code instead. */
>  +static  int nfsdfs_create_files(struct dentry *root,
>  +                                    const struct tree_descr *files)
>  +{
>  +    struct inode *dir = d_inode(root);
>  +    struct inode *inode;
>  +    struct dentry *dentry;
>  +    int i;
>  +
>  +    inode_lock(dir);
>  +    for (i = 0; files->name && files->name[0]; i++, files++) {
>  +            if (!files->name)
>  +                    continue;
>  +            dentry = d_alloc_name(root, files->name);
>  +            if (!dentry)
>  +                    goto out;
>  +            inode = nfsd_get_inode(d_inode(root)->i_sb,
>  +                                    S_IFREG | files->mode);
>  +            if (!inode) {
>  +                    dput(dentry);
>  +                    goto out;
>  +            }
>  +            inode->i_fop = files->ops;
>  +            inode->i_private = __get_nfsdfs_client(dir);
>  +            d_add(dentry, inode);
>  +            fsnotify_create(dir, dentry);
>  +    }
>  +    inode_unlock(dir);
>  +    return 0;
>  +out:
>  +    nfsdfs_remove_files(root);
>  +    inode_unlock(dir);
>  +    return -ENOMEM;
>  +}
>  +
>  +/* on success, returns positive number unique to that client. */
>  +struct dentry *nfsd_client_mkdir(struct nfsd_net *nn,
>  +            struct nfsdfs_client *ncl, u32 id,
>  +            const struct tree_descr *files)
>  +{
>  +    struct dentry *dentry;
>  +    char name[11];
>  +    int ret;
>  +
>  +    sprintf(name, "%u", id);
>  +
>  +    dentry = nfsd_mkdir(nn->nfsd_client_dir, ncl, name);
>  +    if (IS_ERR(dentry)) /* XXX: tossing errors? */
>  +            return NULL;
>  +    ret = nfsdfs_create_files(dentry, files);
>  +    if (ret) {
>  +            nfsd_client_rmdir(dentry);
>  +            return NULL;
>  +    }
>  +    return dentry;
>  +}
>  +
>  +/* Taken from __rpc_rmdir: */
>  +void nfsd_client_rmdir(struct dentry *dentry)
>  +{
>  +    struct inode *dir = d_inode(dentry->d_parent);
>  +    struct inode *inode = d_inode(dentry);
>  +    int ret;
>  +
>  +    inode_lock(dir);
>  +    nfsdfs_remove_files(dentry);
>  +    clear_ncl(inode);
>  +    dget(dentry);
>  +    ret = simple_rmdir(dir, dentry);
>  +    WARN_ON_ONCE(ret);
>  +    d_delete(dentry);
>  +    inode_unlock(dir);
>  +}
>  +
> - static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
> + static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc)
>   {
>  +    struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
>  +                                                    nfsd_net_id);
>  +    struct dentry *dentry;
>  +    int ret;
>  +
>       static const struct tree_descr nfsd_files[] = {
>               [NFSD_List] = {"exports", &exports_nfsd_operations, S_IRUGO},
>               [NFSD_Export_features] = {"export_features",
> @@@ -1372,23 -1178,33 +1373,39 @@@
>   #endif
>               /* last one */ {""}
>       };
> -     get_net(sb->s_fs_info);
>  -
>  -    return simple_fill_super(sb, 0x6e667364, nfsd_files);
>  +    ret = simple_fill_super(sb, 0x6e667364, nfsd_files);
>  +    if (ret)
>  +            return ret;
>  +    dentry = nfsd_mkdir(sb->s_root, NULL, "clients");
>  +    if (IS_ERR(dentry))
>  +            return PTR_ERR(dentry);
>  +    nn->nfsd_client_dir = dentry;
>  +    return 0;
> + }
> + 
> + static int nfsd_fs_get_tree(struct fs_context *fc)
> + {
> +     fc->s_fs_info = get_net(fc->net_ns);
> +     return vfs_get_super(fc, vfs_get_keyed_super, nfsd_fill_super);
> + }
>   
> + static void nfsd_fs_free_fc(struct fs_context *fc)
> + {
> +     if (fc->s_fs_info)
> +             put_net(fc->s_fs_info);
>   }
>   
> - static struct dentry *nfsd_mount(struct file_system_type *fs_type,
> -     int flags, const char *dev_name, void *data)
> + static const struct fs_context_operations nfsd_fs_context_ops = {
> +     .free           = nfsd_fs_free_fc,
> +     .get_tree       = nfsd_fs_get_tree,
> + };
> + 
> + static int nfsd_init_fs_context(struct fs_context *fc)
>   {
> -     struct net *net = current->nsproxy->net_ns;
> -     return mount_ns(fs_type, flags, data, net, net->user_ns, 
> nfsd_fill_super);
> +     put_user_ns(fc->user_ns);
> +     fc->user_ns = get_user_ns(fc->net_ns->user_ns);
> +     fc->ops = &nfsd_fs_context_ops;
> +     return 0;
>   }
>   
>   static void nfsd_umount(struct super_block *sb)


Reply via email to