aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/shmem.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index 0f094a258526..3a5be0feb6af 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -73,6 +73,9 @@ static struct vfsmount *shm_mnt;
73/* Pretend that each entry is of this size in directory's i_size */ 73/* Pretend that each entry is of this size in directory's i_size */
74#define BOGO_DIRENT_SIZE 20 74#define BOGO_DIRENT_SIZE 20
75 75
76/* Symlink up to this size is kmalloc'ed instead of using a swappable page */
77#define SHORT_SYMLINK_LEN 128
78
76struct shmem_xattr { 79struct shmem_xattr {
77 struct list_head list; /* anchored by shmem_inode_info->xattr_list */ 80 struct list_head list; /* anchored by shmem_inode_info->xattr_list */
78 char *name; /* xattr name */ 81 char *name; /* xattr name */
@@ -585,7 +588,8 @@ static void shmem_evict_inode(struct inode *inode)
585 list_del_init(&info->swaplist); 588 list_del_init(&info->swaplist);
586 mutex_unlock(&shmem_swaplist_mutex); 589 mutex_unlock(&shmem_swaplist_mutex);
587 } 590 }
588 } 591 } else
592 kfree(info->symlink);
589 593
590 list_for_each_entry_safe(xattr, nxattr, &info->xattr_list, list) { 594 list_for_each_entry_safe(xattr, nxattr, &info->xattr_list, list) {
591 kfree(xattr->name); 595 kfree(xattr->name);
@@ -1173,7 +1177,7 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
1173 1177
1174#ifdef CONFIG_TMPFS 1178#ifdef CONFIG_TMPFS
1175static const struct inode_operations shmem_symlink_inode_operations; 1179static const struct inode_operations shmem_symlink_inode_operations;
1176static const struct inode_operations shmem_symlink_inline_operations; 1180static const struct inode_operations shmem_short_symlink_operations;
1177 1181
1178static int 1182static int
1179shmem_write_begin(struct file *file, struct address_space *mapping, 1183shmem_write_begin(struct file *file, struct address_space *mapping,
@@ -1638,10 +1642,13 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
1638 1642
1639 info = SHMEM_I(inode); 1643 info = SHMEM_I(inode);
1640 inode->i_size = len-1; 1644 inode->i_size = len-1;
1641 if (len <= SHMEM_SYMLINK_INLINE_LEN) { 1645 if (len <= SHORT_SYMLINK_LEN) {
1642 /* do it inline */ 1646 info->symlink = kmemdup(symname, len, GFP_KERNEL);
1643 memcpy(info->inline_symlink, symname, len); 1647 if (!info->symlink) {
1644 inode->i_op = &shmem_symlink_inline_operations; 1648 iput(inode);
1649 return -ENOMEM;
1650 }
1651 inode->i_op = &shmem_short_symlink_operations;
1645 } else { 1652 } else {
1646 error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL); 1653 error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
1647 if (error) { 1654 if (error) {
@@ -1664,9 +1671,9 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
1664 return 0; 1671 return 0;
1665} 1672}
1666 1673
1667static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd) 1674static void *shmem_follow_short_symlink(struct dentry *dentry, struct nameidata *nd)
1668{ 1675{
1669 nd_set_link(nd, SHMEM_I(dentry->d_inode)->inline_symlink); 1676 nd_set_link(nd, SHMEM_I(dentry->d_inode)->symlink);
1670 return NULL; 1677 return NULL;
1671} 1678}
1672 1679
@@ -1914,9 +1921,9 @@ static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
1914} 1921}
1915#endif /* CONFIG_TMPFS_XATTR */ 1922#endif /* CONFIG_TMPFS_XATTR */
1916 1923
1917static const struct inode_operations shmem_symlink_inline_operations = { 1924static const struct inode_operations shmem_short_symlink_operations = {
1918 .readlink = generic_readlink, 1925 .readlink = generic_readlink,
1919 .follow_link = shmem_follow_link_inline, 1926 .follow_link = shmem_follow_short_symlink,
1920#ifdef CONFIG_TMPFS_XATTR 1927#ifdef CONFIG_TMPFS_XATTR
1921 .setxattr = shmem_setxattr, 1928 .setxattr = shmem_setxattr,
1922 .getxattr = shmem_getxattr, 1929 .getxattr = shmem_getxattr,
@@ -2259,10 +2266,8 @@ static void shmem_destroy_callback(struct rcu_head *head)
2259 2266
2260static void shmem_destroy_inode(struct inode *inode) 2267static void shmem_destroy_inode(struct inode *inode)
2261{ 2268{
2262 if ((inode->i_mode & S_IFMT) == S_IFREG) { 2269 if ((inode->i_mode & S_IFMT) == S_IFREG)
2263 /* only struct inode is valid if it's an inline symlink */
2264 mpol_free_shared_policy(&SHMEM_I(inode)->policy); 2270 mpol_free_shared_policy(&SHMEM_I(inode)->policy);
2265 }
2266 call_rcu(&inode->i_rcu, shmem_destroy_callback); 2271 call_rcu(&inode->i_rcu, shmem_destroy_callback);
2267} 2272}
2268 2273