#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 */
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;
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)
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;
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;