From ee493dbaf6529247f2a69586a383b825ce6e6908 Mon Sep 17 00:00:00 2001 From: braam Date: Sun, 23 Jan 2000 16:12:32 +0000 Subject: [PATCH] Several bugfixes. Most notably ext2obd_brw is still totally broken, fix that first. --- lustre/include/linux/obdfs.h | 1 + lustre/obdfs/flushd.c | 74 ++++++++++++++++++++++--------- lustre/obdfs/rw.c | 102 +++++++++++++++++++++++++++++++------------ lustre/obdfs/super.c | 5 ++- 4 files changed, 134 insertions(+), 48 deletions(-) diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index 6949f42..67a0ed1 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -29,6 +29,7 @@ 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); +void obdfs_dequeue_reqs(struct inode *inode); /* namei.c */ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry); diff --git a/lustre/obdfs/flushd.c b/lustre/obdfs/flushd.c index d12c63f..7d6f798 100644 --- a/lustre/obdfs/flushd.c +++ b/lustre/obdfs/flushd.c @@ -51,6 +51,13 @@ 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 }; +#if 0 +static void obdfs_lock_page(struct page *page) +{ + while (TryLockPage(page)) + ___wait_on_page(page); +} +#endif static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo, int nr_slots, struct page **pages, char **bufs, @@ -74,13 +81,14 @@ static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo, *flag = OBD_BRW_CREATE; tmp = page_list; - while ( (tmp = tmp->next) != page_list && (num < nr_slots) ) { + while ( ((tmp = tmp->next) != page_list) && (num < nr_slots) ) { struct obdfs_pgrq *req; struct page *page; req = list_entry(tmp, struct obdfs_pgrq, rq_plist); page = req->rq_page; + if (check_time && (jiffies - req->rq_jiffies) < pupd_prm.age_buffer) continue; @@ -89,17 +97,20 @@ static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo, * Note that obdfs_pgrq_del() also deletes the request. */ obdfs_pgrq_del(req); - + /* + obdfs_lock_page(page); + */ if ( !page ) { CDEBUG(D_INODE, "no page \n"); continue; } - CDEBUG(D_INODE, "adding page %p to vector\n", page); bufs[num] = (char *)page_address(page); pages[num] = page; counts[num] = PAGE_SIZE; offsets[num] = ((obd_off)page->index) << PAGE_SHIFT; + CDEBUG(D_INODE, "ENQ inode %ld, page %p addr %p to vector\n", + inode->i_ino, page, (char *)page_address(page)); num++; } @@ -111,10 +122,40 @@ static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo, return num; } +/* dequeue requests for a dying inode */ +void obdfs_dequeue_reqs(struct inode *inode) +{ + + struct list_head *tmp; + + tmp = obdfs_islist(inode); + if ( list_empty(tmp) ) { + EXIT; + return; + } + + /* take it out of the super list */ + list_del(tmp); + INIT_LIST_HEAD(obdfs_islist(inode)); + + tmp = obdfs_iplist(inode); + while ( (tmp = tmp->next) != obdfs_iplist(inode) ) { + struct obdfs_pgrq *req; + struct page *page; + + req = list_entry(tmp, struct obdfs_pgrq, rq_plist); + page = req->rq_page; + /* take it out of the list and free */ + obdfs_pgrq_del(req); + /* now put the page away */ + put_page(page); + } + +} + /* Remove writeback requests for the superblock */ -int obdfs_flush_reqs(struct list_head *inode_list, int flush_inode, - int check_time) +int obdfs_flush_reqs(struct list_head *inode_list, int check_time) { struct list_head *tmp = inode_list; int total_io = 0; @@ -169,6 +210,8 @@ int obdfs_flush_reqs(struct list_head *inode_list, int flush_inode, &counts[num_io], &offsets[num_io], &flags[num_obdos],1); + CDEBUG(D_INODE, "FLUSHED inode %ld, pages flushed: %d\n", + inode->i_ino, res); if ( res < 0 ) { err = res; goto ERR; @@ -220,7 +263,7 @@ ERR: } /* obdfs_remove_pages_from_cache */ -static void obdfs_flush_dirty_pages(int check_time) +void obdfs_flush_dirty_pages(int check_time) { struct list_head *sl; @@ -230,20 +273,9 @@ static void obdfs_flush_dirty_pages(int check_time) 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, 1); + obdfs_flush_reqs(&sbi->osi_inodes, 0); } -#if 0 - /* again, but now we wait for completion */ - sl = &obdfs_super_list; - while ( (sl = sl->next) != &obdfs_super_list ) { - struct obdfs_sb_info *sbi = - list_entry(sl, struct obdfs_sb_info, sl_chain); - - /* walk write requests here */ - obdfs_flush_reqs(&sbi->osi_pages, 0, check_time); - } -#endif } @@ -285,6 +317,7 @@ static int pupdate(void *unused) else { stop_pupdate: + obdfs_flush_dirty_pages(0); tsk->state = TASK_STOPPED; /* MOD_DEC_USE_COUNT; */ printk("pupdated stopped...\n"); @@ -307,7 +340,7 @@ static int pupdate(void *unused) } /* asynchronous setattr etc for the future ... */ /* flush_inodes(); */ - obdfs_flush_dirty_pages(1); + obdfs_flush_dirty_pages(1); } } @@ -337,7 +370,8 @@ int flushd_cleanup(void) /* XXX need to do something like this here: send_sig(SIGTERM, current, 0); */ - 1; + 1; + /*obdfs_flush_dirty_pages(0); */ } /* not reached */ diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 5320744..1f451d8 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -37,6 +37,7 @@ 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) @@ -89,6 +90,7 @@ int obdfs_readpage(struct dentry *dentry, struct page *page) } /* obdfs_readpage */ static kmem_cache_t *obdfs_pgrq_cachep = NULL; +static int obdfs_cache_count = 0; int obdfs_init_pgrqcache(void) { @@ -116,7 +118,8 @@ int obdfs_init_pgrqcache(void) inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq) { - CDEBUG(D_INODE, "deleting page %p from list\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); } @@ -125,8 +128,8 @@ void obdfs_cleanup_pgrqcache(void) { ENTRY; if (obdfs_pgrq_cachep != NULL) { - CDEBUG(D_INODE, "destroying obdfs_pgrqcache at %p\n", - obdfs_pgrq_cachep); + CDEBUG(D_INODE, "destroying obdfs_pgrqcache at %p, count %d\n", + obdfs_pgrq_cachep, obdfs_cache_count); if (kmem_cache_destroy(obdfs_pgrq_cachep)) printk(KERN_INFO "obd_cleanup_pgrqcache: unable to free all of cache\n"); } else @@ -172,6 +175,40 @@ obdfs_find_in_page_list(struct inode *inode, struct page *page) } /* obdfs_find_in_page_list */ +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; + struct page *page; + + ENTRY; + + CDEBUG(D_INODE, "looking for inode %ld pageindex %ld\n", inode->i_ino, index); + OIDEBUG(inode); + + if (list_empty(page_list)) { + EXIT; + return NULL; + } + tmp = page_list; + while ( (tmp = tmp->next) != page_list ) { + struct obdfs_pgrq *pgrq; + + pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist); + page = pgrq->rq_page; + if (index == page->index) { + CDEBUG(D_INODE, "INDEX SEARC found page %p in list, index %ld\n", page, index); + EXIT; + return page; + } + } + + EXIT; + return NULL; +} /* obdfs_find_in_page_list */ + + /* call and free pages from Linux page cache */ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, obd_count num_obdos, struct obdo **obdos, @@ -191,7 +228,10 @@ 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\n", pages[num_io]); + CDEBUG(D_INODE, "calling put_page for %p, index %ld\n", pages[num_io], pages[num_io]->index); + /* + UnlockPage(pages[num_io]); + */ put_page(pages[num_io]); } @@ -213,43 +253,44 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, */ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page) { - struct obdfs_pgrq *pgrq; + int res = 0; ENTRY; - pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL); - CDEBUG(D_INODE, "adding inode %ld page %p, pgrq: %p\n", - inode->i_ino, page, pgrq); - if (!pgrq) { - EXIT; - return -ENOMEM; - } - memset(pgrq, 0, sizeof(*pgrq)); - - pgrq->rq_page = page; - - get_page(pgrq->rq_page); /* If this page isn't already in the inode page list, add it */ if ( !obdfs_find_in_page_list(inode, page) ) { - CDEBUG(D_INODE, "adding page %p to inode list %p\n", page, - obdfs_iplist(inode)); + struct obdfs_pgrq *pgrq; + pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL); + CDEBUG(D_INODE, "adding inode %ld page %p, pgrq: %p, cache count [%d]\n", + inode->i_ino, page, pgrq, obdfs_cache_count); + if (!pgrq) { + EXIT; + return -ENOMEM; + } + memset(pgrq, 0, sizeof(*pgrq)); + + pgrq->rq_page = page; + get_page(pgrq->rq_page); list_add(&pgrq->rq_plist, obdfs_iplist(inode)); } /* If inode isn't already on the superblock inodes list, add it */ if ( list_empty(obdfs_islist(inode)) ) { - CDEBUG(D_INODE, "adding inode %p to superblock list %p\n", - obdfs_islist(inode), obdfs_slist(inode)); + CDEBUG(D_INODE, "adding inode %ld to superblock list %p\n", + inode->i_ino, obdfs_slist(inode)); list_add(obdfs_islist(inode), obdfs_slist(inode)); } - EXIT; /* XXX For testing purposes, we write out the page here. * In the future, a flush daemon will write out the page. - return obdfs_flush_reqs(obdfs_slist(inode), 0, 0); + res = obdfs_flush_reqs(obdfs_slist(inode), 0); + obdfs_flush_dirty_pages(1); */ - return 0; + + EXIT; + return res; + /*return 0;*/ } /* obdfs_add_page_to_cache */ @@ -259,15 +300,17 @@ int obdfs_do_writepage(struct inode *inode, struct page *page, int sync) int err; ENTRY; - PDEBUG(page, "WRITEPAGE"); + /* PDEBUG(page, "WRITEPAGE"); */ if ( sync ) err = obdfs_brw(WRITE, inode, page, 1); - else + else { err = obdfs_add_page_to_cache(inode, page); + CDEBUG(D_IOCTL, "DO_WR ino: %ld, page %p, err %d, uptodata %d\n", inode->i_ino, page, err, Page_Uptodate(page)); + } if ( !err ) SetPageUptodate(page); - PDEBUG(page,"WRITEPAGE"); + /* PDEBUG(page,"WRITEPAGE"); */ EXIT; return err; } /* obdfs_do_writepage */ @@ -362,6 +405,11 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create return page; } + + if ( obdfs_find_page_index(inode, offset) ) { + printk("OVERWRITE: found dirty page %p, index %ld\n", page, page->index); + } + err = obdfs_brw(READ, inode, page, create); if ( err ) { diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index fafdf96..e5d04a7 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -308,7 +308,7 @@ void obdfs_read_inode(struct inode *inode) INIT_LIST_HEAD(obdfs_islist(inode)); /* list of inodes in superblock */ obdo_free(oa); - OIDEBUG(inode); + /* OIDEBUG(inode); */ if (S_ISREG(inode->i_mode)) { inode->i_op = &obdfs_file_inode_operations; @@ -374,6 +374,9 @@ static void obdfs_delete_inode(struct inode *inode) oa->o_valid = OBD_MD_FLNOTOBD; obdfs_from_inode(oa, inode); + /* free the cache pages that might be hangning around */ + obdfs_dequeue_reqs(inode); + err = IOPS(inode, destroy)(IID(inode), oa); obdo_free(oa); -- 1.8.3.1