/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Lustre Lite I/O page cache for the 2.4 kernel version * * Copyright (c) 2001-2003 Cluster File Systems, Inc. * * This file is part of Lustre, http://www.lustre.org. * * Lustre is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * Lustre is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Lustre; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEBUG_SUBSYSTEM S_LLITE #include #include #include "llite_internal.h" #include static int ll_writepage_24(struct page *page) { struct inode *inode = page->mapping->host; struct obd_export *exp; struct ll_async_page *llap; int rc = 0; ENTRY; LASSERT(!PageDirty(page)); LASSERT(PageLocked(page)); exp = ll_i2obdexp(inode); if (exp == NULL) GOTO(out, rc = -EINVAL); llap = llap_from_page(page); if (IS_ERR(llap)) GOTO(out, rc = PTR_ERR(llap)); page_cache_get(page); if (llap->llap_write_queued) { LL_CDEBUG_PAGE(D_PAGE, page, "marking urgent\n"); rc = obd_set_async_flags(exp, ll_i2info(inode)->lli_smd, NULL, llap->llap_cookie, ASYNC_READY | ASYNC_URGENT); } else { llap->llap_write_queued = 1; rc = obd_queue_async_io(exp, ll_i2info(inode)->lli_smd, NULL, llap->llap_cookie, OBD_BRW_WRITE, 0, 0, 0, ASYNC_READY | ASYNC_URGENT); if (rc == 0) LL_CDEBUG_PAGE(D_PAGE, page, "mmap write queued\n"); else llap->llap_write_queued = 0; } if (rc) page_cache_release(page); out: if (rc) unlock_page(page); RETURN(rc); } static int ll_direct_IO_24(int rw, #ifdef HAVE_DIO_FILE struct file *file, #else struct inode *inode, #endif struct kiobuf *iobuf, unsigned long blocknr, int blocksize) { #ifdef HAVE_DIO_FILE struct inode *inode = file->f_dentry->d_inode; #endif struct ll_inode_info *lli = ll_i2info(inode); struct lov_stripe_md *lsm = lli->lli_smd; struct brw_page *pga; struct ptlrpc_request_set *set; struct obdo oa; int length, i, flags, rc = 0; loff_t offset; ENTRY; if (!lsm || !lsm->lsm_object_id) RETURN(-EBADF); /* FIXME: io smaller than PAGE_SIZE is broken on ia64 */ if ((iobuf->offset & (PAGE_SIZE - 1)) || (iobuf->length & (PAGE_SIZE - 1))) RETURN(-EINVAL); set = ptlrpc_prep_set(); if (set == NULL) RETURN(-ENOMEM); OBD_ALLOC(pga, sizeof(*pga) * iobuf->nr_pages); if (!pga) { ptlrpc_set_destroy(set); RETURN(-ENOMEM); } flags = 0 /* | OBD_BRW_DIRECTIO */; offset = ((obd_off)blocknr << inode->i_blkbits); length = iobuf->length; for (i = 0, length = iobuf->length; length > 0; length -= pga[i].count, offset += pga[i].count, i++) { /*i last!*/ pga[i].pg = iobuf->maplist[i]; pga[i].off = offset; /* To the end of the page, or the length, whatever is less */ pga[i].count = min_t(int, PAGE_SIZE - (offset & ~PAGE_MASK), length); pga[i].flag = flags; if (rw == READ) POISON_PAGE(iobuf->maplist[i], 0x0d); } ll_inode_fill_obdo(inode, rw, &oa); if (rw == WRITE) lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, LPROC_LL_DIRECT_WRITE, iobuf->length); else lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, LPROC_LL_DIRECT_READ, iobuf->length); rc = obd_brw_async(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ, ll_i2obdexp(inode), &oa, lsm, iobuf->nr_pages, pga, set, NULL); if (rc) { CDEBUG(rc == -ENOSPC ? D_INODE : D_ERROR, "error from obd_brw_async: rc = %d\n", rc); } else { rc = ptlrpc_set_wait(set); if (rc) CERROR("error from callback: rc = %d\n", rc); } ptlrpc_set_destroy(set); if (rc == 0) { rc = iobuf->length; obdo_to_inode(inode, &oa, OBD_MD_FLBLOCKS); } OBD_FREE(pga, sizeof(*pga) * iobuf->nr_pages); RETURN(rc); } struct address_space_operations ll_aops = { readpage: ll_readpage, direct_IO: ll_direct_IO_24, writepage: ll_writepage_24, prepare_write: ll_prepare_write, commit_write: ll_commit_write, removepage: ll_removepage, sync_page: NULL, bmap: NULL };