diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-01-22 18:08:52 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-01-22 18:08:52 -0500 |
commit | 3ed47db34f480df7caf44436e3e63e555351ae9a (patch) | |
tree | aea60132d6706c44c155c1281c5c3ec1f3fb76b6 | |
parent | 5955102c9984fa081b2d570cfac75c97eecf8f3b (diff) | |
download | linux-stable-3ed47db34f480df7caf44436e3e63e555351ae9a.tar.gz linux-stable-3ed47db34f480df7caf44436e3e63e555351ae9a.tar.bz2 linux-stable-3ed47db34f480df7caf44436e3e63e555351ae9a.zip |
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.h | 5 | ||||
-rw-r--r-- | mm/shmem.c | 9 |
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 { unsigned int seals; /* shmem seals */ unsigned long flags; unsigned long alloced; /* data pages alloced to file */ - union { - unsigned long swapped; /* subtotal assigned to swap */ - char *symlink; /* unswappable short symlink */ - }; + unsigned long swapped; /* subtotal assigned to swap */ struct shared_policy policy; /* NUMA memory alloc policy */ struct list_head swaplist; /* chain of maybes on swap */ 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) list_del_init(&info->swaplist); mutex_unlock(&shmem_swaplist_mutex); } - } else - kfree(info->symlink); + } simple_xattrs_free(&info->xattrs); WARN_ON(inode->i_blocks); @@ -2549,13 +2548,12 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s info = SHMEM_I(inode); inode->i_size = len-1; if (len <= SHORT_SYMLINK_LEN) { - info->symlink = kmemdup(symname, len, GFP_KERNEL); - if (!info->symlink) { + inode->i_link = kmemdup(symname, len, GFP_KERNEL); + if (!inode->i_link) { iput(inode); return -ENOMEM; } inode->i_op = &shmem_short_symlink_operations; - inode->i_link = info->symlink; } else { inode_nohighmem(inode); error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL); @@ -3132,6 +3130,7 @@ static struct inode *shmem_alloc_inode(struct super_block *sb) static void shmem_destroy_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); + kfree(inode->i_link); kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode)); } |