diff options
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 77 |
1 files changed, 38 insertions, 39 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 5dfe79048f6d..ce64b6616376 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -205,6 +205,31 @@ static void shmem_free_blocks(struct inode *inode, long pages) | |||
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | static int shmem_reserve_inode(struct super_block *sb) | ||
209 | { | ||
210 | struct shmem_sb_info *sbinfo = SHMEM_SB(sb); | ||
211 | if (sbinfo->max_inodes) { | ||
212 | spin_lock(&sbinfo->stat_lock); | ||
213 | if (!sbinfo->free_inodes) { | ||
214 | spin_unlock(&sbinfo->stat_lock); | ||
215 | return -ENOSPC; | ||
216 | } | ||
217 | sbinfo->free_inodes--; | ||
218 | spin_unlock(&sbinfo->stat_lock); | ||
219 | } | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static void shmem_free_inode(struct super_block *sb) | ||
224 | { | ||
225 | struct shmem_sb_info *sbinfo = SHMEM_SB(sb); | ||
226 | if (sbinfo->max_inodes) { | ||
227 | spin_lock(&sbinfo->stat_lock); | ||
228 | sbinfo->free_inodes++; | ||
229 | spin_unlock(&sbinfo->stat_lock); | ||
230 | } | ||
231 | } | ||
232 | |||
208 | /* | 233 | /* |
209 | * shmem_recalc_inode - recalculate the size of an inode | 234 | * shmem_recalc_inode - recalculate the size of an inode |
210 | * | 235 | * |
@@ -762,7 +787,6 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) | |||
762 | 787 | ||
763 | static void shmem_delete_inode(struct inode *inode) | 788 | static void shmem_delete_inode(struct inode *inode) |
764 | { | 789 | { |
765 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); | ||
766 | struct shmem_inode_info *info = SHMEM_I(inode); | 790 | struct shmem_inode_info *info = SHMEM_I(inode); |
767 | 791 | ||
768 | if (inode->i_op->truncate == shmem_truncate) { | 792 | if (inode->i_op->truncate == shmem_truncate) { |
@@ -777,11 +801,7 @@ static void shmem_delete_inode(struct inode *inode) | |||
777 | } | 801 | } |
778 | } | 802 | } |
779 | BUG_ON(inode->i_blocks); | 803 | BUG_ON(inode->i_blocks); |
780 | if (sbinfo->max_inodes) { | 804 | shmem_free_inode(inode->i_sb); |
781 | spin_lock(&sbinfo->stat_lock); | ||
782 | sbinfo->free_inodes++; | ||
783 | spin_unlock(&sbinfo->stat_lock); | ||
784 | } | ||
785 | clear_inode(inode); | 805 | clear_inode(inode); |
786 | } | 806 | } |
787 | 807 | ||
@@ -1371,15 +1391,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) | |||
1371 | struct shmem_inode_info *info; | 1391 | struct shmem_inode_info *info; |
1372 | struct shmem_sb_info *sbinfo = SHMEM_SB(sb); | 1392 | struct shmem_sb_info *sbinfo = SHMEM_SB(sb); |
1373 | 1393 | ||
1374 | if (sbinfo->max_inodes) { | 1394 | if (shmem_reserve_inode(sb)) |
1375 | spin_lock(&sbinfo->stat_lock); | 1395 | return NULL; |
1376 | if (!sbinfo->free_inodes) { | ||
1377 | spin_unlock(&sbinfo->stat_lock); | ||
1378 | return NULL; | ||
1379 | } | ||
1380 | sbinfo->free_inodes--; | ||
1381 | spin_unlock(&sbinfo->stat_lock); | ||
1382 | } | ||
1383 | 1396 | ||
1384 | inode = new_inode(sb); | 1397 | inode = new_inode(sb); |
1385 | if (inode) { | 1398 | if (inode) { |
@@ -1423,11 +1436,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) | |||
1423 | NULL); | 1436 | NULL); |
1424 | break; | 1437 | break; |
1425 | } | 1438 | } |
1426 | } else if (sbinfo->max_inodes) { | 1439 | } else |
1427 | spin_lock(&sbinfo->stat_lock); | 1440 | shmem_free_inode(sb); |
1428 | sbinfo->free_inodes++; | ||
1429 | spin_unlock(&sbinfo->stat_lock); | ||
1430 | } | ||
1431 | return inode; | 1441 | return inode; |
1432 | } | 1442 | } |
1433 | 1443 | ||
@@ -1670,22 +1680,16 @@ static int shmem_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1670 | static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | 1680 | static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) |
1671 | { | 1681 | { |
1672 | struct inode *inode = old_dentry->d_inode; | 1682 | struct inode *inode = old_dentry->d_inode; |
1673 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); | 1683 | int ret; |
1674 | 1684 | ||
1675 | /* | 1685 | /* |
1676 | * No ordinary (disk based) filesystem counts links as inodes; | 1686 | * No ordinary (disk based) filesystem counts links as inodes; |
1677 | * but each new link needs a new dentry, pinning lowmem, and | 1687 | * but each new link needs a new dentry, pinning lowmem, and |
1678 | * tmpfs dentries cannot be pruned until they are unlinked. | 1688 | * tmpfs dentries cannot be pruned until they are unlinked. |
1679 | */ | 1689 | */ |
1680 | if (sbinfo->max_inodes) { | 1690 | ret = shmem_reserve_inode(inode->i_sb); |
1681 | spin_lock(&sbinfo->stat_lock); | 1691 | if (ret) |
1682 | if (!sbinfo->free_inodes) { | 1692 | goto out; |
1683 | spin_unlock(&sbinfo->stat_lock); | ||
1684 | return -ENOSPC; | ||
1685 | } | ||
1686 | sbinfo->free_inodes--; | ||
1687 | spin_unlock(&sbinfo->stat_lock); | ||
1688 | } | ||
1689 | 1693 | ||
1690 | dir->i_size += BOGO_DIRENT_SIZE; | 1694 | dir->i_size += BOGO_DIRENT_SIZE; |
1691 | inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 1695 | 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 | |||
1693 | atomic_inc(&inode->i_count); /* New dentry reference */ | 1697 | atomic_inc(&inode->i_count); /* New dentry reference */ |
1694 | dget(dentry); /* Extra pinning count for the created dentry */ | 1698 | dget(dentry); /* Extra pinning count for the created dentry */ |
1695 | d_instantiate(dentry, inode); | 1699 | d_instantiate(dentry, inode); |
1696 | return 0; | 1700 | out: |
1701 | return ret; | ||
1697 | } | 1702 | } |
1698 | 1703 | ||
1699 | static int shmem_unlink(struct inode *dir, struct dentry *dentry) | 1704 | static int shmem_unlink(struct inode *dir, struct dentry *dentry) |
1700 | { | 1705 | { |
1701 | struct inode *inode = dentry->d_inode; | 1706 | struct inode *inode = dentry->d_inode; |
1702 | 1707 | ||
1703 | if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) { | 1708 | if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) |
1704 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); | 1709 | shmem_free_inode(inode->i_sb); |
1705 | if (sbinfo->max_inodes) { | ||
1706 | spin_lock(&sbinfo->stat_lock); | ||
1707 | sbinfo->free_inodes++; | ||
1708 | spin_unlock(&sbinfo->stat_lock); | ||
1709 | } | ||
1710 | } | ||
1711 | 1710 | ||
1712 | dir->i_size -= BOGO_DIRENT_SIZE; | 1711 | dir->i_size -= BOGO_DIRENT_SIZE; |
1713 | inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 1712 | inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; |