[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <74488f024f3802c65e320f5884939f200c866a7e.camel@kernel.org>
Date: Tue, 18 Feb 2025 08:13:54 -0500
From: Jeff Layton <jlayton@...nel.org>
To: NeilBrown <neilb@...e.de>, Christian Brauner <brauner@...nel.org>,
Alexander Viro <viro@...iv.linux.org.uk>, Jan Kara <jack@...e.cz>
Cc: linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH 1/3] Change inode_operations.mkdir to return struct
dentry *
On Mon, 2025-02-17 at 16:30 +1100, NeilBrown wrote:
> Some filesystems, such as NFS, cifs, ceph, and fuse, do not have
> complete control of sequencing on the actual filesystem (e.g. on a
> different server) and may find that the inode created for a mkdir
> request already exists in the icache and dcache by the time the mkdir
> request returns. For example, if the filesystem is mounted twice the
> file could be visible on the other mount before it is on the original
> mount, and a pair of name_to_handle_at(), open_by_handle_at() could
> instantiate the directory inode with an IS_ROOT() dentry before the
> first mkdir returns.
>
> This means that the dentry passed to ->mkdir() may not be the one that
> is associated with the inode after the ->mkdir() completes. Some
> callers need to interact with the inode after the ->mkdir completes and
> they currently need to perform a lookup in the (rare) case that the
> dentry is no longer hashed.
>
> This lookup-after-mkdir requires that the directory remains locked to
> avoid races. Planned future patches to lock the dentry rather than the
> directory will mean that this lookup cannot be performed atomically with
> the mkdir.
>
> To remove this barrier, this patch changes ->mkdir to return the
> resulting dentry if it is different from the one passed in.
> Possible returns are:
> NULL - the directory was created and no other dentry was used
> ERR_PTR() - an error occurred
> non-NULL - this other dentry was spliced in
>
> Not all filesystems reliable result in a positive hashed dentry:
>
> - NFS does produce the proper dentry, but does not yet return it. The
> code change is larger than I wanted to include in this patch
To be clear: with this patch and NFS, the only breakage is that you get
a fsnotify_mkdir() call with the wrong dentry.
> - cifs will, when posix extensions are enabled, unhash the
> dentry on success so a subsequent lookup will create it if needed.
> - cifs without posix extensions will unhash the dentry if an
> internal lookup finds a non-directory where it expected the dir.
> - kernfs and tracefs leave the dentry negative and the ->revalidate
> operation ensures that lookup will be called to correctly populate
> the dentry
> - hostfs leaves the dentry negative and uses
> .d_delete = always_delete_dentry
> so the negative dentry is quickly discarded and a lookup will add a
> new entry.
>
> Signed-off-by: NeilBrown <neilb@...e.de>
> ---
> Documentation/filesystems/locking.rst | 2 +-
> Documentation/filesystems/porting.rst | 11 +++++
> Documentation/filesystems/vfs.rst | 7 +++-
> fs/9p/vfs_inode.c | 7 ++--
> fs/9p/vfs_inode_dotl.c | 8 ++--
> fs/affs/affs.h | 2 +-
> fs/affs/namei.c | 8 ++--
> fs/afs/dir.c | 12 +++---
> fs/autofs/root.c | 14 +++----
> fs/bad_inode.c | 6 +--
> fs/bcachefs/fs.c | 6 +--
> fs/btrfs/inode.c | 8 ++--
> fs/ceph/dir.c | 15 +++++--
> fs/coda/dir.c | 14 +++----
> fs/configfs/dir.c | 6 +--
> fs/ecryptfs/inode.c | 6 +--
> fs/exfat/namei.c | 8 ++--
> fs/ext2/namei.c | 9 +++--
> fs/ext4/namei.c | 10 ++---
> fs/f2fs/namei.c | 14 +++----
> fs/fat/namei_msdos.c | 8 ++--
> fs/fat/namei_vfat.c | 8 ++--
> fs/fuse/dir.c | 58 +++++++++++++++++----------
> fs/gfs2/inode.c | 9 +++--
> fs/hfs/dir.c | 10 ++---
> fs/hfsplus/dir.c | 6 +--
> fs/hostfs/hostfs_kern.c | 8 ++--
> fs/hpfs/namei.c | 10 ++---
> fs/hugetlbfs/inode.c | 6 +--
> fs/jffs2/dir.c | 18 ++++-----
> fs/jfs/namei.c | 8 ++--
> fs/kernfs/dir.c | 12 +++---
> fs/minix/namei.c | 8 ++--
> fs/namei.c | 14 +++++--
> fs/nfs/dir.c | 9 +++--
> fs/nfs/internal.h | 4 +-
> fs/nilfs2/namei.c | 8 ++--
> fs/ntfs3/namei.c | 8 ++--
> fs/ocfs2/dlmfs/dlmfs.c | 14 ++++---
> fs/ocfs2/namei.c | 10 ++---
> fs/omfs/dir.c | 6 +--
> fs/orangefs/namei.c | 8 ++--
> fs/overlayfs/dir.c | 9 +++--
> fs/ramfs/inode.c | 6 +--
> fs/smb/client/cifsfs.h | 4 +-
> fs/smb/client/inode.c | 10 ++---
> fs/sysv/namei.c | 8 ++--
> fs/tracefs/inode.c | 10 ++---
> fs/ubifs/dir.c | 10 ++---
> fs/udf/namei.c | 12 +++---
> fs/ufs/namei.c | 8 ++--
> fs/vboxsf/dir.c | 8 ++--
> fs/xfs/xfs_iops.c | 4 +-
> include/linux/fs.h | 4 +-
> kernel/bpf/inode.c | 8 ++--
> mm/shmem.c | 8 ++--
> security/apparmor/apparmorfs.c | 8 ++--
> 57 files changed, 294 insertions(+), 246 deletions(-)
>
> diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
> index d20a32b77b60..0ec0bb6eb0fb 100644
> --- a/Documentation/filesystems/locking.rst
> +++ b/Documentation/filesystems/locking.rst
> @@ -66,7 +66,7 @@ prototypes::
> int (*link) (struct dentry *,struct inode *,struct dentry *);
> int (*unlink) (struct inode *,struct dentry *);
> int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,const char *);
> - int (*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
> + struct dentry *(*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
> int (*rmdir) (struct inode *,struct dentry *);
> int (*mknod) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t,dev_t);
> int (*rename) (struct mnt_idmap *, struct inode *, struct dentry *,
> diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
> index 159adb02be52..68938b7ca1ab 100644
> --- a/Documentation/filesystems/porting.rst
> +++ b/Documentation/filesystems/porting.rst
> @@ -1175,3 +1175,14 @@ lookup_one_qstr_excl() is changed to return errors in some cases:
>
> LOOKUP_EXCL now means "target must not exist". It can be combined with
> LOOK_CREATE or LOOKUP_RENAME_TARGET.
> +
> +---
> +
> +** mandatory**
> +
> +->mkdir() now returns a 'struct dentry *'. If the created inode is
> +found to already be in cache and have a dentry (often IS_ROOT), it will
> +need to be spliced into the given name in place of the given dentry.
> +That dentry now needs to be returned. If the original dentry is used,
> +NULL should be returned. Any error should be returned with
> +ERR_PTR().
> diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
> index 31eea688609a..bd3751dfddcf 100644
> --- a/Documentation/filesystems/vfs.rst
> +++ b/Documentation/filesystems/vfs.rst
> @@ -495,7 +495,7 @@ As of kernel 2.6.22, the following members are defined:
> int (*link) (struct dentry *,struct inode *,struct dentry *);
> int (*unlink) (struct inode *,struct dentry *);
> int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,const char *);
> - int (*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
> + struct dentry *(*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
> int (*rmdir) (struct inode *,struct dentry *);
> int (*mknod) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t,dev_t);
> int (*rename) (struct mnt_idmap *, struct inode *, struct dentry *,
> @@ -562,7 +562,10 @@ otherwise noted.
> ``mkdir``
> called by the mkdir(2) system call. Only required if you want
> to support creating subdirectories. You will probably need to
> - call d_instantiate() just as you would in the create() method
> + call d_instantiate() just as you would in the create() method.
> + If some dentry other than the one given is spliced in, then it
> + much be returned, otherwise NULL is returned is the original dentry
> + is successfully used, else an ERR_PTR() is returned.
>
> ``rmdir``
> called by the rmdir(2) system call. Only required if you want
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 3e68521f4e2f..399d455d50d6 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -669,8 +669,8 @@ v9fs_vfs_create(struct mnt_idmap *idmap, struct inode *dir,
> *
> */
>
> -static int v9fs_vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *v9fs_vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> int err;
> u32 perm;
> @@ -692,8 +692,7 @@ static int v9fs_vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> if (fid)
> p9_fid_put(fid);
> -
> - return err;
> + return ERR_PTR(err);
> }
>
> /**
> diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
> index 143ac03b7425..cc2007be2173 100644
> --- a/fs/9p/vfs_inode_dotl.c
> +++ b/fs/9p/vfs_inode_dotl.c
> @@ -350,9 +350,9 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
> *
> */
>
> -static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
> - struct inode *dir, struct dentry *dentry,
> - umode_t omode)
> +static struct dentry *v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
> + struct inode *dir, struct dentry *dentry,
> + umode_t omode)
> {
> int err;
> struct v9fs_session_info *v9ses;
> @@ -417,7 +417,7 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
> p9_fid_put(fid);
> v9fs_put_acl(dacl, pacl);
> p9_fid_put(dfid);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int
> diff --git a/fs/affs/affs.h b/fs/affs/affs.h
> index e8c2c4535cb3..ac4e9a02910b 100644
> --- a/fs/affs/affs.h
> +++ b/fs/affs/affs.h
> @@ -168,7 +168,7 @@ extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, unsi
> extern int affs_unlink(struct inode *dir, struct dentry *dentry);
> extern int affs_create(struct mnt_idmap *idmap, struct inode *dir,
> struct dentry *dentry, umode_t mode, bool);
> -extern int affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> +extern struct dentry *affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> struct dentry *dentry, umode_t mode);
> extern int affs_rmdir(struct inode *dir, struct dentry *dentry);
> extern int affs_link(struct dentry *olddentry, struct inode *dir,
> diff --git a/fs/affs/namei.c b/fs/affs/namei.c
> index 8c154490a2d6..f883be50db12 100644
> --- a/fs/affs/namei.c
> +++ b/fs/affs/namei.c
> @@ -273,7 +273,7 @@ affs_create(struct mnt_idmap *idmap, struct inode *dir,
> return 0;
> }
>
> -int
> +struct dentry *
> affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> struct dentry *dentry, umode_t mode)
> {
> @@ -285,7 +285,7 @@ affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> inode = affs_new_inode(dir);
> if (!inode)
> - return -ENOSPC;
> + return ERR_PTR(-ENOSPC);
>
> inode->i_mode = S_IFDIR | mode;
> affs_mode_to_prot(inode);
> @@ -298,9 +298,9 @@ affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> clear_nlink(inode);
> mark_inode_dirty(inode);
> iput(inode);
> - return error;
> + return ERR_PTR(error);
> }
> - return 0;
> + return NULL;
> }
>
> int
> diff --git a/fs/afs/dir.c b/fs/afs/dir.c
> index 02cbf38e1a77..5bddcc20786e 100644
> --- a/fs/afs/dir.c
> +++ b/fs/afs/dir.c
> @@ -33,8 +33,8 @@ static bool afs_lookup_filldir(struct dir_context *ctx, const char *name, int nl
> loff_t fpos, u64 ino, unsigned dtype);
> static int afs_create(struct mnt_idmap *idmap, struct inode *dir,
> struct dentry *dentry, umode_t mode, bool excl);
> -static int afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode);
> +static struct dentry *afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode);
> static int afs_rmdir(struct inode *dir, struct dentry *dentry);
> static int afs_unlink(struct inode *dir, struct dentry *dentry);
> static int afs_link(struct dentry *from, struct inode *dir,
> @@ -1315,8 +1315,8 @@ static const struct afs_operation_ops afs_mkdir_operation = {
> /*
> * create a directory on an AFS filesystem
> */
> -static int afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct afs_operation *op;
> struct afs_vnode *dvnode = AFS_FS_I(dir);
> @@ -1328,7 +1328,7 @@ static int afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> op = afs_alloc_operation(NULL, dvnode->volume);
> if (IS_ERR(op)) {
> d_drop(dentry);
> - return PTR_ERR(op);
> + return ERR_CAST(op);
> }
>
> fscache_use_cookie(afs_vnode_cache(dvnode), true);
> @@ -1344,7 +1344,7 @@ static int afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> op->ops = &afs_mkdir_operation;
> ret = afs_do_sync_operation(op);
> afs_dir_unuse_cookie(dvnode, ret);
> - return ret;
> + return ERR_PTR(ret);
> }
>
> /*
> diff --git a/fs/autofs/root.c b/fs/autofs/root.c
> index 530d18827e35..174c7205fee4 100644
> --- a/fs/autofs/root.c
> +++ b/fs/autofs/root.c
> @@ -15,8 +15,8 @@ static int autofs_dir_symlink(struct mnt_idmap *, struct inode *,
> struct dentry *, const char *);
> static int autofs_dir_unlink(struct inode *, struct dentry *);
> static int autofs_dir_rmdir(struct inode *, struct dentry *);
> -static int autofs_dir_mkdir(struct mnt_idmap *, struct inode *,
> - struct dentry *, umode_t);
> +static struct dentry *autofs_dir_mkdir(struct mnt_idmap *, struct inode *,
> + struct dentry *, umode_t);
> static long autofs_root_ioctl(struct file *, unsigned int, unsigned long);
> #ifdef CONFIG_COMPAT
> static long autofs_root_compat_ioctl(struct file *,
> @@ -720,9 +720,9 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
> return 0;
> }
>
> -static int autofs_dir_mkdir(struct mnt_idmap *idmap,
> - struct inode *dir, struct dentry *dentry,
> - umode_t mode)
> +static struct dentry *autofs_dir_mkdir(struct mnt_idmap *idmap,
> + struct inode *dir, struct dentry *dentry,
> + umode_t mode)
> {
> struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
> struct autofs_info *ino = autofs_dentry_ino(dentry);
> @@ -739,7 +739,7 @@ static int autofs_dir_mkdir(struct mnt_idmap *idmap,
>
> inode = autofs_get_inode(dir->i_sb, S_IFDIR | mode);
> if (!inode)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
> d_add(dentry, inode);
>
> if (sbi->version < 5)
> @@ -751,7 +751,7 @@ static int autofs_dir_mkdir(struct mnt_idmap *idmap,
> inc_nlink(dir);
> inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
>
> - return 0;
> + return NULL;
> }
>
> /* Get/set timeout ioctl() operation */
> diff --git a/fs/bad_inode.c b/fs/bad_inode.c
> index 316d88da2ce1..0ef9bcb744dd 100644
> --- a/fs/bad_inode.c
> +++ b/fs/bad_inode.c
> @@ -58,10 +58,10 @@ static int bad_inode_symlink(struct mnt_idmap *idmap,
> return -EIO;
> }
>
> -static int bad_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *bad_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> - return -EIO;
> + return ERR_PTR(-EIO);
> }
>
> static int bad_inode_rmdir (struct inode *dir, struct dentry *dentry)
> diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
> index 90ade8f648d9..1c94a680fcce 100644
> --- a/fs/bcachefs/fs.c
> +++ b/fs/bcachefs/fs.c
> @@ -858,10 +858,10 @@ static int bch2_symlink(struct mnt_idmap *idmap,
> return bch2_err_class(ret);
> }
>
> -static int bch2_mkdir(struct mnt_idmap *idmap,
> - struct inode *vdir, struct dentry *dentry, umode_t mode)
> +static struct dentry *bch2_mkdir(struct mnt_idmap *idmap,
> + struct inode *vdir, struct dentry *dentry, umode_t mode)
> {
> - return bch2_mknod(idmap, vdir, dentry, mode|S_IFDIR, 0);
> + return ERR_PTR(bch2_mknod(idmap, vdir, dentry, mode|S_IFDIR, 0));
> }
>
> static int bch2_rename2(struct mnt_idmap *idmap,
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index a9322601ab5c..851d3e8a06a7 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -6739,18 +6739,18 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
> return err;
> }
>
> -static int btrfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *btrfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct inode *inode;
>
> inode = new_inode(dir->i_sb);
> if (!inode)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
> inode_init_owner(idmap, inode, dir, S_IFDIR | mode);
> inode->i_op = &btrfs_dir_inode_operations;
> inode->i_fop = &btrfs_dir_file_operations;
> - return btrfs_create_common(dir, dentry, inode);
> + return ERR_PTR(btrfs_create_common(dir, dentry, inode));
> }
>
> static noinline int uncompress_inline(struct btrfs_path *path,
> diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
> index 62e99e65250d..c1a1c168bb27 100644
> --- a/fs/ceph/dir.c
> +++ b/fs/ceph/dir.c
> @@ -1092,19 +1092,20 @@ static int ceph_symlink(struct mnt_idmap *idmap, struct inode *dir,
> return err;
> }
>
> -static int ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
> struct ceph_client *cl = mdsc->fsc->client;
> struct ceph_mds_request *req;
> struct ceph_acl_sec_ctx as_ctx = {};
> + struct dentry *ret = NULL;
> int err;
> int op;
>
> err = ceph_wait_on_conflict_unlink(dentry);
> if (err)
> - return err;
> + return ERR_PTR(err);
>
> if (ceph_snap(dir) == CEPH_SNAPDIR) {
> /* mkdir .snap/foo is a MKSNAP */
> @@ -1166,14 +1167,20 @@ static int ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> !req->r_reply_info.head->is_dentry)
> err = ceph_handle_notrace_create(dir, dentry);
> out_req:
> + if (!err && req->r_dentry != dentry)
> + /* Some other dentry was spliced in */
> + ret = dget(req->r_dentry);
> ceph_mdsc_put_request(req);
> out:
> if (!err)
> + /* Should this use 'ret' ?? */
> ceph_init_inode_acls(d_inode(dentry), &as_ctx);
> else
> d_drop(dentry);
> ceph_release_acl_sec_ctx(&as_ctx);
> - return err;
> + if (err)
> + return ERR_PTR(err);
> + return ret;
> }
>
> static int ceph_link(struct dentry *old_dentry, struct inode *dir,
> diff --git a/fs/coda/dir.c b/fs/coda/dir.c
> index a3e2dfeedfbf..ab69d8f0cec2 100644
> --- a/fs/coda/dir.c
> +++ b/fs/coda/dir.c
> @@ -166,8 +166,8 @@ static int coda_create(struct mnt_idmap *idmap, struct inode *dir,
> return error;
> }
>
> -static int coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *de, umode_t mode)
> +static struct dentry *coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *de, umode_t mode)
> {
> struct inode *inode;
> struct coda_vattr attrs;
> @@ -177,14 +177,14 @@ static int coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> struct CodaFid newfid;
>
> if (is_root_inode(dir) && coda_iscontrol(name, len))
> - return -EPERM;
> + return ERR_PTR(-EPERM);
>
> attrs.va_mode = mode;
> - error = venus_mkdir(dir->i_sb, coda_i2f(dir),
> + error = venus_mkdir(dir->i_sb, coda_i2f(dir),
> name, len, &newfid, &attrs);
> if (error)
> goto err_out;
> -
> +
> inode = coda_iget(dir->i_sb, &newfid, &attrs);
> if (IS_ERR(inode)) {
> error = PTR_ERR(inode);
> @@ -195,10 +195,10 @@ static int coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> coda_dir_inc_nlink(dir);
> coda_dir_update_mtime(dir);
> d_instantiate(de, inode);
> - return 0;
> + return NULL;
> err_out:
> d_drop(de);
> - return error;
> + return ERR_PTR(error);
> }
>
> /* try to make de an entry in dir_inodde linked to source_de */
> diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
> index 7d10278db30d..5568cb74b322 100644
> --- a/fs/configfs/dir.c
> +++ b/fs/configfs/dir.c
> @@ -1280,8 +1280,8 @@ int configfs_depend_item_unlocked(struct configfs_subsystem *caller_subsys,
> }
> EXPORT_SYMBOL(configfs_depend_item_unlocked);
>
> -static int configfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *configfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> int ret = 0;
> int module_got = 0;
> @@ -1461,7 +1461,7 @@ static int configfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> put_fragment(frag);
>
> out:
> - return ret;
> + return ERR_PTR(ret);
> }
>
> static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
> diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
> index a9819ddb1ab8..6315dd194228 100644
> --- a/fs/ecryptfs/inode.c
> +++ b/fs/ecryptfs/inode.c
> @@ -503,8 +503,8 @@ static int ecryptfs_symlink(struct mnt_idmap *idmap,
> return rc;
> }
>
> -static int ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> int rc;
> struct dentry *lower_dentry;
> @@ -526,7 +526,7 @@ static int ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> inode_unlock(lower_dir);
> if (d_really_is_negative(dentry))
> d_drop(dentry);
> - return rc;
> + return ERR_PTR(rc);
> }
>
> static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
> diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
> index 691dd77b6ab5..1660c9bbcfa9 100644
> --- a/fs/exfat/namei.c
> +++ b/fs/exfat/namei.c
> @@ -835,8 +835,8 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
> return err;
> }
>
> -static int exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct super_block *sb = dir->i_sb;
> struct inode *inode;
> @@ -846,7 +846,7 @@ static int exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> loff_t size = i_size_read(dir);
>
> if (unlikely(exfat_forced_shutdown(sb)))
> - return -EIO;
> + return ERR_PTR(-EIO);
>
> mutex_lock(&EXFAT_SB(sb)->s_lock);
> exfat_set_volume_dirty(sb);
> @@ -877,7 +877,7 @@ static int exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> unlock:
> mutex_unlock(&EXFAT_SB(sb)->s_lock);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int exfat_check_dir_empty(struct super_block *sb,
> diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
> index 8346ab9534c1..bde617a66cec 100644
> --- a/fs/ext2/namei.c
> +++ b/fs/ext2/namei.c
> @@ -225,15 +225,16 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
> return err;
> }
>
> -static int ext2_mkdir(struct mnt_idmap * idmap,
> - struct inode * dir, struct dentry * dentry, umode_t mode)
> +static struct dentry *ext2_mkdir(struct mnt_idmap * idmap,
> + struct inode * dir, struct dentry * dentry,
> + umode_t mode)
> {
> struct inode * inode;
> int err;
>
> err = dquot_initialize(dir);
> if (err)
> - return err;
> + return ERR_PTR(err);
>
> inode_inc_link_count(dir);
>
> @@ -258,7 +259,7 @@ static int ext2_mkdir(struct mnt_idmap * idmap,
>
> d_instantiate_new(dentry, inode);
> out:
> - return err;
> + return ERR_PTR(err);
>
> out_fail:
> inode_dec_link_count(inode);
> diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
> index 536d56d15072..716cc6096870 100644
> --- a/fs/ext4/namei.c
> +++ b/fs/ext4/namei.c
> @@ -3004,19 +3004,19 @@ int ext4_init_new_dir(handle_t *handle, struct inode *dir,
> return err;
> }
>
> -static int ext4_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *ext4_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> handle_t *handle;
> struct inode *inode;
> int err, err2 = 0, credits, retries = 0;
>
> if (EXT4_DIR_LINK_MAX(dir))
> - return -EMLINK;
> + return ERR_PTR(-EMLINK);
>
> err = dquot_initialize(dir);
> if (err)
> - return err;
> + return ERR_PTR(err);
>
> credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
> EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3);
> @@ -3066,7 +3066,7 @@ static int ext4_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> out_retry:
> if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
> goto retry;
> - return err;
> + return ERR_PTR(err);
> }
>
> /*
> diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
> index a278c7da8177..24dca4dc85a9 100644
> --- a/fs/f2fs/namei.c
> +++ b/fs/f2fs/namei.c
> @@ -684,23 +684,23 @@ static int f2fs_symlink(struct mnt_idmap *idmap, struct inode *dir,
> return err;
> }
>
> -static int f2fs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *f2fs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
> struct inode *inode;
> int err;
>
> if (unlikely(f2fs_cp_error(sbi)))
> - return -EIO;
> + return ERR_PTR(-EIO);
>
> err = f2fs_dquot_initialize(dir);
> if (err)
> - return err;
> + return ERR_PTR(err);
>
> inode = f2fs_new_inode(idmap, dir, S_IFDIR | mode, NULL);
> if (IS_ERR(inode))
> - return PTR_ERR(inode);
> + return ERR_CAST(inode);
>
> inode->i_op = &f2fs_dir_inode_operations;
> inode->i_fop = &f2fs_dir_operations;
> @@ -722,12 +722,12 @@ static int f2fs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> f2fs_sync_fs(sbi->sb, 1);
>
> f2fs_balance_fs(sbi, true);
> - return 0;
> + return NULL;
>
> out_fail:
> clear_inode_flag(inode, FI_INC_LINK);
> f2fs_handle_failed_inode(inode);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int f2fs_rmdir(struct inode *dir, struct dentry *dentry)
> diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
> index f06f6ba643cc..23e9b9371ec3 100644
> --- a/fs/fat/namei_msdos.c
> +++ b/fs/fat/namei_msdos.c
> @@ -339,8 +339,8 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
> }
>
> /***** Make a directory */
> -static int msdos_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *msdos_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct super_block *sb = dir->i_sb;
> struct fat_slot_info sinfo;
> @@ -389,13 +389,13 @@ static int msdos_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
> fat_flush_inodes(sb, dir, inode);
> - return 0;
> + return NULL;
>
> out_free:
> fat_free_clusters(dir, cluster);
> out:
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
> - return err;
> + return ERR_PTR(err);
> }
>
> /***** Unlink a file */
> diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
> index 926c26e90ef8..dd910edd2404 100644
> --- a/fs/fat/namei_vfat.c
> +++ b/fs/fat/namei_vfat.c
> @@ -841,8 +841,8 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
> return err;
> }
>
> -static int vfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *vfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct super_block *sb = dir->i_sb;
> struct inode *inode;
> @@ -877,13 +877,13 @@ static int vfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> d_instantiate(dentry, inode);
>
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
> - return 0;
> + return NULL;
>
> out_free:
> fat_free_clusters(dir, cluster);
> out:
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int vfat_get_dotdot_de(struct inode *inode, struct buffer_head **bh,
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index 198862b086ff..2537eefcd023 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -781,9 +781,9 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
> /*
> * Code shared between mknod, mkdir, symlink and link
> */
> -static int create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
> - struct fuse_args *args, struct inode *dir,
> - struct dentry *entry, umode_t mode)
> +static struct dentry *create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
> + struct fuse_args *args, struct inode *dir,
> + struct dentry *entry, umode_t mode)
> {
> struct fuse_entry_out outarg;
> struct inode *inode;
> @@ -792,11 +792,11 @@ static int create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
> struct fuse_forget_link *forget;
>
> if (fuse_is_bad(dir))
> - return -EIO;
> + return ERR_PTR(-EIO);
>
> forget = fuse_alloc_forget();
> if (!forget)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> memset(&outarg, 0, sizeof(outarg));
> args->nodeid = get_node_id(dir);
> @@ -826,29 +826,27 @@ static int create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
> &outarg.attr, ATTR_TIMEOUT(&outarg), 0, 0);
> if (!inode) {
> fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
> }
> kfree(forget);
>
> d_drop(entry);
> d = d_splice_alias(inode, entry);
> if (IS_ERR(d))
> - return PTR_ERR(d);
> + return d;
>
> - if (d) {
> + if (d)
> fuse_change_entry_timeout(d, &outarg);
> - dput(d);
> - } else {
> + else
> fuse_change_entry_timeout(entry, &outarg);
> - }
> fuse_dir_changed(dir);
> - return 0;
> + return d;
>
> out_put_forget_req:
> if (err == -EEXIST)
> fuse_invalidate_entry(entry);
> kfree(forget);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
> @@ -856,6 +854,7 @@ static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
> {
> struct fuse_mknod_in inarg;
> struct fuse_mount *fm = get_fuse_mount(dir);
> + struct dentry *de;
> FUSE_ARGS(args);
>
> if (!fm->fc->dont_mask)
> @@ -871,7 +870,12 @@ static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
> args.in_args[0].value = &inarg;
> args.in_args[1].size = entry->d_name.len + 1;
> args.in_args[1].value = entry->d_name.name;
> - return create_new_entry(idmap, fm, &args, dir, entry, mode);
> + de = create_new_entry(idmap, fm, &args, dir, entry, mode);
> + if (IS_ERR(de))
> + return PTR_ERR(de);
> + if (de)
> + dput(de);
> + return 0;
> }
>
> static int fuse_create(struct mnt_idmap *idmap, struct inode *dir,
> @@ -898,8 +902,8 @@ static int fuse_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
> return err;
> }
>
> -static int fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *entry, umode_t mode)
> +static struct dentry *fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *entry, umode_t mode)
> {
> struct fuse_mkdir_in inarg;
> struct fuse_mount *fm = get_fuse_mount(dir);
> @@ -918,6 +922,7 @@ static int fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> args.in_args[1].size = entry->d_name.len + 1;
> args.in_args[1].value = entry->d_name.name;
> return create_new_entry(idmap, fm, &args, dir, entry, S_IFDIR);
> +
> }
>
> static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
> @@ -925,6 +930,7 @@ static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
> {
> struct fuse_mount *fm = get_fuse_mount(dir);
> unsigned len = strlen(link) + 1;
> + struct dentry *de;
> FUSE_ARGS(args);
>
> args.opcode = FUSE_SYMLINK;
> @@ -934,7 +940,12 @@ static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
> args.in_args[1].value = entry->d_name.name;
> args.in_args[2].size = len;
> args.in_args[2].value = link;
> - return create_new_entry(idmap, fm, &args, dir, entry, S_IFLNK);
> + de = create_new_entry(idmap, fm, &args, dir, entry, S_IFLNK);
> + if (IS_ERR(de))
> + return PTR_ERR(de);
> + if (de)
> + dput(de);
> + return 0;
> }
>
> void fuse_flush_time_update(struct inode *inode)
> @@ -1117,7 +1128,7 @@ static int fuse_rename2(struct mnt_idmap *idmap, struct inode *olddir,
> static int fuse_link(struct dentry *entry, struct inode *newdir,
> struct dentry *newent)
> {
> - int err;
> + struct dentry *de;
> struct fuse_link_in inarg;
> struct inode *inode = d_inode(entry);
> struct fuse_mount *fm = get_fuse_mount(inode);
> @@ -1131,13 +1142,16 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
> args.in_args[0].value = &inarg;
> args.in_args[1].size = newent->d_name.len + 1;
> args.in_args[1].value = newent->d_name.name;
> - err = create_new_entry(&invalid_mnt_idmap, fm, &args, newdir, newent, inode->i_mode);
> - if (!err)
> + de = create_new_entry(&invalid_mnt_idmap, fm, &args, newdir, newent, inode->i_mode);
> + if (!IS_ERR(de)) {
> + if (de)
> + dput(de);
> + de = NULL;
> fuse_update_ctime_in_cache(inode);
> - else if (err == -EINTR)
> + } else if (PTR_ERR(de) == -EINTR)
> fuse_invalidate_attr(inode);
>
> - return err;
> + return PTR_ERR(de);
> }
>
> static void fuse_fillattr(struct mnt_idmap *idmap, struct inode *inode,
> diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> index 6fbbaaad1cd0..198a8cbaf5e5 100644
> --- a/fs/gfs2/inode.c
> +++ b/fs/gfs2/inode.c
> @@ -1248,14 +1248,15 @@ static int gfs2_symlink(struct mnt_idmap *idmap, struct inode *dir,
> * @dentry: The dentry of the new directory
> * @mode: The mode of the new directory
> *
> - * Returns: errno
> + * Returns: the dentry, or ERR_PTR(errno)
> */
>
> -static int gfs2_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *gfs2_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> unsigned dsize = gfs2_max_stuffed_size(GFS2_I(dir));
> - return gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0);
> +
> + return ERR_PTR(gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0));
> }
>
> /**
> diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
> index b75c26045df4..86a6b317b474 100644
> --- a/fs/hfs/dir.c
> +++ b/fs/hfs/dir.c
> @@ -219,26 +219,26 @@ static int hfs_create(struct mnt_idmap *idmap, struct inode *dir,
> * in a directory, given the inode for the parent directory and the
> * name (and its length) of the new directory.
> */
> -static int hfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *hfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct inode *inode;
> int res;
>
> inode = hfs_new_inode(dir, &dentry->d_name, S_IFDIR | mode);
> if (!inode)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
> if (res) {
> clear_nlink(inode);
> hfs_delete_inode(inode);
> iput(inode);
> - return res;
> + return ERR_PTR(res);
> }
> d_instantiate(dentry, inode);
> mark_inode_dirty(inode);
> - return 0;
> + return NULL;
> }
>
> /*
> diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
> index f5c4b3e31a1c..876bbb80fb4d 100644
> --- a/fs/hfsplus/dir.c
> +++ b/fs/hfsplus/dir.c
> @@ -523,10 +523,10 @@ static int hfsplus_create(struct mnt_idmap *idmap, struct inode *dir,
> return hfsplus_mknod(&nop_mnt_idmap, dir, dentry, mode, 0);
> }
>
> -static int hfsplus_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *hfsplus_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> - return hfsplus_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0);
> + return ERR_PTR(hfsplus_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0));
> }
>
> static int hfsplus_rename(struct mnt_idmap *idmap,
> diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
> index e0741e468956..ccbb48fe830d 100644
> --- a/fs/hostfs/hostfs_kern.c
> +++ b/fs/hostfs/hostfs_kern.c
> @@ -679,17 +679,17 @@ static int hostfs_symlink(struct mnt_idmap *idmap, struct inode *ino,
> return err;
> }
>
> -static int hostfs_mkdir(struct mnt_idmap *idmap, struct inode *ino,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *hostfs_mkdir(struct mnt_idmap *idmap, struct inode *ino,
> + struct dentry *dentry, umode_t mode)
> {
> char *file;
> int err;
>
> if ((file = dentry_name(dentry)) == NULL)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
> err = do_mkdir(file, mode);
> __putname(file);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
> diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
> index d0edf9ed33b6..e3cdc421dfba 100644
> --- a/fs/hpfs/namei.c
> +++ b/fs/hpfs/namei.c
> @@ -19,8 +19,8 @@ static void hpfs_update_directory_times(struct inode *dir)
> hpfs_write_inode_nolock(dir);
> }
>
> -static int hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> const unsigned char *name = dentry->d_name.name;
> unsigned len = dentry->d_name.len;
> @@ -35,7 +35,7 @@ static int hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> int r;
> struct hpfs_dirent dee;
> int err;
> - if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
> + if ((err = hpfs_chk_name(name, &len))) return ERR_PTR(err==-ENOENT ? -EINVAL : err);
> hpfs_lock(dir->i_sb);
> err = -ENOSPC;
> fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
> @@ -112,7 +112,7 @@ static int hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> hpfs_update_directory_times(dir);
> d_instantiate(dentry, result);
> hpfs_unlock(dir->i_sb);
> - return 0;
> + return NULL;
> bail3:
> iput(result);
> bail2:
> @@ -123,7 +123,7 @@ static int hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> hpfs_free_sectors(dir->i_sb, fno, 1);
> bail:
> hpfs_unlock(dir->i_sb);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int hpfs_create(struct mnt_idmap *idmap, struct inode *dir,
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 0fc179a59830..d98caedbb723 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -991,14 +991,14 @@ static int hugetlbfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
> return 0;
> }
>
> -static int hugetlbfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *hugetlbfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> int retval = hugetlbfs_mknod(idmap, dir, dentry,
> mode | S_IFDIR, 0);
> if (!retval)
> inc_nlink(dir);
> - return retval;
> + return ERR_PTR(retval);
> }
>
> static int hugetlbfs_create(struct mnt_idmap *idmap,
> diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
> index 2b2938970da3..dd91f725ded6 100644
> --- a/fs/jffs2/dir.c
> +++ b/fs/jffs2/dir.c
> @@ -32,8 +32,8 @@ static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
> static int jffs2_unlink (struct inode *,struct dentry *);
> static int jffs2_symlink (struct mnt_idmap *, struct inode *,
> struct dentry *, const char *);
> -static int jffs2_mkdir (struct mnt_idmap *, struct inode *,struct dentry *,
> - umode_t);
> +static struct dentry *jffs2_mkdir (struct mnt_idmap *, struct inode *,struct dentry *,
> + umode_t);
> static int jffs2_rmdir (struct inode *,struct dentry *);
> static int jffs2_mknod (struct mnt_idmap *, struct inode *,struct dentry *,
> umode_t,dev_t);
> @@ -446,8 +446,8 @@ static int jffs2_symlink (struct mnt_idmap *idmap, struct inode *dir_i,
> }
>
>
> -static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
> + struct dentry *dentry, umode_t mode)
> {
> struct jffs2_inode_info *f, *dir_f;
> struct jffs2_sb_info *c;
> @@ -464,7 +464,7 @@ static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
>
> ri = jffs2_alloc_raw_inode();
> if (!ri)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> c = JFFS2_SB_INFO(dir_i->i_sb);
>
> @@ -477,7 +477,7 @@ static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
>
> if (ret) {
> jffs2_free_raw_inode(ri);
> - return ret;
> + return ERR_PTR(ret);
> }
>
> inode = jffs2_new_inode(dir_i, mode, ri);
> @@ -485,7 +485,7 @@ static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
> if (IS_ERR(inode)) {
> jffs2_free_raw_inode(ri);
> jffs2_complete_reservation(c);
> - return PTR_ERR(inode);
> + return ERR_CAST(inode);
> }
>
> inode->i_op = &jffs2_dir_inode_operations;
> @@ -584,11 +584,11 @@ static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
> jffs2_complete_reservation(c);
>
> d_instantiate_new(dentry, inode);
> - return 0;
> + return NULL;
>
> fail:
> iget_failed(inode);
> - return ret;
> + return ERR_PTR(ret);
> }
>
> static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
> diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
> index fc8ede43afde..65a218eba8fa 100644
> --- a/fs/jfs/namei.c
> +++ b/fs/jfs/namei.c
> @@ -187,13 +187,13 @@ static int jfs_create(struct mnt_idmap *idmap, struct inode *dip,
> * dentry - dentry of child directory
> * mode - create mode (rwxrwxrwx).
> *
> - * RETURN: Errors from subroutines
> + * RETURN: ERR_PTR() of errors from subroutines.
> *
> * note:
> * EACCES: user needs search+write permission on the parent directory
> */
> -static int jfs_mkdir(struct mnt_idmap *idmap, struct inode *dip,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *jfs_mkdir(struct mnt_idmap *idmap, struct inode *dip,
> + struct dentry *dentry, umode_t mode)
> {
> int rc = 0;
> tid_t tid; /* transaction id */
> @@ -308,7 +308,7 @@ static int jfs_mkdir(struct mnt_idmap *idmap, struct inode *dip,
> out1:
>
> jfs_info("jfs_mkdir: rc:%d", rc);
> - return rc;
> + return ERR_PTR(rc);
> }
>
> /*
> diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
> index 5f0f8b95f44c..d296aad70800 100644
> --- a/fs/kernfs/dir.c
> +++ b/fs/kernfs/dir.c
> @@ -1230,24 +1230,24 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
> return d_splice_alias(inode, dentry);
> }
>
> -static int kernfs_iop_mkdir(struct mnt_idmap *idmap,
> - struct inode *dir, struct dentry *dentry,
> - umode_t mode)
> +static struct dentry *kernfs_iop_mkdir(struct mnt_idmap *idmap,
> + struct inode *dir, struct dentry *dentry,
> + umode_t mode)
> {
> struct kernfs_node *parent = dir->i_private;
> struct kernfs_syscall_ops *scops = kernfs_root(parent)->syscall_ops;
> int ret;
>
> if (!scops || !scops->mkdir)
> - return -EPERM;
> + return ERR_PTR(-EPERM);
>
> if (!kernfs_get_active(parent))
> - return -ENODEV;
> + return ERR_PTR(-ENODEV);
>
> ret = scops->mkdir(parent, dentry->d_name.name, mode);
>
> kernfs_put_active(parent);
> - return ret;
> + return ERR_PTR(ret);
> }
>
> static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry)
> diff --git a/fs/minix/namei.c b/fs/minix/namei.c
> index 5d9c1406fe27..8938536d8d3c 100644
> --- a/fs/minix/namei.c
> +++ b/fs/minix/namei.c
> @@ -104,15 +104,15 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
> return add_nondir(dentry, inode);
> }
>
> -static int minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct inode * inode;
> int err;
>
> inode = minix_new_inode(dir, S_IFDIR | mode);
> if (IS_ERR(inode))
> - return PTR_ERR(inode);
> + return ERR_CAST(inode);
>
> inode_inc_link_count(dir);
> minix_set_inode(inode, 0);
> @@ -128,7 +128,7 @@ static int minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> d_instantiate(dentry, inode);
> out:
> - return err;
> + return ERR_PTR(err);
>
> out_fail:
> inode_dec_link_count(inode);
> diff --git a/fs/namei.c b/fs/namei.c
> index 865a009fdebc..19d5ea340a18 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -4297,6 +4297,7 @@ int vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> {
> int error;
> unsigned max_links = dir->i_sb->s_max_links;
> + struct dentry *de;
>
> error = may_create(idmap, dir, dentry);
> if (error)
> @@ -4313,10 +4314,17 @@ int vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> if (max_links && dir->i_nlink >= max_links)
> return -EMLINK;
>
> - error = dir->i_op->mkdir(idmap, dir, dentry, mode);
> - if (!error)
> + de = dir->i_op->mkdir(idmap, dir, dentry, mode);
> + if (IS_ERR(de))
> + return PTR_ERR(de);
> + if (de) {
> + fsnotify_mkdir(dir, de);
> + /* Cannot return de yet */
> + dput(de);
> + } else
> fsnotify_mkdir(dir, dentry);
> - return error;
> +
> + return 0;
> }
> EXPORT_SYMBOL(vfs_mkdir);
>
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index 56cf16a72334..5700f73d48bc 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -2422,8 +2422,8 @@ EXPORT_SYMBOL_GPL(nfs_mknod);
> /*
> * See comments for nfs_proc_create regarding failed operations.
> */
> -int nfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +struct dentry *nfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct iattr attr;
> int error;
> @@ -2439,10 +2439,11 @@ int nfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> trace_nfs_mkdir_exit(dir, dentry, error);
> if (error != 0)
> goto out_err;
> - return 0;
> + /* FIXME - ->mkdir might have used an alternate dentry */
> + return NULL;
> out_err:
> d_drop(dentry);
> - return error;
> + return ERR_PTR(error);
> }
> EXPORT_SYMBOL_GPL(nfs_mkdir);
>
> diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
> index fae2c7ae4acc..1ac1d3eec517 100644
> --- a/fs/nfs/internal.h
> +++ b/fs/nfs/internal.h
> @@ -400,8 +400,8 @@ struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
> void nfs_d_prune_case_insensitive_aliases(struct inode *inode);
> int nfs_create(struct mnt_idmap *, struct inode *, struct dentry *,
> umode_t, bool);
> -int nfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
> - umode_t);
> +struct dentry *nfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
> + umode_t);
> int nfs_rmdir(struct inode *, struct dentry *);
> int nfs_unlink(struct inode *, struct dentry *);
> int nfs_symlink(struct mnt_idmap *, struct inode *, struct dentry *,
> diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
> index 953fbd5f0851..40f4b1a28705 100644
> --- a/fs/nilfs2/namei.c
> +++ b/fs/nilfs2/namei.c
> @@ -218,8 +218,8 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
> return err;
> }
>
> -static int nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct inode *inode;
> struct nilfs_transaction_info ti;
> @@ -227,7 +227,7 @@ static int nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
> if (err)
> - return err;
> + return ERR_PTR(err);
>
> inc_nlink(dir);
>
> @@ -258,7 +258,7 @@ static int nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> else
> nilfs_transaction_abort(dir->i_sb);
>
> - return err;
> + return ERR_PTR(err);
>
> out_fail:
> drop_nlink(inode);
> diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c
> index abf7e81584a9..652735a0b0c4 100644
> --- a/fs/ntfs3/namei.c
> +++ b/fs/ntfs3/namei.c
> @@ -201,11 +201,11 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
> /*
> * ntfs_mkdir- inode_operations::mkdir
> */
> -static int ntfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *ntfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> - return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode, 0,
> - NULL, 0, NULL);
> + return ERR_PTR(ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode, 0,
> + NULL, 0, NULL));
> }
>
> /*
> diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
> index 2a7f36643895..f632fbfe59e8 100644
> --- a/fs/ocfs2/dlmfs/dlmfs.c
> +++ b/fs/ocfs2/dlmfs/dlmfs.c
> @@ -402,10 +402,10 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
> * File creation. Allocate an inode, and we're done..
> */
> /* SMP-safe */
> -static int dlmfs_mkdir(struct mnt_idmap * idmap,
> - struct inode * dir,
> - struct dentry * dentry,
> - umode_t mode)
> +static struct dentry *dlmfs_mkdir(struct mnt_idmap * idmap,
> + struct inode * dir,
> + struct dentry * dentry,
> + umode_t mode)
> {
> int status;
> struct inode *inode = NULL;
> @@ -446,9 +446,11 @@ static int dlmfs_mkdir(struct mnt_idmap * idmap,
>
> status = 0;
> bail:
> - if (status < 0)
> + if (status < 0) {
> iput(inode);
> - return status;
> + return ERR_PTR(status);
> + }
> + return NULL;
> }
>
> static int dlmfs_create(struct mnt_idmap *idmap,
> diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
> index 0ec63a1a94b8..99278c8f0e24 100644
> --- a/fs/ocfs2/namei.c
> +++ b/fs/ocfs2/namei.c
> @@ -644,10 +644,10 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
> suballoc_loc, suballoc_bit);
> }
>
> -static int ocfs2_mkdir(struct mnt_idmap *idmap,
> - struct inode *dir,
> - struct dentry *dentry,
> - umode_t mode)
> +static struct dentry *ocfs2_mkdir(struct mnt_idmap *idmap,
> + struct inode *dir,
> + struct dentry *dentry,
> + umode_t mode)
> {
> int ret;
>
> @@ -657,7 +657,7 @@ static int ocfs2_mkdir(struct mnt_idmap *idmap,
> if (ret)
> mlog_errno(ret);
>
> - return ret;
> + return ERR_PTR(ret);
> }
>
> static int ocfs2_create(struct mnt_idmap *idmap,
> diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c
> index 6bda275826d6..2ed541fccf33 100644
> --- a/fs/omfs/dir.c
> +++ b/fs/omfs/dir.c
> @@ -279,10 +279,10 @@ static int omfs_add_node(struct inode *dir, struct dentry *dentry, umode_t mode)
> return err;
> }
>
> -static int omfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *omfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> - return omfs_add_node(dir, dentry, mode | S_IFDIR);
> + return ERR_PTR(omfs_add_node(dir, dentry, mode | S_IFDIR));
> }
>
> static int omfs_create(struct mnt_idmap *idmap, struct inode *dir,
> diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
> index 200558ec72f0..82395fe2b956 100644
> --- a/fs/orangefs/namei.c
> +++ b/fs/orangefs/namei.c
> @@ -300,8 +300,8 @@ static int orangefs_symlink(struct mnt_idmap *idmap,
> return ret;
> }
>
> -static int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct orangefs_inode_s *parent = ORANGEFS_I(dir);
> struct orangefs_kernel_op_s *new_op;
> @@ -312,7 +312,7 @@ static int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR);
> if (!new_op)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> new_op->upcall.req.mkdir.parent_refn = parent->refn;
>
> @@ -366,7 +366,7 @@ static int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> __orangefs_setattr(dir, &iattr);
> out:
> op_release(new_op);
> - return ret;
> + return ERR_PTR(ret);
> }
>
> static int orangefs_rename(struct mnt_idmap *idmap,
> diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
> index c9993ff66fc2..21c3aaf7b274 100644
> --- a/fs/overlayfs/dir.c
> +++ b/fs/overlayfs/dir.c
> @@ -282,7 +282,8 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
> * XXX: if we ever use ovl_obtain_alias() to decode directory
> * file handles, need to use ovl_get_inode_locked() and
> * d_instantiate_new() here to prevent from creating two
> - * hashed directory inode aliases.
> + * hashed directory inode aliases. We then need to return
> + * the obtained alias to ovl_mkdir().
> */
> inode = ovl_get_inode(dentry->d_sb, &oip);
> if (IS_ERR(inode))
> @@ -687,10 +688,10 @@ static int ovl_create(struct mnt_idmap *idmap, struct inode *dir,
> return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL);
> }
>
> -static int ovl_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *ovl_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> - return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL);
> + return ERR_PTR(ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL));
> }
>
> static int ovl_mknod(struct mnt_idmap *idmap, struct inode *dir,
> diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
> index 8006faaaf0ec..775fa905fda0 100644
> --- a/fs/ramfs/inode.c
> +++ b/fs/ramfs/inode.c
> @@ -119,13 +119,13 @@ ramfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
> return error;
> }
>
> -static int ramfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *ramfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> int retval = ramfs_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0);
> if (!retval)
> inc_nlink(dir);
> - return retval;
> + return ERR_PTR(retval);
> }
>
> static int ramfs_create(struct mnt_idmap *idmap, struct inode *dir,
> diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h
> index 831fee962c4d..8dea0cf3a8de 100644
> --- a/fs/smb/client/cifsfs.h
> +++ b/fs/smb/client/cifsfs.h
> @@ -59,8 +59,8 @@ extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
> extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
> extern int cifs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
> umode_t, dev_t);
> -extern int cifs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
> - umode_t);
> +extern struct dentry *cifs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
> + umode_t);
> extern int cifs_rmdir(struct inode *, struct dentry *);
> extern int cifs_rename2(struct mnt_idmap *, struct inode *,
> struct dentry *, struct inode *, struct dentry *,
> diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
> index 9cc31cf6ebd0..685a176f7f7e 100644
> --- a/fs/smb/client/inode.c
> +++ b/fs/smb/client/inode.c
> @@ -2194,8 +2194,8 @@ cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
> }
> #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
>
> -int cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,
> - struct dentry *direntry, umode_t mode)
> +struct dentry *cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,
> + struct dentry *direntry, umode_t mode)
> {
> int rc = 0;
> unsigned int xid;
> @@ -2211,10 +2211,10 @@ int cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,
>
> cifs_sb = CIFS_SB(inode->i_sb);
> if (unlikely(cifs_forced_shutdown(cifs_sb)))
> - return -EIO;
> + return ERR_PTR(-EIO);
> tlink = cifs_sb_tlink(cifs_sb);
> if (IS_ERR(tlink))
> - return PTR_ERR(tlink);
> + return ERR_CAST(tlink);
> tcon = tlink_tcon(tlink);
>
> xid = get_xid();
> @@ -2270,7 +2270,7 @@ int cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,
> free_dentry_path(page);
> free_xid(xid);
> cifs_put_tlink(tlink);
> - return rc;
> + return ERR_PTR(rc);
> }
>
> int cifs_rmdir(struct inode *inode, struct dentry *direntry)
> diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
> index fb8bd8437872..ba037727c1e6 100644
> --- a/fs/sysv/namei.c
> +++ b/fs/sysv/namei.c
> @@ -110,8 +110,8 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,
> return add_nondir(dentry, inode);
> }
>
> -static int sysv_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *sysv_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct inode * inode;
> int err;
> @@ -135,9 +135,9 @@ static int sysv_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> if (err)
> goto out_fail;
>
> - d_instantiate(dentry, inode);
> + d_instantiate(dentry, inode);
> out:
> - return err;
> + return ERR_PTR(err);
>
> out_fail:
> inode_dec_link_count(inode);
> diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
> index 53214499e384..cb1af30b49f5 100644
> --- a/fs/tracefs/inode.c
> +++ b/fs/tracefs/inode.c
> @@ -109,9 +109,9 @@ static char *get_dname(struct dentry *dentry)
> return name;
> }
>
> -static int tracefs_syscall_mkdir(struct mnt_idmap *idmap,
> - struct inode *inode, struct dentry *dentry,
> - umode_t mode)
> +static struct dentry *tracefs_syscall_mkdir(struct mnt_idmap *idmap,
> + struct inode *inode, struct dentry *dentry,
> + umode_t mode)
> {
> struct tracefs_inode *ti;
> char *name;
> @@ -119,7 +119,7 @@ static int tracefs_syscall_mkdir(struct mnt_idmap *idmap,
>
> name = get_dname(dentry);
> if (!name)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> /*
> * This is a new directory that does not take the default of
> @@ -141,7 +141,7 @@ static int tracefs_syscall_mkdir(struct mnt_idmap *idmap,
>
> kfree(name);
>
> - return ret;
> + return ERR_PTR(ret);
> }
>
> static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry)
> diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
> index fda82f3e16e8..3c3d3ad4fa6c 100644
> --- a/fs/ubifs/dir.c
> +++ b/fs/ubifs/dir.c
> @@ -1002,8 +1002,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
> return err;
> }
>
> -static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct inode *inode;
> struct ubifs_inode *dir_ui = ubifs_inode(dir);
> @@ -1023,7 +1023,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> err = ubifs_budget_space(c, &req);
> if (err)
> - return err;
> + return ERR_PTR(err);
>
> err = ubifs_prepare_create(dir, dentry, &nm);
> if (err)
> @@ -1060,7 +1060,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> ubifs_release_budget(c, &req);
> d_instantiate(dentry, inode);
> fscrypt_free_filename(&nm);
> - return 0;
> + return NULL;
>
> out_cancel:
> dir->i_size -= sz_change;
> @@ -1074,7 +1074,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> fscrypt_free_filename(&nm);
> out_budg:
> ubifs_release_budget(c, &req);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int ubifs_mknod(struct mnt_idmap *idmap, struct inode *dir,
> diff --git a/fs/udf/namei.c b/fs/udf/namei.c
> index 2cb49b6b0716..5f2e9a892bff 100644
> --- a/fs/udf/namei.c
> +++ b/fs/udf/namei.c
> @@ -419,8 +419,8 @@ static int udf_mknod(struct mnt_idmap *idmap, struct inode *dir,
> return udf_add_nondir(dentry, inode);
> }
>
> -static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct inode *inode;
> struct udf_fileident_iter iter;
> @@ -430,7 +430,7 @@ static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
>
> inode = udf_new_inode(dir, S_IFDIR | mode);
> if (IS_ERR(inode))
> - return PTR_ERR(inode);
> + return ERR_CAST(inode);
>
> iinfo = UDF_I(inode);
> inode->i_op = &udf_dir_inode_operations;
> @@ -439,7 +439,7 @@ static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> if (err) {
> clear_nlink(inode);
> discard_new_inode(inode);
> - return err;
> + return ERR_PTR(err);
> }
> set_nlink(inode, 2);
> iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
> @@ -456,7 +456,7 @@ static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> if (err) {
> clear_nlink(inode);
> discard_new_inode(inode);
> - return err;
> + return ERR_PTR(err);
> }
> iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
> iter.fi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
> @@ -471,7 +471,7 @@ static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> mark_inode_dirty(dir);
> d_instantiate_new(dentry, inode);
>
> - return 0;
> + return NULL;
> }
>
> static int empty_dir(struct inode *dir)
> diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
> index 38a024c8cccd..5b3c85c93242 100644
> --- a/fs/ufs/namei.c
> +++ b/fs/ufs/namei.c
> @@ -166,8 +166,8 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
> return error;
> }
>
> -static int ufs_mkdir(struct mnt_idmap * idmap, struct inode * dir,
> - struct dentry * dentry, umode_t mode)
> +static struct dentry *ufs_mkdir(struct mnt_idmap * idmap, struct inode * dir,
> + struct dentry * dentry, umode_t mode)
> {
> struct inode * inode;
> int err;
> @@ -194,7 +194,7 @@ static int ufs_mkdir(struct mnt_idmap * idmap, struct inode * dir,
> goto out_fail;
>
> d_instantiate_new(dentry, inode);
> - return 0;
> + return NULL;
>
> out_fail:
> inode_dec_link_count(inode);
> @@ -202,7 +202,7 @@ static int ufs_mkdir(struct mnt_idmap * idmap, struct inode * dir,
> discard_new_inode(inode);
> out_dir:
> inode_dec_link_count(dir);
> - return err;
> + return ERR_PTR(err);
> }
>
> static int ufs_unlink(struct inode *dir, struct dentry *dentry)
> diff --git a/fs/vboxsf/dir.c b/fs/vboxsf/dir.c
> index a859ac9b74ba..770e29ec3557 100644
> --- a/fs/vboxsf/dir.c
> +++ b/fs/vboxsf/dir.c
> @@ -303,11 +303,11 @@ static int vboxsf_dir_mkfile(struct mnt_idmap *idmap,
> return vboxsf_dir_create(parent, dentry, mode, false, excl, NULL);
> }
>
> -static int vboxsf_dir_mkdir(struct mnt_idmap *idmap,
> - struct inode *parent, struct dentry *dentry,
> - umode_t mode)
> +static struct dentry *vboxsf_dir_mkdir(struct mnt_idmap *idmap,
> + struct inode *parent, struct dentry *dentry,
> + umode_t mode)
> {
> - return vboxsf_dir_create(parent, dentry, mode, true, true, NULL);
> + return ERR_PTR(vboxsf_dir_create(parent, dentry, mode, true, true, NULL));
> }
>
> static int vboxsf_dir_atomic_open(struct inode *parent, struct dentry *dentry,
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index 40289fe6f5b2..a4480098d2bf 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -298,14 +298,14 @@ xfs_vn_create(
> return xfs_generic_create(idmap, dir, dentry, mode, 0, NULL);
> }
>
> -STATIC int
> +STATIC struct dentry *
> xfs_vn_mkdir(
> struct mnt_idmap *idmap,
> struct inode *dir,
> struct dentry *dentry,
> umode_t mode)
> {
> - return xfs_generic_create(idmap, dir, dentry, mode | S_IFDIR, 0, NULL);
> + return ERR_PTR(xfs_generic_create(idmap, dir, dentry, mode | S_IFDIR, 0, NULL));
> }
>
> STATIC struct dentry *
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 2c3b2f8a621f..45269608ee23 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -2211,8 +2211,8 @@ struct inode_operations {
> int (*unlink) (struct inode *,struct dentry *);
> int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,
> const char *);
> - int (*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,
> - umode_t);
> + struct dentry *(*mkdir) (struct mnt_idmap *, struct inode *,
> + struct dentry *, umode_t);
> int (*rmdir) (struct inode *,struct dentry *);
> int (*mknod) (struct mnt_idmap *, struct inode *,struct dentry *,
> umode_t,dev_t);
> diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
> index 9aaf5124648b..dc3aa91a6ba0 100644
> --- a/kernel/bpf/inode.c
> +++ b/kernel/bpf/inode.c
> @@ -150,14 +150,14 @@ static void bpf_dentry_finalize(struct dentry *dentry, struct inode *inode,
> inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
> }
>
> -static int bpf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *bpf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct inode *inode;
>
> inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFDIR);
> if (IS_ERR(inode))
> - return PTR_ERR(inode);
> + return ERR_CAST(inode);
>
> inode->i_op = &bpf_dir_iops;
> inode->i_fop = &simple_dir_operations;
> @@ -166,7 +166,7 @@ static int bpf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> inc_nlink(dir);
>
> bpf_dentry_finalize(dentry, inode, dir);
> - return 0;
> + return NULL;
> }
>
> struct map_iter {
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 4ea6109a8043..00ae0146e768 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -3889,16 +3889,16 @@ shmem_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
> return error;
> }
>
> -static int shmem_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *shmem_mkdir(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> int error;
>
> error = shmem_mknod(idmap, dir, dentry, mode | S_IFDIR, 0);
> if (error)
> - return error;
> + return ERR_PTR(error);
> inc_nlink(dir);
> - return 0;
> + return NULL;
> }
>
> static int shmem_create(struct mnt_idmap *idmap, struct inode *dir,
> diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
> index c07d150685d7..6039afae4bfc 100644
> --- a/security/apparmor/apparmorfs.c
> +++ b/security/apparmor/apparmorfs.c
> @@ -1795,8 +1795,8 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
> return error;
> }
>
> -static int ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, umode_t mode)
> +static struct dentry *ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
> + struct dentry *dentry, umode_t mode)
> {
> struct aa_ns *ns, *parent;
> /* TODO: improve permission check */
> @@ -1808,7 +1808,7 @@ static int ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
> AA_MAY_LOAD_POLICY);
> end_current_label_crit_section(label);
> if (error)
> - return error;
> + return ERR_PTR(error);
>
> parent = aa_get_ns(dir->i_private);
> AA_BUG(d_inode(ns_subns_dir(parent)) != dir);
> @@ -1843,7 +1843,7 @@ static int ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
> mutex_unlock(&parent->lock);
> aa_put_ns(parent);
>
> - return error;
> + return ERR_PTR(error);
> }
>
> static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
Reviewed-by: Jeff Layton <jlayton@...nel.org>
Powered by blists - more mailing lists