From 5ffc9e67fce81ae1b946244565b74f98e2f9c786 Mon Sep 17 00:00:00 2001 From: adilger Date: Wed, 29 Dec 1999 21:03:12 +0000 Subject: [PATCH] obdsync/*: added to CVS obdfs/super.c,rw.c: added start of page cache --- lustre/include/linux/obdfs.h | 14 +++++ lustre/obdfs/rw.c | 140 +++++++++++++++++++++++++++++++++++++++---- lustre/obdfs/super.c | 8 ++- 3 files changed, 149 insertions(+), 13 deletions(-) diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index 78ca2ae..d15844f 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -12,12 +12,14 @@ #ifndef _OBDFS_H #define OBDFS_H #include +#include /* super.c */ void obdfs_read_inode(struct inode *inode); /* rw.c */ +int obdfs_init_wreqcache(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); @@ -42,6 +44,12 @@ 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_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_sb_info { struct obd_conn osi_conn; struct super_block *osi_super; @@ -49,8 +57,14 @@ struct obdfs_sb_info { struct obd_ops *osi_ops; ino_t osi_rootino; /* which root inode */ int osi_minor; /* minor of /dev/obdX */ + struct list_head osi_list; /* linked list of pages to write */ }; +#define WB_NEXT(req) ((struct obdfs_wreq *) ((req)->wb_list.next)) +/* XXX page list should go on each inode instead of supberblock */ +#define OBD_LIST(inode) (((struct obdfs_sb_info *)(&(inode)->i_sb->u.generic_sbp))->osi_list) +#define WREQ(entry) (list_entry(entry, struct obdfs_wreq, wb_list)) + void obdfs_sysctl_init(void); void obdfs_sysctl_clean(void); diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 2be005b..16168f9 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -43,27 +43,143 @@ int obdfs_brw(struct inode *dir, int rw, struct page *page, int create) } #endif +static kmem_cache_t *obdfs_wreq_cachep; + +int obdfs_init_wreqcache(void) +{ + /* XXX need to free this somewhere? */ + ENTRY; + 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; + } + EXIT; + return 0; +} + +/* + * 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) +{ + struct list_head *list_head = &OBD_LIST(inode); + struct obdfs_wreq *head, *wreq; + + ENTRY; + CDEBUG(D_INODE, "looking for inode %ld page %p\n", inode->i_ino, page); + if (list_empty(list_head)) { + 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) { + CDEBUG(D_INODE, "found page %p in list\n", page); + EXIT; + return wreq; + } + } while ((wreq = WB_NEXT(wreq)) != head); + + EXIT; + return NULL; +} + /* returns the page unlocked, but with a reference */ int obdfs_readpage(struct dentry *dentry, struct page *page) { struct inode *inode = dentry->d_inode; - int rc; + struct obdfs_wreq *wreq; + int rc = 0; ENTRY; /* XXX flush stuff */ - PDEBUG(page, "READ"); - rc = iops(inode)->o_brw(READ, iid(inode),inode, page, 0); - if (rc == PAGE_SIZE ) { - SetPageUptodate(page); - UnlockPage(page); + wreq = obdfs_find_in_page_cache(inode, page); + if (!wreq) { + PDEBUG(page, "READ"); + rc = iops(inode)->o_brw(READ, iid(inode),inode, page, 0); + if (rc == PAGE_SIZE ) { + SetPageUptodate(page); + UnlockPage(page); + } + PDEBUG(page, "READ"); + if ( rc == PAGE_SIZE ) + rc = 0; } - PDEBUG(page, "READ"); - if ( rc == PAGE_SIZE ) - rc = 0; + EXIT; + return rc; +} + +/* + * Remove a writeback request from a list + */ +static inline int +obdfs_remove_from_page_cache(struct obdfs_wreq *wreq) +{ + struct inode *inode = wreq->wb_inode; + struct page *page = wreq->wb_page; + int rc; + + ENTRY; + CDEBUG(D_INODE, "removing inode %ld page %p, wreq: %p\n", + inode->i_ino, page, wreq); + rc = iops(inode)->o_brw(WRITE, iid(inode), 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); + + EXIT; return rc; +} + +/* + * Add a page to the write request cache list for later writing + */ +static int +obdfs_add_to_page_cache(struct inode *inode, struct page *page) +{ + struct obdfs_wreq *wreq; + + 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) { + EXIT; + return -ENOMEM; + } + memset(wreq, 0, sizeof(*wreq)); + + wreq->wb_page = page; + wreq->wb_inode = inode; + get_page(wreq->wb_page); + list_add(&wreq->wb_list, &OBD_LIST(inode)); + + /* For testing purposes, we write out the page here. + * In the future, a flush daemon will write out the page. + */ + wreq = obdfs_find_in_page_cache(inode, page); + if (!wreq) { + CDEBUG(D_INODE, "XXXX Can't find page after adding it!!!\n"); + return -EINVAL; + } else + return obdfs_remove_from_page_cache(wreq); + + return 0; } + /* returns the page unlocked, but with a reference */ int obdfs_writepage(struct dentry *dentry, struct page *page) { @@ -73,10 +189,10 @@ int obdfs_writepage(struct dentry *dentry, struct page *page) ENTRY; PDEBUG(page, "WRITEPAGE"); /* XXX flush stuff */ + rc = obdfs_add_to_page_cache(inode, page); - rc = iops(inode)->o_brw(WRITE, iid(inode), inode, page, 1); - - SetPageUptodate(page); + if (!rc) + SetPageUptodate(page); PDEBUG(page,"WRITEPAGE"); return rc; } diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index 0df6a03..498e2f4 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -192,7 +192,7 @@ static struct super_block * obdfs_read_super(struct super_block *sb, goto error; } - + INIT_LIST_HEAD(&sbi->osi_list); sbi->osi_super = sb; @@ -388,10 +388,16 @@ struct file_system_type obdfs_fs_type = { int init_obdfs(void) { + int err; + printk(KERN_INFO "OBDFS v0.1, braam@stelias.com\n"); obdfs_sysctl_init(); + err = obdfs_init_wreqcache(); + if (err) + return err; + return register_filesystem(&obdfs_fs_type); } -- 1.8.3.1