[PATCH] tmpfs symlink corrupts mempolicy

From: Hugh Dickins
Date: Mon Nov 15 2004 - 15:47:53 EST


Andrea discovered that short symlinks on tmpfs, stored within the inode
itself, overwrote the NUMA mempolicy field which shmem_destroy_inode
expected to find there. His fix was good, but Hugh changed it around a
little, to match existing shmem.c practice (now mpol_init in cases which
might allocate a page, mpol_free in shmem_truncate_inode), and allow for
possibility that mpol_init for a long symlink might one day do something
which really needs mpol_free.

Signed-off-by: Hugh Dickins <hugh@xxxxxxxxxxx>
---

Thanks a lot for working that out, Andrea: is this version okay with you?
I've not studied the mempolicy.c part of the patch you posted, which
seemed to be an entirely separate (and less urgent) patch,
better reviewed by Andi.

--- 2.6.10-rc2/mm/shmem.c 2004-11-15 16:21:24.000000000 +0000
+++ linux/mm/shmem.c 2004-11-15 19:08:58.366829456 +0000
@@ -672,6 +672,7 @@ static void shmem_delete_inode(struct in
shmem_unacct_size(info->flags, inode->i_size);
inode->i_size = 0;
shmem_truncate(inode);
+ mpol_free_shared_policy(&info->policy);
if (!list_empty(&info->swaplist)) {
spin_lock(&shmem_swaplist_lock);
list_del_init(&info->swaplist);
@@ -1292,7 +1293,6 @@ shmem_get_inode(struct super_block *sb,
info = SHMEM_I(inode);
memset(info, 0, (char *)inode - (char *)info);
spin_lock_init(&info->lock);
- mpol_shared_policy_init(&info->policy);
INIT_LIST_HEAD(&info->swaplist);

switch (mode & S_IFMT) {
@@ -1303,6 +1303,7 @@ shmem_get_inode(struct super_block *sb,
case S_IFREG:
inode->i_op = &shmem_inode_operations;
inode->i_fop = &shmem_file_operations;
+ mpol_shared_policy_init(&info->policy);
break;
case S_IFDIR:
inode->i_nlink++;
@@ -1766,12 +1767,13 @@ static int shmem_symlink(struct inode *d
memcpy(info, symname, len);
inode->i_op = &shmem_symlink_inline_operations;
} else {
+ inode->i_op = &shmem_symlink_inode_operations;
+ mpol_shared_policy_init(&info->policy);
error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
if (error) {
iput(inode);
return error;
}
- inode->i_op = &shmem_symlink_inode_operations;
kaddr = kmap_atomic(page, KM_USER0);
memcpy(kaddr, symname, len);
kunmap_atomic(kaddr, KM_USER0);
@@ -2026,7 +2028,6 @@ static struct inode *shmem_alloc_inode(s

static void shmem_destroy_inode(struct inode *inode)
{
- mpol_free_shared_policy(&SHMEM_I(inode)->policy);
kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
}


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/