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>
This commit is contained in:
parent
5955102c99
commit
3ed47db34f
|
@ -15,10 +15,7 @@ struct shmem_inode_info {
|
||||||
unsigned int seals; /* shmem seals */
|
unsigned int seals; /* shmem seals */
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned long alloced; /* data pages alloced to file */
|
unsigned long alloced; /* data pages alloced to file */
|
||||||
union {
|
unsigned long swapped; /* subtotal assigned to swap */
|
||||||
unsigned long swapped; /* subtotal assigned to swap */
|
|
||||||
char *symlink; /* unswappable short symlink */
|
|
||||||
};
|
|
||||||
struct shared_policy policy; /* NUMA memory alloc policy */
|
struct shared_policy policy; /* NUMA memory alloc policy */
|
||||||
struct list_head swaplist; /* chain of maybes on swap */
|
struct list_head swaplist; /* chain of maybes on swap */
|
||||||
struct simple_xattrs xattrs; /* list of xattrs */
|
struct simple_xattrs xattrs; /* list of xattrs */
|
||||||
|
|
|
@ -701,8 +701,7 @@ static void shmem_evict_inode(struct inode *inode)
|
||||||
list_del_init(&info->swaplist);
|
list_del_init(&info->swaplist);
|
||||||
mutex_unlock(&shmem_swaplist_mutex);
|
mutex_unlock(&shmem_swaplist_mutex);
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
kfree(info->symlink);
|
|
||||||
|
|
||||||
simple_xattrs_free(&info->xattrs);
|
simple_xattrs_free(&info->xattrs);
|
||||||
WARN_ON(inode->i_blocks);
|
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);
|
info = SHMEM_I(inode);
|
||||||
inode->i_size = len-1;
|
inode->i_size = len-1;
|
||||||
if (len <= SHORT_SYMLINK_LEN) {
|
if (len <= SHORT_SYMLINK_LEN) {
|
||||||
info->symlink = kmemdup(symname, len, GFP_KERNEL);
|
inode->i_link = kmemdup(symname, len, GFP_KERNEL);
|
||||||
if (!info->symlink) {
|
if (!inode->i_link) {
|
||||||
iput(inode);
|
iput(inode);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
inode->i_op = &shmem_short_symlink_operations;
|
inode->i_op = &shmem_short_symlink_operations;
|
||||||
inode->i_link = info->symlink;
|
|
||||||
} else {
|
} else {
|
||||||
inode_nohighmem(inode);
|
inode_nohighmem(inode);
|
||||||
error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
|
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)
|
static void shmem_destroy_callback(struct rcu_head *head)
|
||||||
{
|
{
|
||||||
struct inode *inode = container_of(head, struct inode, i_rcu);
|
struct inode *inode = container_of(head, struct inode, i_rcu);
|
||||||
|
kfree(inode->i_link);
|
||||||
kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
|
kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue