diff mbox series

[2/6] shmem: make shmem_get_inode() return ERR_PTR instead of NULL

Message ID 20230403084759.884681-3-cem@kernel.org (mailing list archive)
State Mainlined, archived
Headers show
Series shmem: Add user and group quota support for tmpfs | expand

Commit Message

Carlos Maiolino April 3, 2023, 8:47 a.m. UTC
From: Lukas Czerner <lczerner@redhat.com>

Make shmem_get_inode() return ERR_PTR instead of NULL on error. This will be
useful later when we introduce quota support.

There should be no functional change.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
---
 mm/shmem.c | 205 +++++++++++++++++++++++++++++------------------------
 1 file changed, 114 insertions(+), 91 deletions(-)

Comments

Jan Kara April 3, 2023, 10:23 a.m. UTC | #1
On Mon 03-04-23 10:47:55, cem@kernel.org wrote:
> From: Lukas Czerner <lczerner@redhat.com>
> 
> Make shmem_get_inode() return ERR_PTR instead of NULL on error. This will be
> useful later when we introduce quota support.
> 
> There should be no functional change.
> 
> Signed-off-by: Lukas Czerner <lczerner@redhat.com>
> Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>

One comment below:

> @@ -2958,21 +2967,24 @@ shmem_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
>  	      struct file *file, umode_t mode)
>  {
>  	struct inode *inode;
> -	int error = -ENOSPC;
> +	int error;
>  
>  	inode = shmem_get_inode(idmap, dir->i_sb, dir, mode, 0, VM_NORESERVE);
> -	if (inode) {
> -		error = security_inode_init_security(inode, dir,
> -						     NULL,
> -						     shmem_initxattrs, NULL);
> -		if (error && error != -EOPNOTSUPP)
> -			goto out_iput;
> -		error = simple_acl_create(dir, inode);
> -		if (error)
> -			goto out_iput;
> -		d_tmpfile(file, inode);
> -	}
> +
> +	if (IS_ERR(inode))
> +		return PTR_ERR(inode);

This doesn't look correct. Previously, we've called
finish_open_simple(file, error), now you just return error... Otherwise the
patch looks good to me.

								Honza
kernel test robot April 3, 2023, 9:10 p.m. UTC | #2
Hi,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.3-rc5]
[cannot apply to akpm-mm/mm-everything next-20230403]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/cem-kernel-org/shmem-make-shmem_inode_acct_block-return-error/20230403-165022
patch link:    https://lore.kernel.org/r/20230403084759.884681-3-cem%40kernel.org
patch subject: [PATCH 2/6] shmem: make shmem_get_inode() return ERR_PTR instead of NULL
config: arm-randconfig-r046-20230403 (https://download.01.org/0day-ci/archive/20230404/202304040420.J4BUN9E6-lkp@intel.com/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project 67409911353323ca5edf2049ef0df54132fa1ca7)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm cross compiling tool for clang build
        # apt-get install binutils-arm-linux-gnueabi
        # https://github.com/intel-lab-lkp/linux/commit/98aa926ee22a768f6a2dc8b0b897d018fc47497e
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review cem-kernel-org/shmem-make-shmem_inode_acct_block-return-error/20230403-165022
        git checkout 98aa926ee22a768f6a2dc8b0b897d018fc47497e
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304040420.J4BUN9E6-lkp@intel.com/

All errors (new ones prefixed by >>):

>> mm/shmem.c:4261:29: error: too many arguments to function call, expected 5, have 6
                                   S_IFREG | S_IRWXUGO, 0, flags);
                                                           ^~~~~
   mm/shmem.c:4231:29: note: 'shmem_get_inode' declared here
   static inline struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
                               ^
   1 error generated.


vim +4261 mm/shmem.c

^1da177e4c3f41 Linus Torvalds    2005-04-16  4241  
703321b60b605b Matthew Auld      2017-10-06  4242  static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, loff_t size,
c7277090927a5e Eric Paris        2013-12-02  4243  				       unsigned long flags, unsigned int i_flags)
^1da177e4c3f41 Linus Torvalds    2005-04-16  4244  {
^1da177e4c3f41 Linus Torvalds    2005-04-16  4245  	struct inode *inode;
93dec2da7b2349 Al Viro           2018-07-08  4246  	struct file *res;
^1da177e4c3f41 Linus Torvalds    2005-04-16  4247  
703321b60b605b Matthew Auld      2017-10-06  4248  	if (IS_ERR(mnt))
703321b60b605b Matthew Auld      2017-10-06  4249  		return ERR_CAST(mnt);
^1da177e4c3f41 Linus Torvalds    2005-04-16  4250  
285b2c4fdd69ea Hugh Dickins      2011-08-03  4251  	if (size < 0 || size > MAX_LFS_FILESIZE)
^1da177e4c3f41 Linus Torvalds    2005-04-16  4252  		return ERR_PTR(-EINVAL);
^1da177e4c3f41 Linus Torvalds    2005-04-16  4253  
^1da177e4c3f41 Linus Torvalds    2005-04-16  4254  	if (shmem_acct_size(flags, size))
^1da177e4c3f41 Linus Torvalds    2005-04-16  4255  		return ERR_PTR(-ENOMEM);
^1da177e4c3f41 Linus Torvalds    2005-04-16  4256  
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20  4257  	if (is_idmapped_mnt(mnt))
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20  4258  		return ERR_PTR(-EINVAL);
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20  4259  
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20  4260  	inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20 @4261  				S_IFREG | S_IRWXUGO, 0, flags);
98aa926ee22a76 Lukas Czerner     2023-04-03  4262  
98aa926ee22a76 Lukas Czerner     2023-04-03  4263  	if (IS_ERR(inode)) {
dac2d1f6cbfe3f Al Viro           2018-06-09  4264  		shmem_unacct_size(flags, size);
98aa926ee22a76 Lukas Czerner     2023-04-03  4265  		return ERR_CAST(inode);
dac2d1f6cbfe3f Al Viro           2018-06-09  4266  	}
c7277090927a5e Eric Paris        2013-12-02  4267  	inode->i_flags |= i_flags;
^1da177e4c3f41 Linus Torvalds    2005-04-16  4268  	inode->i_size = size;
6d6b77f163c7ea Miklos Szeredi    2011-10-28  4269  	clear_nlink(inode);	/* It is unlinked */
26567cdbbf1a6b Al Viro           2013-03-01  4270  	res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size));
93dec2da7b2349 Al Viro           2018-07-08  4271  	if (!IS_ERR(res))
93dec2da7b2349 Al Viro           2018-07-08  4272  		res = alloc_file_pseudo(inode, mnt, name, O_RDWR,
4b42af81f0d7f9 Al Viro           2009-08-05  4273  				&shmem_file_operations);
6b4d0b2793337c Al Viro           2013-02-14  4274  	if (IS_ERR(res))
93dec2da7b2349 Al Viro           2018-07-08  4275  		iput(inode);
6b4d0b2793337c Al Viro           2013-02-14  4276  	return res;
^1da177e4c3f41 Linus Torvalds    2005-04-16  4277  }
c7277090927a5e Eric Paris        2013-12-02  4278
kernel test robot April 4, 2023, 4:26 a.m. UTC | #3
Hi,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.3-rc5]
[cannot apply to akpm-mm/mm-everything next-20230403]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/cem-kernel-org/shmem-make-shmem_inode_acct_block-return-error/20230403-165022
patch link:    https://lore.kernel.org/r/20230403084759.884681-3-cem%40kernel.org
patch subject: [PATCH 2/6] shmem: make shmem_get_inode() return ERR_PTR instead of NULL
config: arm-randconfig-r033-20230403 (https://download.01.org/0day-ci/archive/20230404/202304041204.sEsaejmQ-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/98aa926ee22a768f6a2dc8b0b897d018fc47497e
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review cem-kernel-org/shmem-make-shmem_inode_acct_block-return-error/20230403-165022
        git checkout 98aa926ee22a768f6a2dc8b0b897d018fc47497e
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304041204.sEsaejmQ-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   mm/shmem.c: In function '__shmem_file_setup':
>> mm/shmem.c:4260:33: error: passing argument 1 of 'shmem_get_inode' from incompatible pointer type [-Werror=incompatible-pointer-types]
    4260 |         inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
         |                                 ^~~~~~~~~~~~~~
         |                                 |
         |                                 struct mnt_idmap *
   mm/shmem.c:4231:65: note: expected 'struct super_block *' but argument is of type 'struct mnt_idmap *'
    4231 | static inline struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
         |                                             ~~~~~~~~~~~~~~~~~~~~^~
   mm/shmem.c:4260:52: error: passing argument 2 of 'shmem_get_inode' from incompatible pointer type [-Werror=incompatible-pointer-types]
    4260 |         inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
         |                                                 ~~~^~~~~~~~
         |                                                    |
         |                                                    struct super_block *
   mm/shmem.c:4231:83: note: expected 'struct inode *' but argument is of type 'struct super_block *'
    4231 | static inline struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
         |                                                                     ~~~~~~~~~~~~~~^~~
   In file included from include/uapi/linux/posix_types.h:5,
                    from include/uapi/linux/types.h:14,
                    from include/linux/types.h:6,
                    from include/linux/kasan-checks.h:5,
                    from include/asm-generic/rwonce.h:26,
                    from ./arch/arm/include/generated/asm/rwonce.h:1,
                    from include/linux/compiler.h:247,
                    from include/linux/build_bug.h:5,
                    from include/linux/container_of.h:5,
                    from include/linux/list.h:5,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from mm/shmem.c:24:
>> include/linux/stddef.h:8:14: warning: passing argument 3 of 'shmem_get_inode' makes integer from pointer without a cast [-Wint-conversion]
       8 | #define NULL ((void *)0)
         |              ^~~~~~~~~~~
         |              |
         |              void *
   mm/shmem.c:4260:62: note: in expansion of macro 'NULL'
    4260 |         inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
         |                                                              ^~~~
   mm/shmem.c:4232:53: note: expected 'umode_t' {aka 'short unsigned int'} but argument is of type 'void *'
    4232 |                                             umode_t mode, dev_t dev, unsigned long flags)
         |                                             ~~~~~~~~^~~~
>> mm/shmem.c:4260:17: error: too many arguments to function 'shmem_get_inode'
    4260 |         inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
         |                 ^~~~~~~~~~~~~~~
   mm/shmem.c:4231:29: note: declared here
    4231 | static inline struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
         |                             ^~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +/shmem_get_inode +4260 mm/shmem.c

^1da177e4c3f41 Linus Torvalds    2005-04-16  4241  
703321b60b605b Matthew Auld      2017-10-06  4242  static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, loff_t size,
c7277090927a5e Eric Paris        2013-12-02  4243  				       unsigned long flags, unsigned int i_flags)
^1da177e4c3f41 Linus Torvalds    2005-04-16  4244  {
^1da177e4c3f41 Linus Torvalds    2005-04-16  4245  	struct inode *inode;
93dec2da7b2349 Al Viro           2018-07-08  4246  	struct file *res;
^1da177e4c3f41 Linus Torvalds    2005-04-16  4247  
703321b60b605b Matthew Auld      2017-10-06  4248  	if (IS_ERR(mnt))
703321b60b605b Matthew Auld      2017-10-06  4249  		return ERR_CAST(mnt);
^1da177e4c3f41 Linus Torvalds    2005-04-16  4250  
285b2c4fdd69ea Hugh Dickins      2011-08-03  4251  	if (size < 0 || size > MAX_LFS_FILESIZE)
^1da177e4c3f41 Linus Torvalds    2005-04-16  4252  		return ERR_PTR(-EINVAL);
^1da177e4c3f41 Linus Torvalds    2005-04-16  4253  
^1da177e4c3f41 Linus Torvalds    2005-04-16  4254  	if (shmem_acct_size(flags, size))
^1da177e4c3f41 Linus Torvalds    2005-04-16  4255  		return ERR_PTR(-ENOMEM);
^1da177e4c3f41 Linus Torvalds    2005-04-16  4256  
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20  4257  	if (is_idmapped_mnt(mnt))
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20  4258  		return ERR_PTR(-EINVAL);
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20  4259  
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20 @4260  	inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
7a80e5b8c6fa7d Giuseppe Scrivano 2023-01-20  4261  				S_IFREG | S_IRWXUGO, 0, flags);
98aa926ee22a76 Lukas Czerner     2023-04-03  4262  
98aa926ee22a76 Lukas Czerner     2023-04-03  4263  	if (IS_ERR(inode)) {
dac2d1f6cbfe3f Al Viro           2018-06-09  4264  		shmem_unacct_size(flags, size);
98aa926ee22a76 Lukas Czerner     2023-04-03  4265  		return ERR_CAST(inode);
dac2d1f6cbfe3f Al Viro           2018-06-09  4266  	}
c7277090927a5e Eric Paris        2013-12-02  4267  	inode->i_flags |= i_flags;
^1da177e4c3f41 Linus Torvalds    2005-04-16  4268  	inode->i_size = size;
6d6b77f163c7ea Miklos Szeredi    2011-10-28  4269  	clear_nlink(inode);	/* It is unlinked */
26567cdbbf1a6b Al Viro           2013-03-01  4270  	res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size));
93dec2da7b2349 Al Viro           2018-07-08  4271  	if (!IS_ERR(res))
93dec2da7b2349 Al Viro           2018-07-08  4272  		res = alloc_file_pseudo(inode, mnt, name, O_RDWR,
4b42af81f0d7f9 Al Viro           2009-08-05  4273  				&shmem_file_operations);
6b4d0b2793337c Al Viro           2013-02-14  4274  	if (IS_ERR(res))
93dec2da7b2349 Al Viro           2018-07-08  4275  		iput(inode);
6b4d0b2793337c Al Viro           2013-02-14  4276  	return res;
^1da177e4c3f41 Linus Torvalds    2005-04-16  4277  }
c7277090927a5e Eric Paris        2013-12-02  4278
Carlos Maiolino April 11, 2023, 7:47 a.m. UTC | #4
Hi Honza.

My apologies it took a while to get back to you on this one, I was accumulating
reviews before running through all of them.


> >  	inode = shmem_get_inode(idmap, dir->i_sb, dir, mode, 0, VM_NORESERVE);
> > -	if (inode) {
> > -		error = security_inode_init_security(inode, dir,
> > -						     NULL,
> > -						     shmem_initxattrs, NULL);
> > -		if (error && error != -EOPNOTSUPP)
> > -			goto out_iput;
> > -		error = simple_acl_create(dir, inode);
> > -		if (error)
> > -			goto out_iput;
> > -		d_tmpfile(file, inode);
> > -	}
> > +
> > +	if (IS_ERR(inode))
> > +		return PTR_ERR(inode);
> 
> This doesn't look correct. Previously, we've called
> finish_open_simple(file, error), now you just return error... Otherwise the
> patch looks good to me.

I see what you mean. But, finish_open_simple() simply does:

	if (error)
		return error;

So, calling it with a non-zero value for error at most will just add another
function call into the stack.
I'm not opposed to still call finish_open_simple() but I don't think it adds
anything.

If you prefer it being called. I thought about adding a new label, something
like:

	if (IS_ERR(inode))
		goto err_out;
	.
	.
	.
	d_tmpfile(file, inode)
err_out:
	return finish_open_simple(file, error)
.
.
.

Would it work for you?

> 
> 								Honza
> --
> Jan Kara <jack@suse.com>
> SUSE Labs, CR
Jan Kara April 11, 2023, 8:14 a.m. UTC | #5
Hi!

On Tue 11-04-23 09:47:08, Carlos Maiolino wrote:
> My apologies it took a while to get back to you on this one, I was
> accumulating reviews before running through all of them.

Sure, that is fine.

> > >  	inode = shmem_get_inode(idmap, dir->i_sb, dir, mode, 0, VM_NORESERVE);
> > > -	if (inode) {
> > > -		error = security_inode_init_security(inode, dir,
> > > -						     NULL,
> > > -						     shmem_initxattrs, NULL);
> > > -		if (error && error != -EOPNOTSUPP)
> > > -			goto out_iput;
> > > -		error = simple_acl_create(dir, inode);
> > > -		if (error)
> > > -			goto out_iput;
> > > -		d_tmpfile(file, inode);
> > > -	}
> > > +
> > > +	if (IS_ERR(inode))
> > > +		return PTR_ERR(inode);
> > 
> > This doesn't look correct. Previously, we've called
> > finish_open_simple(file, error), now you just return error... Otherwise the
> > patch looks good to me.
> 
> I see what you mean. But, finish_open_simple() simply does:
> 
> 	if (error)
> 		return error;
> 
> So, calling it with a non-zero value for error at most will just add another
> function call into the stack.

I see, I didn't look inside finish_open_simple() :). Well, it is at least
inline function so actually no function call.

> I'm not opposed to still call finish_open_simple() but I don't think it adds
> anything.

Yeah, the value of the call is questionable but given it takes 'error'
argument only so that it could do that if (error) return error; dance, it
seems to be very much expected it is called in error cases as well.

> If you prefer it being called. I thought about adding a new label, something
> like:
> 
> 	if (IS_ERR(inode))
> 		goto err_out;
> 	.
> 	.
> 	.
> 	d_tmpfile(file, inode)
> err_out:
> 	return finish_open_simple(file, error)
> .
> .
> .
> 
> Would it work for you?

Yeah, I'd prefer we keep calling finish_open_simple(). Adding a label for
it is fine by me.

								Honza
Carlos Maiolino April 11, 2023, 8:41 a.m. UTC | #6
On Tue, Apr 11, 2023 at 10:14:45AM +0200, Jan Kara wrote:
> 
> Hi!
> 
> On Tue 11-04-23 09:47:08, Carlos Maiolino wrote:
> > My apologies it took a while to get back to you on this one, I was
> > accumulating reviews before running through all of them.
> 
> Sure, that is fine.
> 
> > > >  	inode = shmem_get_inode(idmap, dir->i_sb, dir, mode, 0, VM_NORESERVE);
> > > > -	if (inode) {
> > > > -		error = security_inode_init_security(inode, dir,
> > > > -						     NULL,
> > > > -						     shmem_initxattrs, NULL);
> > > > -		if (error && error != -EOPNOTSUPP)
> > > > -			goto out_iput;
> > > > -		error = simple_acl_create(dir, inode);
> > > > -		if (error)
> > > > -			goto out_iput;
> > > > -		d_tmpfile(file, inode);
> > > > -	}
> > > > +
> > > > +	if (IS_ERR(inode))
> > > > +		return PTR_ERR(inode);
> > >
> > > This doesn't look correct. Previously, we've called
> > > finish_open_simple(file, error), now you just return error... Otherwise the
> > > patch looks good to me.
> >
> > I see what you mean. But, finish_open_simple() simply does:
> >
> > 	if (error)
> > 		return error;
> >
> > So, calling it with a non-zero value for error at most will just add another
> > function call into the stack.
> 
> I see, I didn't look inside finish_open_simple() :). Well, it is at least
> inline function so actually no function call.

Great, I didn't notice it's an inline function :D

.
.
.
> Yeah, I'd prefer we keep calling finish_open_simple(). Adding a label for
> it is fine by me.

Ok, I'm updating the series today, hopefully I'll send the new version today or
tomorrow.

Thanks for the reviews!
diff mbox series

Patch

diff --git a/mm/shmem.c b/mm/shmem.c
index 0e63ea5f6ce69..88e13930fc013 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2354,65 +2354,71 @@  static struct inode *shmem_get_inode(struct mnt_idmap *idmap, struct super_block
 	struct shmem_inode_info *info;
 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
 	ino_t ino;
+	int err;
+
+	err = shmem_reserve_inode(sb, &ino);
+	if (err)
+		return ERR_PTR(err);
 
-	if (shmem_reserve_inode(sb, &ino))
-		return NULL;
 
 	inode = new_inode(sb);
-	if (inode) {
-		inode->i_ino = ino;
-		inode_init_owner(idmap, inode, dir, mode);
-		inode->i_blocks = 0;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
-		inode->i_generation = get_random_u32();
-		info = SHMEM_I(inode);
-		memset(info, 0, (char *)inode - (char *)info);
-		spin_lock_init(&info->lock);
-		atomic_set(&info->stop_eviction, 0);
-		info->seals = F_SEAL_SEAL;
-		info->flags = flags & VM_NORESERVE;
-		info->i_crtime = inode->i_mtime;
-		info->fsflags = (dir == NULL) ? 0 :
-			SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED;
-		if (info->fsflags)
-			shmem_set_inode_flags(inode, info->fsflags);
-		INIT_LIST_HEAD(&info->shrinklist);
-		INIT_LIST_HEAD(&info->swaplist);
-		simple_xattrs_init(&info->xattrs);
-		cache_no_acl(inode);
-		mapping_set_large_folios(inode->i_mapping);
-
-		switch (mode & S_IFMT) {
-		default:
-			inode->i_op = &shmem_special_inode_operations;
-			init_special_inode(inode, mode, dev);
-			break;
-		case S_IFREG:
-			inode->i_mapping->a_ops = &shmem_aops;
-			inode->i_op = &shmem_inode_operations;
-			inode->i_fop = &shmem_file_operations;
-			mpol_shared_policy_init(&info->policy,
-						 shmem_get_sbmpol(sbinfo));
-			break;
-		case S_IFDIR:
-			inc_nlink(inode);
-			/* Some things misbehave if size == 0 on a directory */
-			inode->i_size = 2 * BOGO_DIRENT_SIZE;
-			inode->i_op = &shmem_dir_inode_operations;
-			inode->i_fop = &simple_dir_operations;
-			break;
-		case S_IFLNK:
-			/*
-			 * Must not load anything in the rbtree,
-			 * mpol_free_shared_policy will not be called.
-			 */
-			mpol_shared_policy_init(&info->policy, NULL);
-			break;
-		}
 
-		lockdep_annotate_inode_mutex_key(inode);
-	} else
+	if (!inode) {
 		shmem_free_inode(sb);
+		return ERR_PTR(-ENOSPC);
+	}
+
+	inode->i_ino = ino;
+	inode_init_owner(idmap, inode, dir, mode);
+	inode->i_blocks = 0;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
+	inode->i_generation = get_random_u32();
+	info = SHMEM_I(inode);
+	memset(info, 0, (char *)inode - (char *)info);
+	spin_lock_init(&info->lock);
+	atomic_set(&info->stop_eviction, 0);
+	info->seals = F_SEAL_SEAL;
+	info->flags = flags & VM_NORESERVE;
+	info->i_crtime = inode->i_mtime;
+	info->fsflags = (dir == NULL) ? 0 :
+		SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED;
+	if (info->fsflags)
+		shmem_set_inode_flags(inode, info->fsflags);
+	INIT_LIST_HEAD(&info->shrinklist);
+	INIT_LIST_HEAD(&info->swaplist);
+	simple_xattrs_init(&info->xattrs);
+	cache_no_acl(inode);
+	mapping_set_large_folios(inode->i_mapping);
+
+	switch (mode & S_IFMT) {
+	default:
+		inode->i_op = &shmem_special_inode_operations;
+		init_special_inode(inode, mode, dev);
+		break;
+	case S_IFREG:
+		inode->i_mapping->a_ops = &shmem_aops;
+		inode->i_op = &shmem_inode_operations;
+		inode->i_fop = &shmem_file_operations;
+		mpol_shared_policy_init(&info->policy,
+					 shmem_get_sbmpol(sbinfo));
+		break;
+	case S_IFDIR:
+		inc_nlink(inode);
+		/* Some things misbehave if size == 0 on a directory */
+		inode->i_size = 2 * BOGO_DIRENT_SIZE;
+		inode->i_op = &shmem_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
+		break;
+	case S_IFLNK:
+		/*
+		 * Must not load anything in the rbtree,
+		 * mpol_free_shared_policy will not be called.
+		 */
+		mpol_shared_policy_init(&info->policy, NULL);
+		break;
+	}
+
+	lockdep_annotate_inode_mutex_key(inode);
 	return inode;
 }
 
@@ -2927,27 +2933,30 @@  shmem_mknod(struct mnt_idmap *idmap, struct inode *dir,
 	    struct dentry *dentry, umode_t mode, dev_t dev)
 {
 	struct inode *inode;
-	int error = -ENOSPC;
+	int error;
 
 	inode = shmem_get_inode(idmap, dir->i_sb, dir, mode, dev, VM_NORESERVE);
-	if (inode) {
-		error = simple_acl_create(dir, inode);
-		if (error)
-			goto out_iput;
-		error = security_inode_init_security(inode, dir,
-						     &dentry->d_name,
-						     shmem_initxattrs, NULL);
-		if (error && error != -EOPNOTSUPP)
-			goto out_iput;
 
-		error = 0;
-		dir->i_size += BOGO_DIRENT_SIZE;
-		dir->i_ctime = dir->i_mtime = current_time(dir);
-		inode_inc_iversion(dir);
-		d_instantiate(dentry, inode);
-		dget(dentry); /* Extra count - pin the dentry in core */
-	}
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	error = simple_acl_create(dir, inode);
+	if (error)
+		goto out_iput;
+	error = security_inode_init_security(inode, dir,
+					     &dentry->d_name,
+					     shmem_initxattrs, NULL);
+	if (error && error != -EOPNOTSUPP)
+		goto out_iput;
+
+	error = 0;
+	dir->i_size += BOGO_DIRENT_SIZE;
+	dir->i_ctime = dir->i_mtime = current_time(dir);
+	inode_inc_iversion(dir);
+	d_instantiate(dentry, inode);
+	dget(dentry); /* Extra count - pin the dentry in core */
 	return error;
+
 out_iput:
 	iput(inode);
 	return error;
@@ -2958,21 +2967,24 @@  shmem_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
 	      struct file *file, umode_t mode)
 {
 	struct inode *inode;
-	int error = -ENOSPC;
+	int error;
 
 	inode = shmem_get_inode(idmap, dir->i_sb, dir, mode, 0, VM_NORESERVE);
-	if (inode) {
-		error = security_inode_init_security(inode, dir,
-						     NULL,
-						     shmem_initxattrs, NULL);
-		if (error && error != -EOPNOTSUPP)
-			goto out_iput;
-		error = simple_acl_create(dir, inode);
-		if (error)
-			goto out_iput;
-		d_tmpfile(file, inode);
-	}
+
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	error = security_inode_init_security(inode, dir,
+					     NULL,
+					     shmem_initxattrs, NULL);
+	if (error && error != -EOPNOTSUPP)
+		goto out_iput;
+	error = simple_acl_create(dir, inode);
+	if (error)
+		goto out_iput;
+	d_tmpfile(file, inode);
 	return finish_open_simple(file, error);
+
 out_iput:
 	iput(inode);
 	return error;
@@ -3146,8 +3158,9 @@  static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
 
 	inode = shmem_get_inode(idmap, dir->i_sb, dir, S_IFLNK | 0777, 0,
 				VM_NORESERVE);
-	if (!inode)
-		return -ENOSPC;
+
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
 
 	error = security_inode_init_security(inode, dir, &dentry->d_name,
 					     shmem_initxattrs, NULL);
@@ -3762,12 +3775,13 @@  static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
 	struct shmem_options *ctx = fc->fs_private;
 	struct inode *inode;
 	struct shmem_sb_info *sbinfo;
+	int error = -ENOMEM;
 
 	/* Round up to L1_CACHE_BYTES to resist false sharing */
 	sbinfo = kzalloc(max((int)sizeof(struct shmem_sb_info),
 				L1_CACHE_BYTES), GFP_KERNEL);
 	if (!sbinfo)
-		return -ENOMEM;
+		return error;
 
 	sb->s_fs_info = sbinfo;
 
@@ -3829,8 +3843,10 @@  static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	inode = shmem_get_inode(&nop_mnt_idmap, sb, NULL, S_IFDIR | sbinfo->mode, 0,
 				VM_NORESERVE);
-	if (!inode)
+	if (IS_ERR(inode)) {
+		error = PTR_ERR(inode);
 		goto failed;
+	}
 	inode->i_uid = sbinfo->uid;
 	inode->i_gid = sbinfo->gid;
 	sb->s_root = d_make_root(inode);
@@ -3840,7 +3856,7 @@  static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
 
 failed:
 	shmem_put_super(sb);
-	return -ENOMEM;
+	return error;
 }
 
 static int shmem_get_tree(struct fs_context *fc)
@@ -4209,10 +4225,16 @@  EXPORT_SYMBOL_GPL(shmem_truncate_range);
 #define shmem_vm_ops				generic_file_vm_ops
 #define shmem_anon_vm_ops			generic_file_vm_ops
 #define shmem_file_operations			ramfs_file_operations
-#define shmem_get_inode(idmap, sb, dir, mode, dev, flags) ramfs_get_inode(sb, dir, mode, dev)
 #define shmem_acct_size(flags, size)		0
 #define shmem_unacct_size(flags, size)		do {} while (0)
 
+static inline struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
+					    umode_t mode, dev_t dev, unsigned long flags)
+{
+	struct inode *inode = ramfs_get_inode(sb, dir, mode, dev);
+	return inode ? inode : ERR_PTR(-ENOSPC);
+}
+
 #endif /* CONFIG_SHMEM */
 
 /* common code */
@@ -4237,9 +4259,10 @@  static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
 
 	inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
 				S_IFREG | S_IRWXUGO, 0, flags);
-	if (unlikely(!inode)) {
+
+	if (IS_ERR(inode)) {
 		shmem_unacct_size(flags, size);
-		return ERR_PTR(-ENOSPC);
+		return ERR_CAST(inode);
 	}
 	inode->i_flags |= i_flags;
 	inode->i_size = size;