From cf651de01ba1e36c99f4acf098e73a96f927ff20 Mon Sep 17 00:00:00 2001 From: braam Date: Mon, 10 Jan 2000 14:50:06 +0000 Subject: [PATCH] Changes for the flushdaemon. Page cache now per inode. Other changes to follow. --- lustre/include/linux/obdfs.h | 35 ++++++++------ lustre/obdclass/class_obd.c | 2 +- lustre/obdclass/genops.c | 9 ++-- lustre/obdfs/Makefile | 2 +- lustre/obdfs/flushd.c | 84 +++++++++++++++++++--------------- lustre/obdfs/namei.c | 3 +- lustre/obdfs/rw.c | 106 ++++++++++++++++++++----------------------- lustre/obdfs/super.c | 12 +++-- 8 files changed, 132 insertions(+), 121 deletions(-) diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index 04c0f5f..cad8f07 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -23,8 +23,8 @@ int flushd_init(void); /* rw.c */ int obdfs_do_writepage(struct inode *, struct page *, int sync); -int obdfs_init_wreqcache(void); -void obdfs_cleanup_wreqcache(void); +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); @@ -49,15 +49,24 @@ int obdfs_check_dir_entry (const char * function, struct inode * dir, int obdfs_readlink (struct dentry *, char *, int); struct dentry *obdfs_follow_link(struct dentry *, struct dentry *, unsigned int); + +struct obdfs_super_info { + struct list_head s_wr_head; +}; + + +/* list of all OBDFS super blocks */ +struct list_head obdfs_super_list; struct obdfs_super_entry { struct list_head sl_chain; - struct obdfs_sb_info *sbi; + struct obdfs_super_info *sl_sbi; }; -struct obdfs_wreq { - struct list_head wb_list; /* linked list of req's */ - struct inode *wb_inode; /* dentry referenced */ - struct page *wb_page; /* page to be written */ +struct obdfs_pgrq { + struct list_head rq_list; /* linked list of req's */ + unsigned long rq_jiffies; + struct inode *rq_inode; /* dentry referenced */ + struct page *rq_page; /* page to be written */ }; struct obdfs_sb_info { @@ -72,18 +81,14 @@ struct obdfs_sb_info { struct obdfs_inode_info { int oi_flags; - struct list_head oi_list; + struct list_head oi_pages; char *oi_inline; }; -#define OBD_INFO(inode) ((struct obdfs_inode_info *)(&(inode)->u.generic_ip)) -/* this was used when the list was in the superblock -#define OBD_LIST(inode) (((struct obdfs_sb_info *)(&(inode)->i_sb->u.generic_sbp))->osi_list) -*/ -#define OBD_LIST(inode) (OBD_INFO(inode)->oi_list) -#define WB_NEXT(req) ((struct obdfs_wreq *) ((req)->wb_list.next)) -#define WREQ(entry) (list_entry(entry, struct obdfs_wreq, wb_list)) +#define OBD_LIST(inode) (((struct obdfs_inode_info *)(&(inode)->u.generic_ip))->oi_pages) +#define WREQ(entry) (list_entry(entry, struct obdfs_pgrq, rq_list)) +#define OBD_INFO(inode) ((struct obdfs_inode_info *)(&(inode)->u.generic_ip)) void obdfs_sysctl_init(void); void obdfs_sysctl_clean(void); diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index 45d2fcf..f32917a 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -95,7 +95,7 @@ static int obd_class_release(struct inode * inode, struct file * file) return -ENODEV; fsync_dev(inode->i_rdev); if (obd_dev[dev].obd_refcnt <= 0) - printk(KERN_ALERT "obd_class_release: refcount(%d) <= 0\n", + printk(KERN_ALERT "presto_psdev_release: refcount(%d) <= 0\n", obd_dev[dev].obd_refcnt); obd_dev[dev].obd_refcnt--; diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index 3f9801b..10a69dc 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -260,20 +260,21 @@ int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst, lck_page(page); while (index < ((src->o_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) { + obd_size count = PAGE_SIZE; page->index = index; rc = OBP(src_conn->oc_dev, brw) (READ, src_conn, src, (char *)page_address(page), - PAGE_SIZE, (page->index) << PAGE_SHIFT, 0); + &count, (page->index) << PAGE_SHIFT, 0); - if ( rc != PAGE_SIZE ) + if ( rc != 0 ) break; CDEBUG(D_INODE, "Read page %ld ...\n", page->index); rc = OBP(dst_conn->oc_dev, brw) (WRITE, dst_conn, dst, (char *)page_address(page), - PAGE_SIZE, (page->index) << PAGE_SHIFT, 1); - if ( rc != PAGE_SIZE) + &count, (page->index) << PAGE_SHIFT, 1); + if ( rc != 0) break; CDEBUG(D_INODE, "Wrote page %ld ...\n", page->index); diff --git a/lustre/obdfs/Makefile b/lustre/obdfs/Makefile index f0a7390..f83021e 100644 --- a/lustre/obdfs/Makefile +++ b/lustre/obdfs/Makefile @@ -5,6 +5,6 @@ include ../config.mk MODULE = obdfs.o -CFILES= file.c dir.c sysctl.c super.c rw.c namei.c symlink.c #flushd.c +CFILES= flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c include ../make.rules diff --git a/lustre/obdfs/flushd.c b/lustre/obdfs/flushd.c index 19c7437..e94b6bf 100644 --- a/lustre/obdfs/flushd.c +++ b/lustre/obdfs/flushd.c @@ -7,25 +7,28 @@ * Copryright (C) 1999 Seagate Technology Inc. * */ -#include +#define __NO_VERSION__ #include -#include -#include -#include -#include -#include +#include +#include +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include #include - -#include -#include -#include -#include -#include -#include +#include +#include +#include #include #include @@ -45,23 +48,24 @@ struct { int interval; /* jiffies delay between kupdate flushes */ int age_buffer; /* Time for normal buffer to age before we flush it */ int age_super; /* Time for superblock to age before we flush it */ -} pupd_prm = {40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ }; - +} pupd_prm = {40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ }; -atatic void obdfs_flush_reqs(struct obdfs_super_info *sbi, int wait, - int check_time) +/* static void obdfs_flush_reqs(struct obdfs_super_info *sbi, int wait, + +*/ +static void obdfs_flush_reqs(struct obdfs_super_info *sbi, int check_time) { struct list_head *wr; - struct pg_req *req; + struct obdfs_pgrq *req; - wr = &si.s_wr_head; - while ( (wr = wr->next) != &si.s_wr_head ) { - req = list_entry(wr, struct pg_req, rq_list); + wr = &sbi->s_wr_head; + while ( (wr = wr->next) != &sbi->s_wr_head ) { + req = list_entry(wr, struct obdfs_pgrq, rq_list); if (!check_time || - req->rq_jiffies <= (jiffies - pup_rpm.age_buffer)) { + req->rq_jiffies <= (jiffies - pupd_prm.age_buffer)) { /* write request out to disk */ - obdfs_write_page(req->inode, req->page); + obdfs_do_writepage(req->rq_inode, req->rq_page, 1); } } @@ -72,33 +76,33 @@ atatic void obdfs_flush_reqs(struct obdfs_super_info *sbi, int wait, static void obdfs_flush_dirty_pages(int check_time) { struct list_head *sl; + struct obdfs_super_info *sbi; sl = &obdfs_super_list; - while ( (sl = sl->next) != &obdfs_super_listhead ) { + while ( (sl = sl->next) != &obdfs_super_list ) { struct obdfs_super_entry *entry = list_entry(sl, struct obdfs_super_entry, sl_chain); - struct obdfs_sb_info *sbi = sl->sl_sbi; + struct obdfs_super_info *sbi = entry->sl_sbi; /* walk write requests here */ - obdfs_flush_reqs(sbi, 0); + obdfs_flush_reqs(sbi, jiffies); } /* again, but now we wait for completion */ - sl = &obdfs_super_listhead; - while ( (sl = sl->next) != &obdfs_super_listhead ) { - struct obdfs_super_list *entry = - list_entry(sl, struct obdfs_super_list, sl_chain); - struct super_block *sb = sl->sl_sb; + sl = &obdfs_super_list; + while ( (sl = sl->next) != &obdfs_super_list ) { + struct obdfs_super_entry *entry = + list_entry(sl, struct obdfs_super_entry, sl_chain); + sbi = entry->sl_sbi; /* walk write requests here */ - si = &sb->u.generic; - obdfs_flush_reqs(si, 1); + obdfs_flush_reqs(sbi, jiffies); } } -static struct task_struct *pupdatd; +static struct task_struct *pupdated; -static int pupdate(void) +static int pupdate(void *unused) { struct task_struct * tsk = current; int interval; @@ -127,6 +131,7 @@ static int pupdate(void) { stop_pupdate: tsk->state = TASK_STOPPED; + MOD_DEC_USE_COUNT; schedule(); /* wait for SIGCONT */ } /* check for sigstop */ @@ -154,6 +159,7 @@ static int pupdate(void) int flushd_init(void) { /* kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); */ + MOD_INC_USE_COUNT; kernel_thread(pupdate, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); return 0; } @@ -169,7 +175,11 @@ int flushd_cleanup(void) if (pupdated) { /* send updated a STOP signal */ /* then let it run at least once, before continuing */ + 1; } + /* not reached */ + return 0; + } diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index 7a811c8..22fdde1 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -485,8 +485,7 @@ struct inode *obdfs_new_inode(struct inode *dir) return ERR_PTR(-EIO); } - INIT_LIST_HEAD(&OBD_LIST(inode)); - + obdo_free(oa); EXIT; return inode; } /* obdfs_new_inode */ diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 3e9825f..f58704b 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -79,35 +79,29 @@ int obdfs_readpage(struct dentry *dentry, struct page *page) return rc; } /* obdfs_readpage */ -static kmem_cache_t *obdfs_wreq_cachep = NULL; +static kmem_cache_t *obdfs_pgrq_cachep; -int obdfs_init_wreqcache(void) +int obdfs_init_pgrqcache(void) { ENTRY; - - if (obdfs_wreq_cachep == NULL) { - obdfs_wreq_cachep = kmem_cache_create("obdfs_wreq", - sizeof(struct obdfs_wreq), - 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (obdfs_wreq_cachep == NULL) { - EXIT; - return -ENOMEM; - } + obdfs_pgrq_cachep = kmem_cache_create("obdfs_pgrq", + sizeof(struct obdfs_pgrq), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (obdfs_pgrq_cachep == NULL) { + EXIT; + return -ENOMEM; } + EXIT; return 0; } /* obdfs_init_wreqcache */ -void obdfs_cleanup_wreqcache(void) +void obdfs_cleanup_pgrqcache(void) { - ENTRY; - if (obdfs_wreq_cachep != NULL) { - if (kmem_cache_shrink(obdfs_wreq_cachep)) - printk(KERN_INFO "obdfs_cleanup_wreqcache: unable to free all of cache\n"); - } else - printk(KERN_ERR "obdfs_cleanup_wreqcache: called with NULL cache pointer\n"); - + if (obdfs_pgrq_cachep != NULL) + kmem_cache_destroy(obdfs_pgrq_cachep); + obdfs_pgrq_cachep = NULL; EXIT; } /* obdfs_cleanup_wreqcache */ @@ -116,28 +110,30 @@ void obdfs_cleanup_wreqcache(void) * Find a specific page in the page cache. If it is found, we return * the write request struct associated with it, if not found return NULL. */ -static struct obdfs_wreq *obdfs_find_in_page_cache(struct inode *inode, - struct page *page) +static struct obdfs_pgrq * +obdfs_find_in_page_cache(struct inode *inode, struct page *page) { - struct list_head *list_head = &OBD_LIST(inode); - struct obdfs_wreq *head, *wreq; + struct list_head *page_list = &OBD_LIST(inode); + struct list_head *tmp; + struct obdfs_pgrq *pgrq; ENTRY; CDEBUG(D_INODE, "looking for inode %ld page %p\n", inode->i_ino, page); - if (list_empty(list_head)) { + if (list_empty(page_list)) { CDEBUG(D_INODE, "empty list\n"); EXIT; return NULL; } - wreq = head = WREQ(list_head->next); - do { - CDEBUG(D_INODE, "checking page %p\n", wreq->wb_page); - if (wreq->wb_page == page) { + tmp = page_list; + while ( (tmp = tmp->next) != page_list ) { + pgrq = list_entry(tmp, struct obdfs_pgrq, rq_list); + CDEBUG(D_INODE, "checking page %p\n", pgrq->rq_page); + if (pgrq->rq_page == page) { CDEBUG(D_INODE, "found page %p in list\n", page); EXIT; - return wreq; + return pgrq; } - } while ((wreq = WB_NEXT(wreq)) != head); + } EXIT; return NULL; @@ -147,23 +143,23 @@ static struct obdfs_wreq *obdfs_find_in_page_cache(struct inode *inode, /* * Remove a writeback request from a list */ -static inline int obdfs_remove_from_page_cache(struct obdfs_wreq *wreq) +static inline int +obdfs_remove_from_page_cache(struct obdfs_pgrq *pgrq) { - struct inode *inode = wreq->wb_inode; - struct page *page = wreq->wb_page; + struct inode *inode = pgrq->rq_inode; + struct page *page = pgrq->rq_page; int rc; ENTRY; - CDEBUG(D_INODE, "removing inode %ld, wreq: %p\n", - inode->i_ino, wreq); - PDEBUG(page, "REM_CACHE"); + CDEBUG(D_INODE, "removing inode %ld page %p, pgrq: %p\n", + inode->i_ino, page, pgrq); rc = obdfs_brw(WRITE, inode, page, 1); /* XXX probably should handle error here somehow. I think that * ext2 also does the same thing - discard write even if error? */ put_page(page); - list_del(&wreq->wb_list); - kmem_cache_free(obdfs_wreq_cachep, wreq); + list_del(&pgrq->rq_list); + kmem_cache_free(obdfs_pgrq_cachep, pgrq); EXIT; return rc; @@ -174,38 +170,36 @@ static inline int obdfs_remove_from_page_cache(struct obdfs_wreq *wreq) */ static int obdfs_add_to_page_cache(struct inode *inode, struct page *page) { - struct obdfs_wreq *wreq; + struct obdfs_pgrq *pgrq; ENTRY; - wreq = kmem_cache_alloc(obdfs_wreq_cachep, SLAB_KERNEL); - CDEBUG(D_INODE, "adding inode %ld page %p, wreq: %p\n", - inode->i_ino, page, wreq); - if (!wreq) { + 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(wreq, 0, sizeof(*wreq)); + memset(pgrq, 0, sizeof(*pgrq)); - wreq->wb_page = page; - wreq->wb_inode = inode; + pgrq->rq_page = page; + pgrq->rq_inode = inode; - get_page(wreq->wb_page); - list_add(&wreq->wb_list, &OBD_LIST(inode)); + get_page(pgrq->rq_page); + list_add(&pgrq->rq_list, &OBD_LIST(inode)); /* For testing purposes, we write out the page here. * In the future, a flush daemon will write out the page. return 0; */ - printk(KERN_INFO "finding page in cache for write\n"); - wreq = obdfs_find_in_page_cache(inode, page); - if (!wreq) { + pgrq = obdfs_find_in_page_cache(inode, page); + if (!pgrq) { CDEBUG(D_INODE, "XXXX Can't find page after adding it!!!\n"); EXIT; return -EINVAL; - } - - EXIT; - return obdfs_remove_from_page_cache(wreq); + } + + return obdfs_remove_from_page_cache(pgrq); } /* obdfs_add_to_page_cache */ diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index f417d77..daaf8cb 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -326,6 +326,7 @@ void obdfs_read_inode(struct inode *inode) { struct obdo *oa; int err; + struct obdfs_inode_info *ii; ENTRY; oa = obdo_alloc(); @@ -336,6 +337,10 @@ void obdfs_read_inode(struct inode *inode) } oa->o_valid = ~OBD_MD_FLOBDMD; oa->o_id = inode->i_ino; + ii = (struct obdfs_inode_info *)(&inode->u.generic_ip); + INIT_LIST_HEAD(&ii->oi_pages); + + err = IOPS(inode, getattr)(IID(inode), oa); if (err) { printk("obdfs_read_inode: obd_getattr fails (%d)\n", err); @@ -473,14 +478,11 @@ int init_obdfs(void) obdfs_sysctl_init(); INIT_LIST_HEAD(&obdfs_super_list); - err = obdfs_init_wreqcache(); + err = obdfs_init_pgrqcache(); if (err) return err; - /* XXX flushd_init(); - */ - return register_filesystem(&obdfs_fs_type); } @@ -495,8 +497,8 @@ void cleanup_module(void) { ENTRY; - obdfs_cleanup_wreqcache(); obdfs_sysctl_clean(); + obdfs_cleanup_pgrqcache(); unregister_filesystem(&obdfs_fs_type); EXIT; -- 1.8.3.1