Skip to content

Commit e07c469

Browse files
Hugh Dickinsbrauner
authored andcommitted
tmpfs: track free_ispace instead of free_inodes
In preparation for assigning some inode space to extended attributes, keep track of free_ispace instead of number of free_inodes: as if one tmpfs inode (and accompanying dentry) occupies very approximately 1KiB. Unsigned long is large enough for free_ispace, on 64-bit and on 32-bit: but take care to enforce the maximum. And fix the nr_blocks maximum on 32-bit: S64_MAX would be too big for it there, so say LONG_MAX instead. Delete the incorrect limited<->unlimited blocks/inodes comment above shmem_reconfigure(): leave it to the error messages below to describe. Signed-off-by: Hugh Dickins <[email protected]> Reviewed-by: Jan Kara <[email protected]> Reviewed-by: Carlos Maiolino <[email protected]> Message-Id: <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 5de7597 commit e07c469

File tree

2 files changed

+18
-17
lines changed

2 files changed

+18
-17
lines changed

include/linux/shmem_fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct shmem_sb_info {
5454
unsigned long max_blocks; /* How many blocks are allowed */
5555
struct percpu_counter used_blocks; /* How many are allocated */
5656
unsigned long max_inodes; /* How many inodes are allowed */
57-
unsigned long free_inodes; /* How many are left for allocation */
57+
unsigned long free_ispace; /* How much ispace left for allocation */
5858
raw_spinlock_t stat_lock; /* Serialize shmem_sb_info changes */
5959
umode_t mode; /* Mount mode for root directory */
6060
unsigned char huge; /* Whether to try for hugepages */

mm/shmem.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ static struct vfsmount *shm_mnt;
9090
/* Pretend that each entry is of this size in directory's i_size */
9191
#define BOGO_DIRENT_SIZE 20
9292

93+
/* Pretend that one inode + its dentry occupy this much memory */
94+
#define BOGO_INODE_SIZE 1024
95+
9396
/* Symlink up to this size is kmalloc'ed instead of using a swappable page */
9497
#define SHORT_SYMLINK_LEN 128
9598

@@ -137,7 +140,8 @@ static unsigned long shmem_default_max_inodes(void)
137140
{
138141
unsigned long nr_pages = totalram_pages();
139142

140-
return min(nr_pages - totalhigh_pages(), nr_pages / 2);
143+
return min3(nr_pages - totalhigh_pages(), nr_pages / 2,
144+
ULONG_MAX / BOGO_INODE_SIZE);
141145
}
142146
#endif
143147

@@ -331,11 +335,11 @@ static int shmem_reserve_inode(struct super_block *sb, ino_t *inop)
331335
if (!(sb->s_flags & SB_KERNMOUNT)) {
332336
raw_spin_lock(&sbinfo->stat_lock);
333337
if (sbinfo->max_inodes) {
334-
if (!sbinfo->free_inodes) {
338+
if (sbinfo->free_ispace < BOGO_INODE_SIZE) {
335339
raw_spin_unlock(&sbinfo->stat_lock);
336340
return -ENOSPC;
337341
}
338-
sbinfo->free_inodes--;
342+
sbinfo->free_ispace -= BOGO_INODE_SIZE;
339343
}
340344
if (inop) {
341345
ino = sbinfo->next_ino++;
@@ -394,7 +398,7 @@ static void shmem_free_inode(struct super_block *sb)
394398
struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
395399
if (sbinfo->max_inodes) {
396400
raw_spin_lock(&sbinfo->stat_lock);
397-
sbinfo->free_inodes++;
401+
sbinfo->free_ispace += BOGO_INODE_SIZE;
398402
raw_spin_unlock(&sbinfo->stat_lock);
399403
}
400404
}
@@ -3158,7 +3162,7 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
31583162
}
31593163
if (sbinfo->max_inodes) {
31603164
buf->f_files = sbinfo->max_inodes;
3161-
buf->f_ffree = sbinfo->free_inodes;
3165+
buf->f_ffree = sbinfo->free_ispace / BOGO_INODE_SIZE;
31623166
}
31633167
/* else leave those fields 0 like simple_statfs */
31643168

@@ -3818,13 +3822,13 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
38183822
break;
38193823
case Opt_nr_blocks:
38203824
ctx->blocks = memparse(param->string, &rest);
3821-
if (*rest || ctx->blocks > S64_MAX)
3825+
if (*rest || ctx->blocks > LONG_MAX)
38223826
goto bad_value;
38233827
ctx->seen |= SHMEM_SEEN_BLOCKS;
38243828
break;
38253829
case Opt_nr_inodes:
38263830
ctx->inodes = memparse(param->string, &rest);
3827-
if (*rest)
3831+
if (*rest || ctx->inodes > ULONG_MAX / BOGO_INODE_SIZE)
38283832
goto bad_value;
38293833
ctx->seen |= SHMEM_SEEN_INODES;
38303834
break;
@@ -4005,21 +4009,17 @@ static int shmem_parse_options(struct fs_context *fc, void *data)
40054009

40064010
/*
40074011
* Reconfigure a shmem filesystem.
4008-
*
4009-
* Note that we disallow change from limited->unlimited blocks/inodes while any
4010-
* are in use; but we must separately disallow unlimited->limited, because in
4011-
* that case we have no record of how much is already in use.
40124012
*/
40134013
static int shmem_reconfigure(struct fs_context *fc)
40144014
{
40154015
struct shmem_options *ctx = fc->fs_private;
40164016
struct shmem_sb_info *sbinfo = SHMEM_SB(fc->root->d_sb);
4017-
unsigned long inodes;
4017+
unsigned long used_isp;
40184018
struct mempolicy *mpol = NULL;
40194019
const char *err;
40204020

40214021
raw_spin_lock(&sbinfo->stat_lock);
4022-
inodes = sbinfo->max_inodes - sbinfo->free_inodes;
4022+
used_isp = sbinfo->max_inodes * BOGO_INODE_SIZE - sbinfo->free_ispace;
40234023

40244024
if ((ctx->seen & SHMEM_SEEN_BLOCKS) && ctx->blocks) {
40254025
if (!sbinfo->max_blocks) {
@@ -4037,7 +4037,7 @@ static int shmem_reconfigure(struct fs_context *fc)
40374037
err = "Cannot retroactively limit inodes";
40384038
goto out;
40394039
}
4040-
if (ctx->inodes < inodes) {
4040+
if (ctx->inodes * BOGO_INODE_SIZE < used_isp) {
40414041
err = "Too few inodes for current use";
40424042
goto out;
40434043
}
@@ -4083,7 +4083,7 @@ static int shmem_reconfigure(struct fs_context *fc)
40834083
sbinfo->max_blocks = ctx->blocks;
40844084
if (ctx->seen & SHMEM_SEEN_INODES) {
40854085
sbinfo->max_inodes = ctx->inodes;
4086-
sbinfo->free_inodes = ctx->inodes - inodes;
4086+
sbinfo->free_ispace = ctx->inodes * BOGO_INODE_SIZE - used_isp;
40874087
}
40884088

40894089
/*
@@ -4214,7 +4214,8 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
42144214
sb->s_flags |= SB_NOUSER;
42154215
#endif
42164216
sbinfo->max_blocks = ctx->blocks;
4217-
sbinfo->free_inodes = sbinfo->max_inodes = ctx->inodes;
4217+
sbinfo->max_inodes = ctx->inodes;
4218+
sbinfo->free_ispace = sbinfo->max_inodes * BOGO_INODE_SIZE;
42184219
if (sb->s_flags & SB_KERNMOUNT) {
42194220
sbinfo->ino_batch = alloc_percpu(ino_t);
42204221
if (!sbinfo->ino_batch)

0 commit comments

Comments
 (0)