X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdfs%2Frw.c;h=558cfedf6ee3661592171e7558e065154fc62c60;hb=86ada49822948e9cf3a8488b3297f111bcaef72e;hp=2be005b04570dcbf9d471ff6b71f662302235432;hpb=8688197f18b85befc95d8bb812c71cc6bec47284;p=fs%2Flustre-release.git diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 2be005b..558cfed 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -47,10 +47,10 @@ int obdfs_brw(struct inode *dir, int rw, struct page *page, int create) 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 ) { @@ -60,10 +60,124 @@ int obdfs_readpage(struct dentry *dentry, struct page *page) PDEBUG(page, "READ"); if ( rc == PAGE_SIZE ) rc = 0; + } + EXIT; return rc; +} + +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; } + +/* + * 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 +187,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; }