#warning "implement writeback mode -bzzz"
-int ext3_map_inode_page(struct inode *inode, struct page *page,
- unsigned long *blocks, int *created, int create);
-
/* 512byte block min */
#define MAX_BLOCKS_PER_PAGE (PAGE_SIZE / 512)
struct dio_request {
atomic_t numreqs; /* number of reqs being processed */
struct bio *bio_list; /* list of completed bios */
wait_queue_head_t wait;
- int created[MAX_BLOCKS_PER_PAGE];
- unsigned long blocks[MAX_BLOCKS_PER_PAGE];
+ int created[MAX_BLOCKS_PER_PAGE];
+ unsigned long blocks[MAX_BLOCKS_PER_PAGE];
spinlock_t lock;
};
static int can_be_merged(struct bio *bio, sector_t sector)
{
- int size;
-
- if (!bio)
- return 0;
-
- size = bio->bi_size >> 9;
- return bio->bi_sector + size == sector ? 1 : 0;
+ int size;
+
+ if (!bio)
+ return 0;
+
+ size = bio->bi_size >> 9;
+ return bio->bi_sector + size == sector ? 1 : 0;
+}
+
+/* See if there are unallocated parts in given file region */
+static int filter_range_is_mapped(struct inode *inode, obd_size offset, int len)
+{
+ sector_t (*fs_bmap)(struct address_space *, sector_t) =
+ inode->i_mapping->a_ops->bmap;
+ int j;
+
+ /* We can't know if we are overwriting or not */
+ if (fs_bmap == NULL)
+ return 0;
+
+ offset >>= inode->i_blkbits;
+ len >>= inode->i_blkbits;
+
+ for (j = 0; j <= len; j++)
+ if (fs_bmap(inode->i_mapping, offset + j) == 0)
+ return 0;
+
+ return 1;
}
int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount,
struct obd_ioobj *obj, int niocount,
- struct niobuf_local *res, struct obd_trans_info *oti)
+ struct niobuf_local *res, struct obd_trans_info *oti,
+ int rc)
{
struct obd_device *obd = exp->exp_obd;
struct obd_run_ctxt saved;
struct fsfilt_objinfo fso;
struct iattr iattr = { .ia_valid = ATTR_SIZE, .ia_size = 0, };
struct inode *inode = NULL;
- int rc = 0, i, k, cleanup_phase = 0, err;
+ int i, k, cleanup_phase = 0, err;
unsigned long now = jiffies; /* DEBUGGING OST TIMEOUTS */
- int blocks_per_page;
+ int blocks_per_page;
struct dio_request *dreq;
struct bio *bio = NULL;
ENTRY;
LASSERT(objcount == 1);
LASSERT(current->journal_info == NULL);
+ if (rc != 0)
+ GOTO(cleanup, rc);
+
inode = res->dentry->d_inode;
blocks_per_page = PAGE_SIZE >> inode->i_blkbits;
- LASSERT(blocks_per_page <= MAX_BLOCKS_PER_PAGE);
+ LASSERT(blocks_per_page <= MAX_BLOCKS_PER_PAGE);
OBD_ALLOC(dreq, sizeof(*dreq));
if (dreq == NULL)
fso.fso_bufcnt = obj->ioo_bufcnt;
push_ctxt(&saved, &obd->obd_ctxt, NULL);
- cleanup_phase = 2;
+ cleanup_phase = 2;
- oti->oti_handle = fsfilt_brw_start(obd, objcount, &fso, niocount, oti);
+ oti->oti_handle = fsfilt_brw_start(obd, objcount, &fso, niocount, res, oti);
if (IS_ERR(oti->oti_handle)) {
rc = PTR_ERR(oti->oti_handle);
CDEBUG(rc == -ENOSPC ? D_INODE : D_ERROR,
if (time_after(jiffies, now + 15 * HZ))
CERROR("slow brw_start %lus\n", (jiffies - now) / HZ);
+ iattr_from_obdo(&iattr,oa,OBD_MD_FLATIME|OBD_MD_FLMTIME|OBD_MD_FLCTIME);
for (i = 0, lnb = res; i < obj->ioo_bufcnt; i++, lnb++) {
loff_t this_size;
- sector_t sector;
- int offs;
+ sector_t sector;
+ int offs;
+
+ /* If overwriting an existing block, we don't need a grant */
+ if (!(lnb->flags & OBD_BRW_GRANTED) && lnb->rc == -ENOSPC &&
+ filter_range_is_mapped(inode, lnb->offset, lnb->len))
+ lnb->rc = 0;
- /* get block number for next page */
- rc = ext3_map_inode_page(inode, lnb->page, dreq->blocks,
- dreq->created, 1);
+ if (lnb->rc) /* ENOSPC, network RPC error */
+ continue;
+
+ /* get block number for next page */
+ rc = fsfilt_map_inode_page(obd, inode, lnb->page, dreq->blocks,
+ dreq->created, 1);
if (rc)
GOTO(cleanup, rc);
- for (k = 0; k < blocks_per_page; k++) {
- sector = dreq->blocks[k] * (inode->i_sb->s_blocksize >> 9);
- offs = k * inode->i_sb->s_blocksize;
+ for (k = 0; k < blocks_per_page; k++) {
+ sector = dreq->blocks[k] *(inode->i_sb->s_blocksize>>9);
+ offs = k * inode->i_sb->s_blocksize;
- if (!bio || !can_be_merged(bio, sector) ||
- !bio_add_page(bio, lnb->page, lnb->len, offs)) {
- if (bio) {
+ if (!bio || !can_be_merged(bio, sector) ||
+ !bio_add_page(bio, lnb->page, lnb->len, offs)) {
+ if (bio) {
atomic_inc(&dreq->numreqs);
- submit_bio(WRITE, bio);
- bio = NULL;
- }
- /* allocate new bio */
- bio = bio_alloc(GFP_NOIO, obj->ioo_bufcnt);
- bio->bi_bdev = inode->i_sb->s_bdev;
- bio->bi_sector = sector;
- bio->bi_end_io = dio_complete_routine;
+ submit_bio(WRITE, bio);
+ bio = NULL;
+ }
+ /* allocate new bio */
+ bio = bio_alloc(GFP_NOIO, obj->ioo_bufcnt);
+ bio->bi_bdev = inode->i_sb->s_bdev;
+ bio->bi_sector = sector;
+ bio->bi_end_io = dio_complete_routine;
bio->bi_private = dreq;
- if (!bio_add_page(bio, lnb->page, lnb->len, 0))
- LBUG();
- }
- }
+ if (!bio_add_page(bio, lnb->page, lnb->len, 0))
+ LBUG();
+ }
+ }
/* We expect these pages to be in offset order, but we'll
* be forgiving */
if (this_size > iattr.ia_size)
iattr.ia_size = this_size;
}
- if (bio) {
+
+#warning This probably needs filemap_fdatasync() like filter_io_24 (bug 2366)
+ if (bio) {
atomic_inc(&dreq->numreqs);
submit_bio(WRITE, bio);
}
- /* time to wait for I/O completion */
+ /* time to wait for I/O completion */
wait_event(dreq->wait, atomic_read(&dreq->numreqs) == 0);
/* free all bios */
if (rc == 0) {
down(&inode->i_sem);
- inode_update_time(inode, 1);
if (iattr.ia_size > inode->i_size) {
CDEBUG(D_INFO, "setting i_size to "LPU64"\n",
iattr.ia_size);
CERROR("slow commitrw commit %lus\n", (jiffies - now) / HZ);
cleanup:
+ filter_grant_commit(exp, niocount, res);
+
switch (cleanup_phase) {
case 2:
pop_ctxt(&saved, &obd->obd_ctxt, NULL);