Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 2460
b: refs/heads/master
c: 0edd73b
h: refs/heads/master
v: v3
  • Loading branch information
Hugh Dickins authored and Linus Torvalds committed Jun 22, 2005
1 parent 809e0ba commit 9338f52
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 77 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 65ed0b337bd2b47097cf6c772f024772513b7b0d
refs/heads/master: 0edd73b33426df61b1d8a0a50d1f2ec097500abb
6 changes: 3 additions & 3 deletions trunk/Documentation/filesystems/tmpfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ can be changed on remount. The size parameter also accepts a suffix %
to limit this tmpfs instance to that percentage of your physical RAM:
the default, when neither size nor nr_blocks is specified, is size=50%

If both nr_blocks (or size) and nr_inodes are set to 0, neither blocks
nor inodes will be limited in that instance. It is generally unwise to
If nr_blocks=0 (or size=0), blocks will not be limited in that instance;
if nr_inodes=0, inodes will not be limited. It is generally unwise to
mount with such options, since it allows any user with write access to
use up all the memory on the machine; but enhances the scalability of
that instance in a system with many cpus making intensive use of it.
Expand All @@ -97,4 +97,4 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
Author:
Christoph Rohland <cr@sap.com>, 1.12.01
Updated:
Hugh Dickins <hugh@veritas.com>, 01 September 2004
Hugh Dickins <hugh@veritas.com>, 13 March 2005
143 changes: 70 additions & 73 deletions trunk/mm/shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* 2000-2001 Christoph Rohland
* 2000-2001 SAP AG
* 2002 Red Hat Inc.
* Copyright (C) 2002-2004 Hugh Dickins.
* Copyright (C) 2002-2004 VERITAS Software Corporation.
* Copyright (C) 2002-2005 Hugh Dickins.
* Copyright (C) 2002-2005 VERITAS Software Corporation.
* Copyright (C) 2004 Andi Kleen, SuSE Labs
*
* Extended attribute support for tmpfs:
Expand Down Expand Up @@ -194,7 +194,7 @@ static DEFINE_SPINLOCK(shmem_swaplist_lock);
static void shmem_free_blocks(struct inode *inode, long pages)
{
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
if (sbinfo) {
if (sbinfo->max_blocks) {
spin_lock(&sbinfo->stat_lock);
sbinfo->free_blocks += pages;
inode->i_blocks -= pages*BLOCKS_PER_PAGE;
Expand Down Expand Up @@ -357,7 +357,7 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long
* page (and perhaps indirect index pages) yet to allocate:
* a waste to allocate index if we cannot allocate data.
*/
if (sbinfo) {
if (sbinfo->max_blocks) {
spin_lock(&sbinfo->stat_lock);
if (sbinfo->free_blocks <= 1) {
spin_unlock(&sbinfo->stat_lock);
Expand Down Expand Up @@ -677,8 +677,8 @@ static void shmem_delete_inode(struct inode *inode)
spin_unlock(&shmem_swaplist_lock);
}
}
if (sbinfo) {
BUG_ON(inode->i_blocks);
BUG_ON(inode->i_blocks);
if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
sbinfo->free_inodes++;
spin_unlock(&sbinfo->stat_lock);
Expand Down Expand Up @@ -1080,7 +1080,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
} else {
shmem_swp_unmap(entry);
sbinfo = SHMEM_SB(inode->i_sb);
if (sbinfo) {
if (sbinfo->max_blocks) {
spin_lock(&sbinfo->stat_lock);
if (sbinfo->free_blocks == 0 ||
shmem_acct_block(info->flags)) {
Expand Down Expand Up @@ -1269,7 +1269,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
struct shmem_inode_info *info;
struct shmem_sb_info *sbinfo = SHMEM_SB(sb);

if (sbinfo) {
if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
if (!sbinfo->free_inodes) {
spin_unlock(&sbinfo->stat_lock);
Expand Down Expand Up @@ -1319,7 +1319,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
mpol_shared_policy_init(&info->policy);
break;
}
} else if (sbinfo) {
} else if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
sbinfo->free_inodes++;
spin_unlock(&sbinfo->stat_lock);
Expand All @@ -1328,31 +1328,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
}

#ifdef CONFIG_TMPFS

static int shmem_set_size(struct shmem_sb_info *sbinfo,
unsigned long max_blocks, unsigned long max_inodes)
{
int error;
unsigned long blocks, inodes;

spin_lock(&sbinfo->stat_lock);
blocks = sbinfo->max_blocks - sbinfo->free_blocks;
inodes = sbinfo->max_inodes - sbinfo->free_inodes;
error = -EINVAL;
if (max_blocks < blocks)
goto out;
if (max_inodes < inodes)
goto out;
error = 0;
sbinfo->max_blocks = max_blocks;
sbinfo->free_blocks = max_blocks - blocks;
sbinfo->max_inodes = max_inodes;
sbinfo->free_inodes = max_inodes - inodes;
out:
spin_unlock(&sbinfo->stat_lock);
return error;
}

static struct inode_operations shmem_symlink_inode_operations;
static struct inode_operations shmem_symlink_inline_operations;

Expand Down Expand Up @@ -1607,15 +1582,17 @@ static int shmem_statfs(struct super_block *sb, struct kstatfs *buf)
buf->f_type = TMPFS_MAGIC;
buf->f_bsize = PAGE_CACHE_SIZE;
buf->f_namelen = NAME_MAX;
if (sbinfo) {
spin_lock(&sbinfo->stat_lock);
spin_lock(&sbinfo->stat_lock);
if (sbinfo->max_blocks) {
buf->f_blocks = sbinfo->max_blocks;
buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
}
if (sbinfo->max_inodes) {
buf->f_files = sbinfo->max_inodes;
buf->f_ffree = sbinfo->free_inodes;
spin_unlock(&sbinfo->stat_lock);
}
/* else leave those fields 0 like simple_statfs */
spin_unlock(&sbinfo->stat_lock);
return 0;
}

Expand Down Expand Up @@ -1672,7 +1649,7 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
* but each new link needs a new dentry, pinning lowmem, and
* tmpfs dentries cannot be pruned until they are unlinked.
*/
if (sbinfo) {
if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
if (!sbinfo->free_inodes) {
spin_unlock(&sbinfo->stat_lock);
Expand All @@ -1697,7 +1674,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)

if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
if (sbinfo) {
if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
sbinfo->free_inodes++;
spin_unlock(&sbinfo->stat_lock);
Expand Down Expand Up @@ -1921,22 +1898,42 @@ static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid,
static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
{
struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
unsigned long max_blocks = 0;
unsigned long max_inodes = 0;
unsigned long max_blocks = sbinfo->max_blocks;
unsigned long max_inodes = sbinfo->max_inodes;
unsigned long blocks;
unsigned long inodes;
int error = -EINVAL;

if (shmem_parse_options(data, NULL, NULL, NULL,
&max_blocks, &max_inodes))
return error;

if (sbinfo) {
max_blocks = sbinfo->max_blocks;
max_inodes = sbinfo->max_inodes;
}
if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks, &max_inodes))
return -EINVAL;
/* Keep it simple: disallow limited <-> unlimited remount */
if ((max_blocks || max_inodes) == !sbinfo)
return -EINVAL;
/* But allow the pointless unlimited -> unlimited remount */
if (!sbinfo)
return 0;
return shmem_set_size(sbinfo, max_blocks, max_inodes);
spin_lock(&sbinfo->stat_lock);
blocks = sbinfo->max_blocks - sbinfo->free_blocks;
inodes = sbinfo->max_inodes - sbinfo->free_inodes;
if (max_blocks < blocks)
goto out;
if (max_inodes < inodes)
goto out;
/*
* Those tests also disallow limited->unlimited while any are in
* use, so i_blocks will always be zero when max_blocks is zero;
* but we must separately disallow unlimited->limited, because
* in that case we have no record of how much is already in use.
*/
if (max_blocks && !sbinfo->max_blocks)
goto out;
if (max_inodes && !sbinfo->max_inodes)
goto out;

error = 0;
sbinfo->max_blocks = max_blocks;
sbinfo->free_blocks = max_blocks - blocks;
sbinfo->max_inodes = max_inodes;
sbinfo->free_inodes = max_inodes - inodes;
out:
spin_unlock(&sbinfo->stat_lock);
return error;
}
#endif

Expand All @@ -1961,11 +1958,11 @@ static int shmem_fill_super(struct super_block *sb,
uid_t uid = current->fsuid;
gid_t gid = current->fsgid;
int err = -ENOMEM;

#ifdef CONFIG_TMPFS
struct shmem_sb_info *sbinfo;
unsigned long blocks = 0;
unsigned long inodes = 0;

#ifdef CONFIG_TMPFS
/*
* Per default we only allow half of the physical ram per
* tmpfs instance, limiting inodes to one per page of lowmem;
Expand All @@ -1976,34 +1973,34 @@ static int shmem_fill_super(struct super_block *sb,
inodes = totalram_pages - totalhigh_pages;
if (inodes > blocks)
inodes = blocks;

if (shmem_parse_options(data, &mode,
&uid, &gid, &blocks, &inodes))
if (shmem_parse_options(data, &mode, &uid, &gid,
&blocks, &inodes))
return -EINVAL;
}

if (blocks || inodes) {
struct shmem_sb_info *sbinfo;
sbinfo = kmalloc(sizeof(struct shmem_sb_info), GFP_KERNEL);
if (!sbinfo)
return -ENOMEM;
sb->s_fs_info = sbinfo;
spin_lock_init(&sbinfo->stat_lock);
sbinfo->max_blocks = blocks;
sbinfo->free_blocks = blocks;
sbinfo->max_inodes = inodes;
sbinfo->free_inodes = inodes;
}
sb->s_xattr = shmem_xattr_handlers;
#else
sb->s_flags |= MS_NOUSER;
#endif

/* Round up to L1_CACHE_BYTES to resist false sharing */
sbinfo = kmalloc(max((int)sizeof(struct shmem_sb_info),
L1_CACHE_BYTES), GFP_KERNEL);
if (!sbinfo)
return -ENOMEM;

spin_lock_init(&sbinfo->stat_lock);
sbinfo->max_blocks = blocks;
sbinfo->free_blocks = blocks;
sbinfo->max_inodes = inodes;
sbinfo->free_inodes = inodes;

sb->s_fs_info = sbinfo;
sb->s_maxbytes = SHMEM_MAX_BYTES;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = TMPFS_MAGIC;
sb->s_op = &shmem_ops;
sb->s_xattr = shmem_xattr_handlers;

inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
if (!inode)
goto failed;
Expand Down

0 comments on commit 9338f52

Please sign in to comment.