Index: git-linux/include/linux/fslog.h =================================================================== --- git-linux.orig/include/linux/fslog.h 2004-04-06 17:27:52.000000000 +0400 +++ git-linux/include/linux/fslog.h 2006-08-24 22:40:18.000000000 +0400 @@ -0,0 +1,18 @@ +/* + * file system logging + */ +#ifndef _LINUX_FSLOG_H +#define _LINUX_FSLOG_H + +enum fslog_rec_type { + FSLOG_READ = 'R', + FSLOG_RA = 'r', + FSLOG_WRITE = 'W', + FSLOG_PFAULT = 'P', + FSLOG_PUNCH = 'T' +}; + +void fslog(const struct address_space *mapping, pgoff_t index, + const struct page *page, enum fslog_rec_type type); + +#endif /* _LINUX_FSLOG_H */ Index: git-linux/lib/Makefile =================================================================== --- git-linux.orig/lib/Makefile 2006-08-17 20:18:39.000000000 +0400 +++ git-linux/lib/Makefile 2006-08-17 20:19:06.000000000 +0400 @@ -11,7 +11,7 @@ lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o kref.o kobject_uevent.o klist.o -obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o +obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o fslog.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG Index: git-linux/lib/fslog.c =================================================================== --- git-linux.orig/lib/fslog.c 2004-04-06 17:27:52.000000000 +0400 +++ git-linux/lib/fslog.c 2006-08-25 16:53:26.000000000 +0400 @@ -0,0 +1,217 @@ +/* + * exported-global-mod - test exported relay file ops with a global buffer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2005 + * + * 2005 Tom Zanussi + * + */ + +#include +#include +#include +#include + +enum { + FR_DIR, + FR_HIT, + FR_UPTODATE, + FR_DIRTY, + FR_REF, + FR_ACTIVE, + FR_WRITEBACK, + FR_RECLAIM +}; + +struct fslog_record { + __u32 fr_no; + __u32 fr_time; + + __u32 fr_dev; + __u32 fr_ino; + + __u32 fr_gen; + __u32 fr_index; + + __u16 fr_pid; + __u8 fr_type; + __u8 fr_bits; + __u32 fr_pad; + + char fr_comm[16]; + char fr_name[16]; +}; + +static __u32 __grab_time(void) +{ +#ifdef CONFIG_X86 + /* + * do_gettimeofday() goes backwards sometimes :(. Usethe TSC + */ + unsigned long long ret; + extern unsigned int cpu_khz; + + rdtscll(ret); + do_div(ret, cpu_khz / 1000); + return ret; +#else + struct timeval now; + unsigned long long ret; + + do_gettimeofday(&now); + ret = now.tv_sec; + ret *= 1000000; + ret += now.tv_usec; + return ret; +#endif +} + +/* This app's relayfs channel will be /debug/fslog/global0 */ +#define APP_DIR "fslog" + +/* app data */ +static struct rchan * chan = NULL; +static struct dentry * dir; +static size_t subbuf_size = 262144; +static size_t n_subbufs = 4; +static DEFINE_SPINLOCK(chan_lock); +static atomic_t no = ATOMIC_INIT(0); + +static inline __u8 getbit(int condition, int shift) +{ + return !!condition << shift; +} + +static inline __u8 pagebit(const struct page *page, int pflag, int shift) +{ + return getbit(page->flags & (1 << pflag), shift); +} + +void fslog(const struct address_space *mapping, pgoff_t index, + const struct page *page, enum fslog_rec_type type) +{ + const struct inode *inode = mapping->host; + + struct fslog_record rec = { + .fr_no = atomic_inc_return(&no), + .fr_time = __grab_time(), + .fr_dev = inode->i_sb->s_dev, + .fr_ino = inode->i_ino, + .fr_gen = inode->i_generation, + .fr_index = index, + .fr_pid = current->pid, + .fr_type = type, + .fr_bits = getbit(S_ISDIR(inode->i_mode), FR_DIR) + }; + if (page != NULL) { + rec.fr_bits |= (1 << FR_HIT) | + pagebit(page, PG_uptodate, FR_UPTODATE) | + pagebit(page, PG_dirty, FR_DIRTY) | + pagebit(page, PG_referenced, FR_REF) | + pagebit(page, PG_active, FR_ACTIVE) | + pagebit(page, PG_writeback, FR_WRITEBACK) | + pagebit(page, PG_reclaim, FR_RECLAIM); + } + memcpy(rec.fr_comm, current->comm, ARRAY_SIZE(rec.fr_comm)); + rec.fr_name[0] = 0; + if (!list_empty(&inode->i_dentry)) { + struct dentry *dentry; + + dentry = list_entry(inode->i_dentry.next, + struct dentry, d_alias); + if (dentry != NULL && dentry->d_name.name != NULL) { + int len; + + len = min(ARRAY_SIZE(rec.fr_name), dentry->d_name.len); + memcpy(rec.fr_name, dentry->d_name.name, len); + } + } + + spin_lock(&chan_lock); + if (chan != NULL) + relay_write(chan, &rec, sizeof rec); + spin_unlock(&chan_lock); +} +EXPORT_SYMBOL(fslog); + +/* + * file_create() callback. Creates relay file in debugfs. + */ +static struct dentry *create_buf_file_handler(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global) +{ + struct dentry *buf_file; + + buf_file = debugfs_create_file(filename, mode, parent, buf, + &relay_file_operations); + *is_global = 1; + + return buf_file; +} + +/* + * file_remove() default callback. Removes relay file in debugfs. + */ +static int remove_buf_file_handler(struct dentry *dentry) +{ + printk("remove_buf_file_handler: dentry %p\n", dentry); + + debugfs_remove(dentry); + + return 0; +} + +/* + * relayfs callbacks + */ +static struct rchan_callbacks relayfs_callbacks = +{ + .create_buf_file = create_buf_file_handler, + .remove_buf_file = remove_buf_file_handler, +}; + + +/** + * module init - creates channel management control files + * + * Returns 0 on success, negative otherwise. + */ +static int init(void) +{ + dir = debugfs_create_dir(APP_DIR, NULL); + if (!dir) { + printk("Couldn't create debugfs app directory.\n"); + return -ENOMEM; + } + + chan = relay_open("global", dir, subbuf_size, + n_subbufs, &relayfs_callbacks); + + if (!chan) { + printk("relay app channel creation failed\n"); + debugfs_remove(dir); + return -ENOMEM; + } + + return 0; +} + + +late_initcall(init); Index: git-linux/mm/filemap.c =================================================================== --- git-linux.orig/mm/filemap.c 2006-08-17 20:18:32.000000000 +0400 +++ git-linux/mm/filemap.c 2006-08-17 20:39:29.000000000 +0400 @@ -30,6 +30,7 @@ #include #include #include +#include #include "filemap.h" #include "internal.h" @@ -927,6 +928,7 @@ void do_generic_mapping_read(struct addr find_page: page = find_get_page(mapping, index); + fslog(mapping, index, page, FSLOG_READ); if (unlikely(page == NULL)) { handle_ra_miss(mapping, &ra, index); goto no_cached_page; @@ -1395,6 +1397,7 @@ retry_all: */ retry_find: page = find_get_page(mapping, pgoff); + fslog(mapping, pgoff, page, FSLOG_PFAULT); if (!page) { unsigned long ra_pages; @@ -1866,6 +1869,7 @@ __grab_cache_page(struct address_space * struct page *page; repeat: page = find_lock_page(mapping, index); + fslog(mapping, index, page, FSLOG_WRITE); if (!page) { if (!*cached_page) { *cached_page = page_cache_alloc(mapping); Index: git-linux/mm/readahead.c =================================================================== --- git-linux.orig/mm/readahead.c 2006-08-17 20:18:32.000000000 +0400 +++ git-linux/mm/readahead.c 2006-08-17 20:22:34.000000000 +0400 @@ -14,6 +14,7 @@ #include #include #include +#include void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) { @@ -290,6 +291,7 @@ __do_page_cache_readahead(struct address break; page = radix_tree_lookup(&mapping->page_tree, page_offset); + fslog(mapping, page_offset, page, FSLOG_RA); if (page) continue; Index: git-linux/mm/truncate.c =================================================================== --- git-linux.orig/mm/truncate.c 2006-08-09 17:12:47.000000000 +0400 +++ git-linux/mm/truncate.c 2006-08-26 21:39:46.000000000 +0400 @@ -14,6 +14,7 @@ #include #include /* grr. try_to_release_page, do_invalidatepage */ +#include static inline void truncate_partial_page(struct page *page, unsigned partial) @@ -117,6 +118,8 @@ void truncate_inode_pages_range(struct a pgoff_t next; int i; + fslog(mapping, start, NULL, FSLOG_PUNCH); + if (mapping->nrpages == 0) return;