[Patch] tmpfs/ramfs accounting
Hi Alan, here is the patch you backed out for -ac22. I slightly changed the approach: I do not rely on removepage to calculate the fs size any more since the special-casing was ugly and PG_marker was dropped. But I use removepage for the shmem_nrpages calculation. Please apply Christoph diff -uNr 5-ac22/fs/ramfs/inode.c 5-ac22-fix/fs/ramfs/inode.c --- 5-ac22/fs/ramfs/inode.c Mon Jul 2 09:13:18 2001 +++ 5-ac22-fix/fs/ramfs/inode.c Mon Jul 2 09:55:52 2001 @@ -289,7 +289,7 @@ return 0; } -static void ramfs_truncatepage(struct page *page) +static void ramfs_removepage(struct page *page) { struct inode *inode = (struct inode *)page->mapping->host; @@ -659,7 +659,7 @@ writepage: ramfs_writepage, prepare_write: ramfs_prepare_write, commit_write: ramfs_commit_write, - truncatepage: ramfs_truncatepage, + removepage: ramfs_removepage, }; static struct file_operations ramfs_file_operations = { diff -uNr 5-ac22/include/linux/fs.h 5-ac22-fix/include/linux/fs.h --- 5-ac22/include/linux/fs.h Mon Jul 2 09:35:39 2001 +++ 5-ac22-fix/include/linux/fs.h Mon Jul 2 10:32:04 2001 @@ -375,7 +375,7 @@ int (*sync_page)(struct page *); int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); int (*commit_write)(struct file *, struct page *, unsigned, unsigned); - void (*truncatepage)(struct page *); /* called from truncate_complete_page */ + void (*removepage)(struct page *); /* called when page gets removed from the +inode */ /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ int (*bmap)(struct address_space *, long); }; diff -uNr 5-ac22/mm/filemap.c 5-ac22-fix/mm/filemap.c --- 5-ac22/mm/filemap.c Mon Jul 2 09:13:29 2001 +++ 5-ac22-fix/mm/filemap.c Mon Jul 2 10:22:52 2001 @@ -87,6 +87,9 @@ { struct address_space * mapping = page->mapping; + if (mapping->a_ops->removepage) + mapping->a_ops->removepage(page); + mapping->nrpages--; list_del(>list); page->mapping = NULL; @@ -211,9 +214,6 @@ if (!page->buffers || block_flushpage(page, 0)) lru_cache_del(page); - if (page->mapping->a_ops->truncatepage) - page->mapping->a_ops->truncatepage(page); - /* * We remove the page from the page cache _after_ we have * destroyed all buffer-cache references to it. Otherwise some diff -uNr 5-ac22/mm/shmem.c 5-ac22-fix/mm/shmem.c --- 5-ac22/mm/shmem.c Mon Jul 2 09:13:29 2001 +++ 5-ac22-fix/mm/shmem.c Mon Jul 2 10:54:55 2001 @@ -34,6 +34,7 @@ #define TMPFS_MAGIC0x01021994 #define ENTRIES_PER_PAGE (PAGE_SIZE/sizeof(unsigned long)) +#define SHMEM_MAX_BLOCKS (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE*ENTRIES_PER_PAGE) #define SHMEM_SB(sb) (>u.shmem_sb) @@ -51,6 +52,11 @@ #define BLOCKS_PER_PAGE (PAGE_SIZE/512) +static void shmem_removepage(struct page *page) +{ + atomic_dec(_nrpages); +} + /* * shmem_recalc_inode - recalculate the size of an inode * @@ -69,11 +75,9 @@ * (inode->i_mapping->nrpages + info->swapped) * * It has to be called with the spinlock held. - * - * The swap parameter is a performance hack for truncate. */ -static void shmem_recalc_inode(struct inode * inode, unsigned long swap) +static void shmem_recalc_inode(struct inode * inode) { unsigned long freed; @@ -85,7 +89,6 @@ spin_lock (>stat_lock); sbinfo->free_blocks += freed; spin_unlock (>stat_lock); - atomic_sub(freed-swap, _nrpages); } } @@ -202,7 +205,7 @@ out: info->max_index = index; info->swapped -= freed; - shmem_recalc_inode(inode, freed); + shmem_recalc_inode(inode); spin_unlock (>lock); up(>sem); } @@ -257,7 +260,7 @@ entry = shmem_swp_entry(info, page->index); if (IS_ERR(entry)) /* this had been allocted on page allocation */ BUG(); - shmem_recalc_inode(page->mapping->host, 0); + shmem_recalc_inode(page->mapping->host); error = -EAGAIN; if (entry->val) BUG(); @@ -265,7 +268,6 @@ *entry = swap; error = 0; /* Remove the page from the page cache */ - atomic_dec(_nrpages); lru_cache_del(page); remove_inode_page(page); @@ -1086,6 +1088,8 @@ unsigned long max_inodes, inodes; struct shmem_sb_info *sbinfo = SHMEM_SB(sb); + max_blocks = sbinfo->max_blocks; + max_inodes = sbinfo->max_inodes; if (shmem_parse_options (data, NULL, _blocks, _inodes)) return -EINVAL; @@ -1134,7 +1138,7 @@ sbinfo->free_blocks = blocks; sbinfo->max_inodes = inodes; sbinfo->free_inodes = inodes; - sb->s_maxbytes = (unsigned long long)(SHMEM_NR_DIRECT +
[Patch] tmpfs/ramfs accounting
Hi Alan, here is the patch you backed out for -ac22. I slightly changed the approach: I do not rely on removepage to calculate the fs size any more since the special-casing was ugly and PG_marker was dropped. But I use removepage for the shmem_nrpages calculation. Please apply Christoph diff -uNr 5-ac22/fs/ramfs/inode.c 5-ac22-fix/fs/ramfs/inode.c --- 5-ac22/fs/ramfs/inode.c Mon Jul 2 09:13:18 2001 +++ 5-ac22-fix/fs/ramfs/inode.c Mon Jul 2 09:55:52 2001 @@ -289,7 +289,7 @@ return 0; } -static void ramfs_truncatepage(struct page *page) +static void ramfs_removepage(struct page *page) { struct inode *inode = (struct inode *)page-mapping-host; @@ -659,7 +659,7 @@ writepage: ramfs_writepage, prepare_write: ramfs_prepare_write, commit_write: ramfs_commit_write, - truncatepage: ramfs_truncatepage, + removepage: ramfs_removepage, }; static struct file_operations ramfs_file_operations = { diff -uNr 5-ac22/include/linux/fs.h 5-ac22-fix/include/linux/fs.h --- 5-ac22/include/linux/fs.h Mon Jul 2 09:35:39 2001 +++ 5-ac22-fix/include/linux/fs.h Mon Jul 2 10:32:04 2001 @@ -375,7 +375,7 @@ int (*sync_page)(struct page *); int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); int (*commit_write)(struct file *, struct page *, unsigned, unsigned); - void (*truncatepage)(struct page *); /* called from truncate_complete_page */ + void (*removepage)(struct page *); /* called when page gets removed from the +inode */ /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ int (*bmap)(struct address_space *, long); }; diff -uNr 5-ac22/mm/filemap.c 5-ac22-fix/mm/filemap.c --- 5-ac22/mm/filemap.c Mon Jul 2 09:13:29 2001 +++ 5-ac22-fix/mm/filemap.c Mon Jul 2 10:22:52 2001 @@ -87,6 +87,9 @@ { struct address_space * mapping = page-mapping; + if (mapping-a_ops-removepage) + mapping-a_ops-removepage(page); + mapping-nrpages--; list_del(page-list); page-mapping = NULL; @@ -211,9 +214,6 @@ if (!page-buffers || block_flushpage(page, 0)) lru_cache_del(page); - if (page-mapping-a_ops-truncatepage) - page-mapping-a_ops-truncatepage(page); - /* * We remove the page from the page cache _after_ we have * destroyed all buffer-cache references to it. Otherwise some diff -uNr 5-ac22/mm/shmem.c 5-ac22-fix/mm/shmem.c --- 5-ac22/mm/shmem.c Mon Jul 2 09:13:29 2001 +++ 5-ac22-fix/mm/shmem.c Mon Jul 2 10:54:55 2001 @@ -34,6 +34,7 @@ #define TMPFS_MAGIC0x01021994 #define ENTRIES_PER_PAGE (PAGE_SIZE/sizeof(unsigned long)) +#define SHMEM_MAX_BLOCKS (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE*ENTRIES_PER_PAGE) #define SHMEM_SB(sb) (sb-u.shmem_sb) @@ -51,6 +52,11 @@ #define BLOCKS_PER_PAGE (PAGE_SIZE/512) +static void shmem_removepage(struct page *page) +{ + atomic_dec(shmem_nrpages); +} + /* * shmem_recalc_inode - recalculate the size of an inode * @@ -69,11 +75,9 @@ * (inode-i_mapping-nrpages + info-swapped) * * It has to be called with the spinlock held. - * - * The swap parameter is a performance hack for truncate. */ -static void shmem_recalc_inode(struct inode * inode, unsigned long swap) +static void shmem_recalc_inode(struct inode * inode) { unsigned long freed; @@ -85,7 +89,6 @@ spin_lock (sbinfo-stat_lock); sbinfo-free_blocks += freed; spin_unlock (sbinfo-stat_lock); - atomic_sub(freed-swap, shmem_nrpages); } } @@ -202,7 +205,7 @@ out: info-max_index = index; info-swapped -= freed; - shmem_recalc_inode(inode, freed); + shmem_recalc_inode(inode); spin_unlock (info-lock); up(info-sem); } @@ -257,7 +260,7 @@ entry = shmem_swp_entry(info, page-index); if (IS_ERR(entry)) /* this had been allocted on page allocation */ BUG(); - shmem_recalc_inode(page-mapping-host, 0); + shmem_recalc_inode(page-mapping-host); error = -EAGAIN; if (entry-val) BUG(); @@ -265,7 +268,6 @@ *entry = swap; error = 0; /* Remove the page from the page cache */ - atomic_dec(shmem_nrpages); lru_cache_del(page); remove_inode_page(page); @@ -1086,6 +1088,8 @@ unsigned long max_inodes, inodes; struct shmem_sb_info *sbinfo = SHMEM_SB(sb); + max_blocks = sbinfo-max_blocks; + max_inodes = sbinfo-max_inodes; if (shmem_parse_options (data, NULL, max_blocks, max_inodes)) return -EINVAL; @@ -1134,7 +1138,7 @@ sbinfo-free_blocks = blocks; sbinfo-max_inodes = inodes; sbinfo-free_inodes = inodes; - sb-s_maxbytes = (unsigned long long)(SHMEM_NR_DIRECT +