aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-01-22 18:08:52 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2016-01-22 18:08:52 -0500
commit3ed47db34f480df7caf44436e3e63e555351ae9a (patch)
treeaea60132d6706c44c155c1281c5c3ec1f3fb76b6
parent5955102c9984fa081b2d570cfac75c97eecf8f3b (diff)
make sure that freeing shmem fast symlinks is RCU-delayed
Cc: stable@vger.kernel.org # v4.2+ Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--include/linux/shmem_fs.h5
-rw-r--r--mm/shmem.c9
2 files changed, 5 insertions, 9 deletions
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index a43f41cb3c43..4d4780c00d34 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -15,10 +15,7 @@ struct shmem_inode_info {
15 unsigned int seals; /* shmem seals */ 15 unsigned int seals; /* shmem seals */
16 unsigned long flags; 16 unsigned long flags;
17 unsigned long alloced; /* data pages alloced to file */ 17 unsigned long alloced; /* data pages alloced to file */
18 union { 18 unsigned long swapped; /* subtotal assigned to swap */
19 unsigned long swapped; /* subtotal assigned to swap */
20 char *symlink; /* unswappable short symlink */
21 };
22 struct shared_policy policy; /* NUMA memory alloc policy */ 19 struct shared_policy policy; /* NUMA memory alloc policy */
23 struct list_head swaplist; /* chain of maybes on swap */ 20 struct list_head swaplist; /* chain of maybes on swap */
24 struct simple_xattrs xattrs; /* list of xattrs */ 21 struct simple_xattrs xattrs; /* list of xattrs */
diff --git a/mm/shmem.c b/mm/shmem.c
index 38c5e72c7008..440e2a7e6c1c 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -701,8 +701,7 @@ static void shmem_evict_inode(struct inode *inode)
701 list_del_init(&info->swaplist); 701 list_del_init(&info->swaplist);
702 mutex_unlock(&shmem_swaplist_mutex); 702 mutex_unlock(&shmem_swaplist_mutex);
703 } 703 }
704 } else 704 }
705 kfree(info->symlink);
706 705
707 simple_xattrs_free(&info->xattrs); 706 simple_xattrs_free(&info->xattrs);
708 WARN_ON(inode->i_blocks); 707 WARN_ON(inode->i_blocks);
@@ -2549,13 +2548,12 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
2549 info = SHMEM_I(inode); 2548 info = SHMEM_I(inode);
2550 inode->i_size = len-1; 2549 inode->i_size = len-1;
2551 if (len <= SHORT_SYMLINK_LEN) { 2550 if (len <= SHORT_SYMLINK_LEN) {
2552 info->symlink = kmemdup(symname, len, GFP_KERNEL); 2551 inode->i_link = kmemdup(symname, len, GFP_KERNEL);
2553 if (!info->symlink) { 2552 if (!inode->i_link) {
2554 iput(inode); 2553 iput(inode);
2555 return -ENOMEM; 2554 return -ENOMEM;
2556 } 2555 }
2557 inode->i_op = &shmem_short_symlink_operations; 2556 inode->i_op = &shmem_short_symlink_operations;
2558 inode->i_link = info->symlink;
2559 } else { 2557 } else {
2560 inode_nohighmem(inode); 2558 inode_nohighmem(inode);
2561 error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL); 2559 error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
@@ -3132,6 +3130,7 @@ static struct inode *shmem_alloc_inode(struct super_block *sb)
3132static void shmem_destroy_callback(struct rcu_head *head) 3130static void shmem_destroy_callback(struct rcu_head *head)
3133{ 3131{
3134 struct inode *inode = container_of(head, struct inode, i_rcu); 3132 struct inode *inode = container_of(head, struct inode, i_rcu);
3133 kfree(inode->i_link);
3135 kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode)); 3134 kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
3136} 3135}
3137 3136