From f6b72baccee02e6a7aa506b55d6e693f3e3062ff Mon Sep 17 00:00:00 2001 From: adilger Date: Mon, 15 Apr 2002 19:51:09 +0000 Subject: [PATCH] Optimize write-full-page so that we don't read in a page full of data we are not going to use. This should speed up the rewrite tests in iozone. Split the lustre_get_page() into two functions - lustre_get_page_read() and lustre_get_page_write(). The first one reads in the page, and the second one just gets the page locked but without any data. --- lustre/include/linux/lustre_lib.h | 4 ++-- lustre/lib/page.c | 43 +++++++++++++++++++++++++++------------ lustre/obdfilter/filter.c | 12 +++++------ 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/lustre/include/linux/lustre_lib.h b/lustre/include/linux/lustre_lib.h index 0a03f2b..6b109e8 100644 --- a/lustre/include/linux/lustre_lib.h +++ b/lustre/include/linux/lustre_lib.h @@ -34,8 +34,8 @@ #ifdef __KERNEL__ /* page.c */ inline void lustre_put_page(struct page *page); -struct page * lustre_get_page(struct inode *dir, unsigned long n); -int lustre_prepare_page(unsigned from, unsigned to, struct page *page); +struct page *lustre_get_page_read(struct inode *dir, unsigned long index); +struct page *lustre_get_page_write(struct inode *dir, unsigned long index); int lustre_commit_page(struct page *page, unsigned from, unsigned to); /* simple.c */ diff --git a/lustre/lib/page.c b/lustre/lib/page.c index 1b1b995..0e401d8 100644 --- a/lustre/lib/page.c +++ b/lustre/lib/page.c @@ -91,18 +91,19 @@ inline void lustre_put_page(struct page *page) page_cache_release(page); } -struct page * lustre_get_page(struct inode *inode, unsigned long n) +struct page *lustre_get_page_read(struct inode *inode, unsigned long index) { struct address_space *mapping = inode->i_mapping; - struct page *page = read_cache_page(mapping, n, + struct page *page = read_cache_page(mapping, index, (filler_t*)mapping->a_ops->readpage, NULL); + if (!IS_ERR(page)) { wait_on_page(page); kmap(page); if (!Page_Uptodate(page)) - goto fail; + GOTO(fail, -EIO); if (PageError(page)) - goto fail; + GOTO(fail, -EIO); } return page; @@ -111,19 +112,35 @@ fail: return ERR_PTR(-EIO); } -int lustre_prepare_page(unsigned from, unsigned to, struct page *page) +struct page *lustre_get_page_write(struct inode *inode, unsigned long index) { + struct address_space *mapping = inode->i_mapping; + struct page *page = grab_cache_page(mapping, index); /* locked page */ int err; - lock_page(page); - err = page->mapping->a_ops->prepare_write(NULL, page, from, to); - if (err) { - UnlockPage(page); - CERROR("page index %ld from %d to %d err %d\n", - page->index, from, to, err); - LBUG(); + if (!IS_ERR(page)) { + kmap(page); + + /* Note: Called with "O" and "PAGE_SIZE" this is essentially + * a no-op for most filesystems, because we write the whole + * page. For partial-page I/O this will read in the page. + */ + err = mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE); + if (err) { + CERROR("page index %ld, err %d\n", index, err); + LBUG(); + GOTO(fail, err); + } + /* XXX not sure if we need this if we are overwriting page */ + if (PageError(page)) + GOTO(fail, err = -EIO); } - return err; + return page; + +fail: + UnlockPage(page); + lustre_put_page(page); + return ERR_PTR(-EIO); } int lustre_commit_page(struct page *page, unsigned from, unsigned to) diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index ec8c0cb..104e4da 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -782,6 +782,7 @@ static int filter_preprw(int cmd, struct obd_conn *conn, for (i = 0; i < objcount; i++, o++) { int j; for (j = 0; j < o->ioo_bufcnt; j++, b++, r++) { + unsigned long index = b->offset >> PAGE_SHIFT; struct inode *inode = ioobj_to_inode(conn, o); struct page *page; @@ -789,16 +790,13 @@ static int filter_preprw(int cmd, struct obd_conn *conn, if (!inode) RETURN(-EINVAL); - page = lustre_get_page(inode, b->offset >> PAGE_SHIFT); + if (cmd == OBD_BRW_WRITE) + page = lustre_get_page_write(inode, index); + else + page = lustre_get_page_read(inode, index); if (IS_ERR(page)) RETURN(PTR_ERR(page)); - if (cmd == OBD_BRW_WRITE) { - int rc = lustre_prepare_page(0, PAGE_SIZE,page); - if (rc) - CERROR("i %d j %d objcount %d bufcnt %d , rc %d, offset %Ld\n", i, j, objcount, o->ioo_bufcnt, rc, b->offset); - } - r->addr = (__u64)(unsigned long)page_address(page); r->offset = b->offset; r->page = page; -- 1.8.3.1