}
up(&exp->exp_obd->u.filter.fo_alloc_lock);
+ filter_tally_write(&obd->u.filter, iobuf->maplist, iobuf->nr_pages,
+ iobuf->blocks, blocks_per_page);
+
if (attr->ia_size > inode->i_size)
attr->ia_valid |= ATTR_SIZE;
rc = fsfilt_setattr(obd, dchild, oti->oti_handle, attr, 0);
check_pending_bhs(iobuf->blocks, iobuf->nr_pages, inode->i_dev,
1 << inode->i_blkbits);
+ rc = filemap_fdatasync(inode->i_mapping);
+ if (rc == 0)
+ rc = fsync_inode_data_buffers(inode);
+ if (rc == 0)
+ rc = filemap_fdatawait(inode->i_mapping);
+ if (rc < 0)
+ GOTO(cleanup, rc);
+
rc = brw_kiovec(WRITE, 1, &iobuf, inode->i_dev, iobuf->blocks,
1 << inode->i_blkbits);
CDEBUG(D_INFO, "tried to write %d pages, rc = %d\n",
return rc;
}
+/* See if there are unallocated parts in given file region */
+static int filter_range_is_mapped(struct inode *inode, obd_size offset, int len)
+{
+ int (*fs_bmap)(struct address_space *, long) =
+ inode->i_mapping->a_ops->bmap;
+ int j;
+
+ /* We can't know if the range is mapped already 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 iattr iattr = { 0 };
struct kiobuf *iobuf;
struct inode *inode = NULL;
- int rc = 0, i, cleanup_phase = 0, err;
+ int rc = 0, i, n, cleanup_phase = 0, err;
unsigned long now = jiffies; /* DEBUGGING OST TIMEOUTS */
void *wait_handle;
ENTRY;
GOTO(cleanup, rc);
iobuf->offset = 0;
- iobuf->length = PAGE_SIZE * obj->ioo_bufcnt;
- iobuf->nr_pages = obj->ioo_bufcnt;
+ iobuf->length = 0;
+ iobuf->nr_pages = 0;
cleanup_phase = 1;
fso.fso_dentry = res->dentry;
fso.fso_bufcnt = obj->ioo_bufcnt;
inode = res->dentry->d_inode;
- 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++) {
+ for (i = 0, lnb = res, n = 0; i < obj->ioo_bufcnt; i++, lnb++) {
loff_t this_size;
- iobuf->maplist[i] = lnb->page;
+
+ /* 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;
+
+ if (lnb->rc) /* ENOSPC, network RPC error */
+ continue;
+
+ iobuf->maplist[n++] = lnb->page;
+ iobuf->length += PAGE_SIZE;
+ iobuf->nr_pages++;
+
/* We expect these pages to be in offset order, but we'll
* be forgiving */
this_size = lnb->offset + lnb->len;
cleanup_phase = 2;
down(&inode->i_sem);
- 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);
rc = filter_direct_io(OBD_BRW_WRITE, res->dentry, iobuf, exp, &iattr,
oti, &wait_handle);
if (rc == 0)
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);