|
@@ -205,6 +205,31 @@ static void shmem_free_blocks(struct inode *inode, long pages)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static int shmem_reserve_inode(struct super_block *sb)
|
|
|
+{
|
|
|
+ struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
|
|
|
+ if (sbinfo->max_inodes) {
|
|
|
+ spin_lock(&sbinfo->stat_lock);
|
|
|
+ if (!sbinfo->free_inodes) {
|
|
|
+ spin_unlock(&sbinfo->stat_lock);
|
|
|
+ return -ENOSPC;
|
|
|
+ }
|
|
|
+ sbinfo->free_inodes--;
|
|
|
+ spin_unlock(&sbinfo->stat_lock);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void shmem_free_inode(struct super_block *sb)
|
|
|
+{
|
|
|
+ struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
|
|
|
+ if (sbinfo->max_inodes) {
|
|
|
+ spin_lock(&sbinfo->stat_lock);
|
|
|
+ sbinfo->free_inodes++;
|
|
|
+ spin_unlock(&sbinfo->stat_lock);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* shmem_recalc_inode - recalculate the size of an inode
|
|
|
*
|
|
@@ -762,7 +787,6 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
|
|
|
|
|
|
static void shmem_delete_inode(struct inode *inode)
|
|
|
{
|
|
|
- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
|
|
|
struct shmem_inode_info *info = SHMEM_I(inode);
|
|
|
|
|
|
if (inode->i_op->truncate == shmem_truncate) {
|
|
@@ -777,11 +801,7 @@ static void shmem_delete_inode(struct inode *inode)
|
|
|
}
|
|
|
}
|
|
|
BUG_ON(inode->i_blocks);
|
|
|
- if (sbinfo->max_inodes) {
|
|
|
- spin_lock(&sbinfo->stat_lock);
|
|
|
- sbinfo->free_inodes++;
|
|
|
- spin_unlock(&sbinfo->stat_lock);
|
|
|
- }
|
|
|
+ shmem_free_inode(inode->i_sb);
|
|
|
clear_inode(inode);
|
|
|
}
|
|
|
|
|
@@ -1371,15 +1391,8 @@ 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->max_inodes) {
|
|
|
- spin_lock(&sbinfo->stat_lock);
|
|
|
- if (!sbinfo->free_inodes) {
|
|
|
- spin_unlock(&sbinfo->stat_lock);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- sbinfo->free_inodes--;
|
|
|
- spin_unlock(&sbinfo->stat_lock);
|
|
|
- }
|
|
|
+ if (shmem_reserve_inode(sb))
|
|
|
+ return NULL;
|
|
|
|
|
|
inode = new_inode(sb);
|
|
|
if (inode) {
|
|
@@ -1423,11 +1436,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
|
|
|
NULL);
|
|
|
break;
|
|
|
}
|
|
|
- } else if (sbinfo->max_inodes) {
|
|
|
- spin_lock(&sbinfo->stat_lock);
|
|
|
- sbinfo->free_inodes++;
|
|
|
- spin_unlock(&sbinfo->stat_lock);
|
|
|
- }
|
|
|
+ } else
|
|
|
+ shmem_free_inode(sb);
|
|
|
return inode;
|
|
|
}
|
|
|
|
|
@@ -1670,22 +1680,16 @@ static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
|
|
|
static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
|
|
|
{
|
|
|
struct inode *inode = old_dentry->d_inode;
|
|
|
- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
|
|
|
+ int ret;
|
|
|
|
|
|
/*
|
|
|
* No ordinary (disk based) filesystem counts links as inodes;
|
|
|
* but each new link needs a new dentry, pinning lowmem, and
|
|
|
* tmpfs dentries cannot be pruned until they are unlinked.
|
|
|
*/
|
|
|
- if (sbinfo->max_inodes) {
|
|
|
- spin_lock(&sbinfo->stat_lock);
|
|
|
- if (!sbinfo->free_inodes) {
|
|
|
- spin_unlock(&sbinfo->stat_lock);
|
|
|
- return -ENOSPC;
|
|
|
- }
|
|
|
- sbinfo->free_inodes--;
|
|
|
- spin_unlock(&sbinfo->stat_lock);
|
|
|
- }
|
|
|
+ ret = shmem_reserve_inode(inode->i_sb);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
|
|
|
dir->i_size += BOGO_DIRENT_SIZE;
|
|
|
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
|
|
@@ -1693,21 +1697,16 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
|
|
|
atomic_inc(&inode->i_count); /* New dentry reference */
|
|
|
dget(dentry); /* Extra pinning count for the created dentry */
|
|
|
d_instantiate(dentry, inode);
|
|
|
- return 0;
|
|
|
+out:
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int shmem_unlink(struct inode *dir, struct dentry *dentry)
|
|
|
{
|
|
|
struct inode *inode = dentry->d_inode;
|
|
|
|
|
|
- if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
|
|
|
- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
|
|
|
- if (sbinfo->max_inodes) {
|
|
|
- spin_lock(&sbinfo->stat_lock);
|
|
|
- sbinfo->free_inodes++;
|
|
|
- spin_unlock(&sbinfo->stat_lock);
|
|
|
- }
|
|
|
- }
|
|
|
+ if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))
|
|
|
+ shmem_free_inode(inode->i_sb);
|
|
|
|
|
|
dir->i_size -= BOGO_DIRENT_SIZE;
|
|
|
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
|