[PATCH] tmpfs 5/7 writepage/truncate race

From: Hugh Dickins
Date: Wed Oct 15 2003 - 13:26:07 EST


If it's possible for a tmpfs page beyond i_size to remain in cache until
shmem_truncate repeats truncate_inode_pages, then shmem_writepage's
BUG_ON(index >= info->next_index) cannot be completely safe. But it's a
useful check in a fragile area, so retain it when not in shmem_truncate.

--- tmpfs4/mm/shmem.c 2003-10-15 15:39:03.328549328 +0100
+++ tmpfs5/mm/shmem.c 2003-10-15 15:39:14.391867448 +0100
@@ -52,8 +52,9 @@

#define VM_ACCT(size) (PAGE_CACHE_ALIGN(size) >> PAGE_SHIFT)

-/* info->flags needs a VM_flag to handle pagein/truncate races efficiently */
+/* info->flags needs VM_flags to handle pagein/truncate races efficiently */
#define SHMEM_PAGEIN VM_READ
+#define SHMEM_TRUNCATE VM_WRITE

/* Pretend that each entry is of this size in directory's i_size */
#define BOGO_DIRENT_SIZE 20
@@ -393,6 +394,7 @@
return;

spin_lock(&info->lock);
+ info->flags |= SHMEM_TRUNCATE;
limit = info->next_index;
info->next_index = idx;
if (info->swapped && idx < SHMEM_NR_DIRECT) {
@@ -505,6 +507,7 @@
truncate_inode_pages(inode->i_mapping, inode->i_size);
spin_lock(&info->lock);
}
+ info->flags &= ~SHMEM_TRUNCATE;
shmem_recalc_inode(inode);
spin_unlock(&info->lock);
}
@@ -730,7 +733,10 @@

spin_lock(&info->lock);
shmem_recalc_inode(inode);
- BUG_ON(index >= info->next_index);
+ if (index >= info->next_index) {
+ BUG_ON(!(info->flags & SHMEM_TRUNCATE));
+ goto unlock;
+ }
entry = shmem_swp_entry(info, index, NULL);
BUG_ON(!entry);
BUG_ON(entry->val);
@@ -744,6 +750,7 @@
}

shmem_swp_unmap(entry);
+unlock:
spin_unlock(&info->lock);
swap_free(swap);
redirty:

-
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/