X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdfilter%2Ffilter_io_26.c;h=5ce65c7b31130be4c60fa5c1c3d3b82393b0a99d;hb=090c677210ee2946d99c71412e4ff762bb300f4f;hp=cc0007fce4fa76f725fbcc2639dc16cc7cb516b3;hpb=c5050e412572b00cbe93d8517d2d1f767bebfa92;p=fs%2Flustre-release.git diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c index cc0007f..5ce65c7 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -37,17 +37,14 @@ #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; }; @@ -68,18 +65,40 @@ static int dio_complete_routine(struct bio *bio, unsigned int done, int error) 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; @@ -87,9 +106,9 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, 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; @@ -97,9 +116,12 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, 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) @@ -114,9 +136,9 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, 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, @@ -128,39 +150,48 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, 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 */ @@ -168,12 +199,14 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, 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 */ @@ -185,7 +218,6 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, 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); @@ -208,6 +240,8 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, 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);