From c23034aa2b2101e0220d811161613983f58821a2 Mon Sep 17 00:00:00 2001 From: adilger Date: Tue, 25 Jan 2000 21:59:07 +0000 Subject: [PATCH] obdfs/super.c: add call to flush pages when unmounting filesystem obdfs/flushd.c: pass "check_time" parameter to flush routines obdfs/namei.c: fixed rename call to getpage to use offset, not index snap/*: tested snapshots with new vector I/O, async writes - OK tests/snaprun.sh: small script to step through testing of some snapshot features --- lustre/demos/config.sh | 11 ++++++++ lustre/include/linux/obd_support.h | 2 +- lustre/include/linux/obdfs.h | 48 +++++++++++++++++++++-------------- lustre/obdfs/flushd.c | 51 +++++++++++++++++--------------------- lustre/obdfs/namei.c | 13 +++++----- lustre/obdfs/rw.c | 38 +++++++++++++++------------- lustre/obdfs/super.c | 14 +++++------ lustre/obdfs/symlink.c | 4 +-- 8 files changed, 102 insertions(+), 79 deletions(-) diff --git a/lustre/demos/config.sh b/lustre/demos/config.sh index c72a010..fd87c13 100644 --- a/lustre/demos/config.sh +++ b/lustre/demos/config.sh @@ -40,3 +40,14 @@ plog () { fi } +# A routine to display a command, and prompt user if it should be run +qrun () { + echo + echo -n "Run '$*' [Y/n]?'"; + read JUNK + + case $JUNK in + n*|N*) echo "'$*' not run" ;; + *) plog $* ;; + esac +} diff --git a/lustre/include/linux/obd_support.h b/lustre/include/linux/obd_support.h index a9eafc2..68778af 100644 --- a/lustre/include/linux/obd_support.h +++ b/lustre/include/linux/obd_support.h @@ -83,7 +83,7 @@ extern int obd_print_entry; /* OBDFS inode information */ #define OIDEBUG(inode) { \ ICDEBUG(inode);\ - printk("oinfo: flags 0x%08x\n", OBDFS_INFO(inode)->oi_flags);\ + printk("oinfo: flags 0x%08x\n", obdfs_i2info(inode)->oi_flags);\ /* obdfs_print_plist(inode); */\ } diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index 62be45e..474a5e3 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -18,8 +18,10 @@ void obdfs_read_inode(struct inode *inode); /* flush.c */ -int flushd_init(void); - +int obdfs_flushd_init(void); +int obdfs_flushd_cleanup(void); +int obdfs_flush_reqs(struct list_head *inode_list, int check_time); +void obdfs_flush_dirty_pages(int check_time); /* rw.c */ int obdfs_do_writepage(struct inode *, struct page *, int sync); @@ -27,8 +29,11 @@ int obdfs_init_pgrqcache(void); void obdfs_cleanup_pgrqcache(void); int obdfs_readpage(struct dentry *dentry, struct page *page); int obdfs_writepage(struct dentry *dentry, struct page *page); -struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked); -int obdfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf); +struct page *obdfs_getpage(struct inode *inode, unsigned long offset, + int create, int locked); +int obdfs_write_one_page(struct file *file, struct page *page, + unsigned long offset, unsigned long bytes, + const char * buf); void obdfs_dequeue_reqs(struct inode *inode); /* namei.c */ @@ -38,16 +43,22 @@ int obdfs_mkdir(struct inode *dir, struct dentry *dentry, int mode); int obdfs_rmdir(struct inode *dir, struct dentry *dentry); int obdfs_unlink(struct inode *dir, struct dentry *dentry); int obdfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev); -int obdfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); -int obdfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry); -int obdfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry); +int obdfs_symlink(struct inode *dir, struct dentry *dentry, + const char *symname); +int obdfs_link(struct dentry *old_dentry, struct inode *dir, + struct dentry *dentry); +int obdfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry); + /* dir.c */ int obdfs_check_dir_entry (const char * function, struct inode * dir, struct ext2_dir_entry_2 * de, struct page * page, unsigned long offset); + /* symlink.c */ int obdfs_readlink (struct dentry *, char *, int); -struct dentry *obdfs_follow_link(struct dentry *, struct dentry *, unsigned int); +struct dentry *obdfs_follow_link(struct dentry *, struct dentry *, + unsigned int); /* list of all OBDFS super blocks */ @@ -86,26 +97,26 @@ struct obdfs_inode_info { char oi_inline[OBD_INLINESZ]; }; -#define OBDFS_INFO(inode) ((struct obdfs_inode_info *)(&(inode)->u.generic_ip)) +static inline struct obdfs_inode_info *obdfs_i2info(struct inode *inode) +{ + return (struct obdfs_inode_info *)&(inode->u.generic_ip); +} static inline struct obdfs_sb_info *obdfs_i2sbi(struct inode *inode) { - struct obdfs_sb_info *sbi; - - sbi = (struct obdfs_sb_info *) &(inode->i_sb->u.generic_sbp); - return sbi; + return (struct obdfs_sb_info *) &(inode->i_sb->u.generic_sbp); } static inline struct list_head *obdfs_iplist(struct inode *inode) { - struct obdfs_inode_info *info = (struct obdfs_inode_info *)&inode->u.generic_ip; + struct obdfs_inode_info *info = obdfs_i2info(inode); return &info->oi_pages; } static inline struct list_head *obdfs_islist(struct inode *inode) { - struct obdfs_inode_info *info = (struct obdfs_inode_info *)&inode->u.generic_ip; + struct obdfs_inode_info *info = obdfs_i2info(inode); return &info->oi_inodes; } @@ -113,6 +124,7 @@ static inline struct list_head *obdfs_islist(struct inode *inode) static inline struct list_head *obdfs_slist(struct inode *inode) { struct obdfs_sb_info *sbi = obdfs_i2sbi(inode); + return &sbi->osi_inodes; } @@ -159,12 +171,12 @@ extern struct inode_operations obdfs_symlink_inode_operations; static inline int obdfs_has_inline(struct inode *inode) { - return (OBDFS_INFO(inode)->oi_flags & OBD_FL_INLINEDATA); + return (obdfs_i2info(inode)->oi_flags & OBD_FL_INLINEDATA); } static void inline obdfs_from_inode(struct obdo *oa, struct inode *inode) { - struct obdfs_inode_info *oinfo = OBDFS_INFO(inode); + struct obdfs_inode_info *oinfo = obdfs_i2info(inode); CDEBUG(D_INODE, "src inode %ld, dst obdo %ld valid 0x%08x\n", inode->i_ino, (long)oa->o_id, oa->o_valid); @@ -179,7 +191,7 @@ static void inline obdfs_from_inode(struct obdo *oa, struct inode *inode) static void inline obdfs_to_inode(struct inode *inode, struct obdo *oa) { - struct obdfs_inode_info *oinfo = OBDFS_INFO(inode); + struct obdfs_inode_info *oinfo = obdfs_i2info(inode); CDEBUG(D_INODE, "src obdo %ld valid 0x%08x, dst inode %ld\n", (long)oa->o_id, oa->o_valid, inode->i_ino); diff --git a/lustre/obdfs/flushd.c b/lustre/obdfs/flushd.c index c090a0c..af7341e 100644 --- a/lustre/obdfs/flushd.c +++ b/lustre/obdfs/flushd.c @@ -35,7 +35,6 @@ #include - struct { int nfract; /* Percentage of buffer cache dirty to activate bdflush */ @@ -51,7 +50,6 @@ struct { /* } pupd_prm = {40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ }; */ } pupd_prm = {40, 500, 64, 256, 10*HZ, 30*HZ, 5*HZ }; - /* Called with the superblock list lock */ static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo, int nr_slots, struct page **pages, char **bufs, @@ -111,7 +109,7 @@ static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo, EXIT; return num; -} +} /* obdfs_enqueue_pages */ /* dequeue requests for a dying inode */ void obdfs_dequeue_reqs(struct inode *inode) @@ -145,7 +143,7 @@ void obdfs_dequeue_reqs(struct inode *inode) } iput(inode); obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); -} +} /* obdfs_dequeue_reqs */ /* Remove writeback requests for the superblock */ int obdfs_flush_reqs(struct list_head *inode_list, int check_time) @@ -212,7 +210,8 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time) &pages[num_io], &bufs[num_io], &counts[num_io], &offsets[num_io], - &flags[num_obdos], 1); + &flags[num_obdos], + check_time); CDEBUG(D_INODE, "FLUSHED inode %ld, pages flushed: %d\n", inode->i_ino, res); if ( res < 0 ) { @@ -289,21 +288,21 @@ void obdfs_flush_dirty_pages(int check_time) { struct list_head *sl; + ENTRY; sl = &obdfs_super_list; while ( (sl = sl->next) != &obdfs_super_list ) { struct obdfs_sb_info *sbi = list_entry(sl, struct obdfs_sb_info, osi_list); /* walk write requests here, use the sb, check the time */ - obdfs_flush_reqs(&sbi->osi_inodes, 0); + obdfs_flush_reqs(&sbi->osi_inodes, check_time); } - + EXIT; } static struct task_struct *pupdated; - static int pupdate(void *unused) { struct task_struct * tsk = current; @@ -319,6 +318,7 @@ static int pupdate(void *unused) sprintf(tsk->comm, "pupdated"); pupdated = current; + MOD_INC_USE_COUNT; /* XXX until send_sig works */ printk("pupdated activated...\n"); /* sigstop and sigcont will stop and wakeup pupdate */ @@ -339,9 +339,8 @@ static int pupdate(void *unused) else { stop_pupdate: - obdfs_flush_dirty_pages(0); tsk->state = TASK_STOPPED; - /* MOD_DEC_USE_COUNT; */ + MOD_DEC_USE_COUNT; /* XXX until send_sig works */ printk("pupdated stopped...\n"); return 0; } @@ -360,42 +359,38 @@ static int pupdate(void *unused) if (stopped) goto stop_pupdate; } - /* asynchronous setattr etc for the future ... */ - /* flush_inodes(); */ + /* asynchronous setattr etc for the future ... + flush_inodes(); + */ + /* we don't currently check the time on the pages obdfs_flush_dirty_pages(1); + */ + obdfs_flush_dirty_pages(0); } } -int flushd_init(void) +int obdfs_flushd_init(void) { /* kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); */ - /* MOD_INC_USE_COUNT; */ kernel_thread(pupdate, NULL, 0); printk("flushd inited\n"); return 0; } -int flushd_cleanup(void) +int obdfs_flushd_cleanup(void) { - /* this should deliver a signal to */ - - - /* XXX Andreas, we will do this later, for now, you must kill - pupdated with a SIGTERM from userland, before unloading obdfs.o - */ + ENTRY; + /* deliver a signal to pupdated to shut it down + XXX need to kill it from user space for now XXX if (pupdated) { - /* then let it run at least once, before continuing */ - - /* XXX need to do something like this here: - send_sig(SIGTERM, current, 0); - */ - 1; - /*obdfs_flush_dirty_pages(0); */ + send_sig_info(SIGTERM, 1, pupdated); } + */ + EXIT; /* not reached */ return 0; diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index c8fde32..87ddc55 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -874,7 +874,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, for (l = 0; l < inode->i_sb->s_blocksize - 1 && symname [l]; l++) ; - oinfo = OBDFS_INFO(inode); + oinfo = obdfs_i2info(inode); if (l >= sizeof(oinfo->oi_inline)) { CDEBUG(D_INODE, "l=%d, normal symlink\n", l); @@ -1065,9 +1065,10 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(old_dir); if (dir_page) { - PARENT_INO(page_address(dir_page)) = le32_to_cpu(new_dir->i_ino); + PARENT_INO(page_address(dir_page)) =le32_to_cpu(new_dir->i_ino); + err = obdfs_do_writepage(old_inode, dir_page, + IS_SYNC(old_inode)); /* XXX handle err */ - err = obdfs_do_writepage(old_inode, dir_page, IS_SYNC(old_inode)); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { @@ -1084,10 +1085,11 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, /* lock the old_page and release unlocked copy */ CDEBUG(D_INODE, "old_page at %p\n", old_page); page_cache_release(old_page); - old_page = obdfs_getpage(old_dir, index >> PAGE_SHIFT, 0, LOCKED); + old_page = obdfs_getpage(old_dir, index << PAGE_SHIFT, 0, + LOCKED); CDEBUG(D_INODE, "old_page at %p\n", old_page); - /* XXX handle err */ err = obdfs_do_writepage(old_dir, old_page, IS_SYNC(old_dir)); + /* XXX handle err */ } err = obdfs_do_writepage(new_dir, new_page, IS_SYNC(new_dir)); @@ -1106,6 +1108,5 @@ end_rename: if (dir_page) page_cache_release(dir_page); - return err; } /* obdfs_rename */ diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 78bc0b0..9bcc915 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -34,16 +34,11 @@ #include -int obdfs_flush_reqs(struct list_head *page_list, - int flush_inode, int check_time); - -void obdfs_flush_dirty_pages(int check_time); - /* SYNCHRONOUS I/O for an inode */ static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create) { - obd_count num_oa = 1; - obd_count oa_bufs = 1; + obd_count num_obdo = 1; + obd_count bufs_per_obdo = 1; struct obdo *oa; char *buf = (char *)page_address(page); obd_size count = PAGE_SIZE; @@ -59,8 +54,8 @@ static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create) } obdfs_from_inode(oa, inode); - err = IOPS(inode, brw)(rw, IID(inode), num_oa, &oa, &oa_bufs, &buf, - &count, &offset, &flags); + err = IOPS(inode, brw)(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo, + &buf, &count, &offset, &flags); if ( !err ) obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */ @@ -90,6 +85,8 @@ int obdfs_readpage(struct dentry *dentry, struct page *page) } /* obdfs_readpage */ static kmem_cache_t *obdfs_pgrq_cachep = NULL; + +/* XXX should probably have one of these per superblock */ static int obdfs_cache_count = 0; int obdfs_init_pgrqcache(void) @@ -119,7 +116,8 @@ int obdfs_init_pgrqcache(void) inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq) { obdfs_cache_count--; - CDEBUG(D_INODE, "deleting page %p from list [count %d]\n", pgrq->rq_page, obdfs_cache_count); + CDEBUG(D_INODE, "deleting page %p from list [count %d]\n", + pgrq->rq_page, obdfs_cache_count); list_del(&pgrq->rq_plist); kmem_cache_free(obdfs_pgrq_cachep, pgrq); } @@ -178,7 +176,8 @@ obdfs_find_in_page_list(struct inode *inode, struct page *page) /* called with the list lock held */ -static struct page* obdfs_find_page_index(struct inode *inode, unsigned long index) +static struct page* obdfs_find_page_index(struct inode *inode, + unsigned long index) { struct list_head *page_list = obdfs_iplist(inode); struct list_head *tmp; @@ -201,7 +200,9 @@ static struct page* obdfs_find_page_index(struct inode *inode, unsigned long ind pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist); page = pgrq->rq_page; if (index == page->index) { - CDEBUG(D_INODE, "INDEX SEARCH found page %p in list, index %ld\n", page, index); + CDEBUG(D_INODE, + "INDEX SEARCH found page %p, index %ld\n", + page, index); EXIT; return page; } @@ -231,7 +232,8 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, /* release the pages from the page cache */ while ( num_io > 0 ) { num_io--; - CDEBUG(D_INODE, "calling put_page for %p, index %ld\n", pages[num_io], pages[num_io]->index); + CDEBUG(D_INODE, "calling put_page for %p, index %ld\n", + pages[num_io], pages[num_io]->index); put_page(pages[num_io]); } @@ -274,6 +276,7 @@ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page) pgrq->rq_page = page; get_page(pgrq->rq_page); list_add(&pgrq->rq_plist, obdfs_iplist(inode)); + obdfs_cache_count++; } /* If inode isn't already on the superblock inodes list, add it, @@ -295,7 +298,6 @@ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page) EXIT; return res; - /*return 0;*/ } /* obdfs_add_page_to_cache */ @@ -371,7 +373,8 @@ int obdfs_write_one_page(struct file *file, struct page *page, * * modeled on NFS code. */ -struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked) +struct page *obdfs_getpage(struct inode *inode, unsigned long offset, + int create, int locked) { struct page *page_cache; int index; @@ -384,7 +387,7 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create offset = offset & PAGE_CACHE_MASK; CDEBUG(D_INODE, "ino: %ld, offset %ld, create %d, locked %d\n", inode->i_ino, offset, create, locked); - index = offset >> PAGE_CACHE_SHIFT; + index = offset >> PAGE_CACHE_SHIFT; page = NULL; @@ -416,7 +419,8 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create if ( obdfs_find_page_index(inode, index) ) { - printk("OVERWRITE: found dirty page %p, index %ld\n", page, page->index); + CDEBUG(D_INODE, "OVERWRITE: found dirty page %p, index %ld\n", + page, page->index); } err = obdfs_brw(READ, inode, page, create); diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index f4cdf0c..2a79a4e 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -195,6 +195,7 @@ static struct super_block * obdfs_read_super(struct super_block *sb, goto ERR; } + /* list of dirty inodes, and a mutex to hold while modifying it */ INIT_LIST_HEAD(&sbi->osi_inodes); sema_init(&sbi->osi_list_mutex, 1); @@ -265,22 +266,20 @@ ERR: return NULL; } -/* XXX remove the super to the obdfs_super_list */ + static void obdfs_put_super(struct super_block *sb) { struct obdfs_sb_info *sbi; ENTRY; - - sb->s_dev = 0; - /* XXX flush stuff */ sbi = (struct obdfs_sb_info *) &sb->u.generic_sbp; + obdfs_flush_reqs(&sbi->osi_inodes, 0); OPS(sb,disconnect)(ID(sb)); list_del(&sbi->osi_list); - memset(sbi, 0, sizeof(* sbi)); + memset(sbi, 0, sizeof(*sbi)); printk("OBDFS: Bye bye.\n"); @@ -324,7 +323,7 @@ void obdfs_read_inode(struct inode *inode) } else { init_special_inode(inode, inode->i_mode, /* XXX need to fill in the ext2 side */ - ((long *)OBDFS_INFO(inode)->oi_inline)[0]); + ((long *)obdfs_i2info(inode)->oi_inline)[0]); } return; @@ -463,7 +462,7 @@ int init_obdfs(void) if (err) return err; - flushd_init(); + obdfs_flushd_init(); return register_filesystem(&obdfs_fs_type); } @@ -478,6 +477,7 @@ void cleanup_module(void) { ENTRY; + obdfs_flushd_cleanup(); obdfs_sysctl_clean(); obdfs_cleanup_pgrqcache(); unregister_filesystem(&obdfs_fs_type); diff --git a/lustre/obdfs/symlink.c b/lustre/obdfs/symlink.c index dc567b8..7aa2959 100644 --- a/lustre/obdfs/symlink.c +++ b/lustre/obdfs/symlink.c @@ -39,7 +39,7 @@ struct dentry * obdfs_follow_link(struct dentry * dentry, struct dentry *base, char * link; ENTRY; - link = OBDFS_INFO(inode)->oi_inline; + link = obdfs_i2info(inode)->oi_inline; if (!obdfs_has_inline(inode)) { OIDEBUG(inode); page = obdfs_getpage(inode, 0, 0, 0); @@ -72,7 +72,7 @@ int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen) if (buflen > inode->i_sb->s_blocksize - 1) buflen = inode->i_sb->s_blocksize - 1; - link = OBDFS_INFO(inode)->oi_inline; + link = obdfs_i2info(inode)->oi_inline; if (!obdfs_has_inline(inode)) { OIDEBUG(inode); page = obdfs_getpage(inode, 0, 0, 0); -- 1.8.3.1