Unpack or remove file tail when inode is resized If the inode size grows, we need to unpack the tail into a page. If the inode shrinks, such that the entire tail is beyond the end of the file, discard the tail. If the file shrinks, but part of the tail is still valid, just leave it. Signed-off-by: Dave Kleikamp <shaggy@xxxxxxxxxxxxxxxxxx> --- include/linux/fs.h | 14 ++++++++++++++ mm/file_tail.c | 11 +++++++++++ 2 files changed, 25 insertions(+) diff -Nurp linux003/include/linux/fs.h linux004/include/linux/fs.h --- linux003/include/linux/fs.h 2007-11-08 10:49:46.000000000 -0600 +++ linux004/include/linux/fs.h 2007-11-08 10:49:46.000000000 -0600 @@ -715,6 +715,19 @@ static inline loff_t i_size_read(const s #endif } +#ifdef CONFIG_VM_FILE_TAILS +void __vm_file_tail_unpack_on_resize(struct inode *, loff_t); + +static inline void vm_file_tail_unpack_on_resize(struct inode *inode, + loff_t size) +{ + if (inode->i_mapping && inode->i_mapping->tail) + __vm_file_tail_unpack_on_resize(inode, size); +} +#else +#define vm_file_tail_unpack_on_resize(mapping, new_size) do {} while (0) +#endif + /* * NOTE: unlike i_size_read(), i_size_write() does need locking around it * (normally i_mutex), otherwise on 32bit/SMP an update of i_size_seqcount @@ -722,6 +735,7 @@ static inline loff_t i_size_read(const s */ static inline void i_size_write(struct inode *inode, loff_t i_size) { + vm_file_tail_unpack_on_resize(inode, i_size); #if BITS_PER_LONG==32 && defined(CONFIG_SMP) write_seqcount_begin(&inode->i_size_seqcount); inode->i_size = i_size; diff -Nurp linux003/mm/file_tail.c linux004/mm/file_tail.c --- linux003/mm/file_tail.c 2007-11-08 10:49:46.000000000 -0600 +++ linux004/mm/file_tail.c 2007-11-08 10:49:46.000000000 -0600 @@ -13,6 +13,7 @@ #include <linux/buffer_head.h> #include <linux/fs.h> #include <linux/hardirq.h> +#include <linux/module.h> #include <linux/vm_file_tail.h> /* @@ -167,3 +168,13 @@ out: unlock_page(page); return ret; } + +void __vm_file_tail_unpack_on_resize(struct inode *inode, loff_t new_size) +{ + loff_t old_size = i_size_read(inode); + if (new_size > old_size) + vm_file_tail_unpack(inode->i_mapping); + else if (new_size >> PAGE_CACHE_SHIFT != old_size >> PAGE_CACHE_SHIFT) + vm_file_tail_free(inode->i_mapping); +} +EXPORT_SYMBOL(__vm_file_tail_unpack_on_resize); - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html