X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdfilter%2Ffilter_io_26.c;h=95f826348ef1f5733296e06550316c58dfd18744;hb=853090097d24525d2262d281801516c8985e43c8;hp=e5ee2456fc6ef5d7ca4556f01c34fbdaaf48502a;hpb=fc45b584cce84c67c14d374a9357a9781f5ff92e;p=fs%2Flustre-release.git diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c index e5ee245..95f8263 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -95,33 +95,42 @@ static int filter_range_is_mapped(struct inode *inode, obd_size offset, int len) 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) +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, + int rc) { - struct obd_device *obd = exp->exp_obd; - struct obd_run_ctxt saved; + struct bio *bio = NULL; + int blocks_per_page, err; struct niobuf_local *lnb; + struct lvfs_run_ctxt saved; struct fsfilt_objinfo fso; - struct iattr iattr = { .ia_valid = ATTR_SIZE, .ia_size = 0, }; + struct iattr iattr = { 0 }; struct inode *inode = NULL; - int rc = 0, i, k, cleanup_phase = 0, err; - unsigned long now = jiffies; /* DEBUGGING OST TIMEOUTS */ - int blocks_per_page; - struct dio_request *dreq; - struct bio *bio = NULL; + unsigned long now = jiffies; + int i, k, cleanup_phase = 0; + + struct dio_request *dreq = NULL; + struct obd_device *obd = exp->exp_obd; + ENTRY; + LASSERT(oti != NULL); 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); OBD_ALLOC(dreq, sizeof(*dreq)); + if (dreq == NULL) RETURN(-ENOMEM); + dreq->bio_list = NULL; init_waitqueue_head(&dreq->wait); atomic_set(&dreq->numreqs, 0); @@ -131,10 +140,14 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, fso.fso_dentry = res->dentry; fso.fso_bufcnt = obj->ioo_bufcnt; - push_ctxt(&saved, &obd->obd_ctxt, NULL); + push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); cleanup_phase = 2; - oti->oti_handle = fsfilt_brw_start(obd, objcount, &fso, niocount, res, oti); + generic_osync_inode(inode, inode->i_mapping, OSYNC_DATA|OSYNC_METADATA); + + 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, @@ -150,6 +163,7 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, for (i = 0, lnb = res; i < obj->ioo_bufcnt; i++, lnb++) { loff_t this_size; sector_t sector; + struct page *pages[1]; int offs; /* If overwriting an existing block, we don't need a grant */ @@ -157,13 +171,15 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, filter_range_is_mapped(inode, lnb->offset, lnb->len)) lnb->rc = 0; - if (lnb->rc) /* ENOSPC, network RPC error */ + if (lnb->rc) /* ENOSPC, network RPC error, etc. */ continue; /* get block number for next page */ - rc = fsfilt_map_inode_page(obd, inode, lnb->page, dreq->blocks, - dreq->created, 1); - if (rc) + pages[0] = lnb->page; + rc = fsfilt_map_inode_pages(obd, inode, pages, 1, + dreq->blocks, dreq->created, 1, + NULL); + if (rc != 0) GOTO(cleanup, rc); for (k = 0; k < blocks_per_page; k++) { @@ -171,7 +187,7 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, offs = k * inode->i_sb->s_blocksize; if (!bio || !can_be_merged(bio, sector) || - !bio_add_page(bio, lnb->page, lnb->len, offs)) { + !bio_add_page(bio, lnb->page, PAGE_SIZE, offs)) { if (bio) { atomic_inc(&dreq->numreqs); submit_bio(WRITE, bio); @@ -184,26 +200,24 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, bio->bi_end_io = dio_complete_routine; bio->bi_private = dreq; - if (!bio_add_page(bio, lnb->page, lnb->len, 0)) + if (!bio_add_page(bio, lnb->page, PAGE_SIZE, + offs)) LBUG(); } } - /* We expect these pages to be in offset order, but we'll + /* we expect these pages to be in offset order, but we'll * be forgiving */ this_size = lnb->offset + lnb->len; if (this_size > iattr.ia_size) iattr.ia_size = this_size; } -#warning This probably needs filemap_fdatasync() like filter_io_24 (bug 2366) if (bio) { atomic_inc(&dreq->numreqs); - submit_bio(WRITE, bio); + fsfilt_send_bio(obd, inode, bio); } - filter_grant_commit(exp, niocount, res); - /* time to wait for I/O completion */ wait_event(dreq->wait, atomic_read(&dreq->numreqs) == 0); @@ -214,44 +228,49 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, bio_put(bio); } - if (rc == 0) { - down(&inode->i_sem); - if (iattr.ia_size > inode->i_size) { - CDEBUG(D_INFO, "setting i_size to "LPU64"\n", - iattr.ia_size); - fsfilt_setattr(obd, res->dentry, oti->oti_handle, - &iattr, 0); - } - up(&inode->i_sem); + down(&inode->i_sem); + if (iattr.ia_size > inode->i_size) { + CDEBUG(D_INFO, "setting i_size to "LPU64"\n", + iattr.ia_size); + + iattr.ia_valid |= ATTR_SIZE; + + fsfilt_setattr(obd, res->dentry, oti->oti_handle, + &iattr, 0); } + up(&inode->i_sem); if (time_after(jiffies, now + 15 * HZ)) CERROR("slow direct_io %lus\n", (jiffies - now) / HZ); rc = filter_finish_transno(exp, oti, rc); + err = fsfilt_commit(obd, inode, oti->oti_handle, obd_sync_filter); if (err) rc = err; + if (obd_sync_filter) LASSERT(oti->oti_transno <= obd->obd_last_committed); + if (time_after(jiffies, now + 15 * HZ)) 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); + pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); LASSERT(current->journal_info == NULL); case 1: OBD_FREE(dreq, sizeof(*dreq)); case 0: for (i = 0, lnb = res; i < obj->ioo_bufcnt; i++, lnb++) { - /* flip_.. gets a ref, while free_page only frees - * when it decrefs to 0 */ - if (rc == 0) - flip_into_page_cache(inode, lnb->page); - __free_page(lnb->page); + filter_release_write_page(&obd->u.filter, + res->dentry->d_inode, lnb, + rc); } + f_dput(res->dentry); }