Re: [PATCH 1/3] Change inode_operations.mkdir to return struct dentry *

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Feb 17, 2025 at 04:30:03PM +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.

Imho, this example also belongs into Documentation/.

> 
> 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
> - 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@xxxxxxx>
> ---

Thanks, this is a great improvement and makes mkdir a lot easier to
understand imho.

Two nits below.

>  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

        ^^^^^^^                                      ^^^^^^^^^^^^^^^^^
        s/much/must/                                 s/is/if/ ?

> +	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)
> -- 
> 2.47.1
> 




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux