+int filter_do_cow(struct obd_export *exp, struct obd_ioobj *obj,
+ int nioo, struct niobuf_remote *rnb)
+{
+ struct dentry *dentry;
+ struct lvfs_run_ctxt saved;
+ struct write_extents *extents = NULL;
+ int j, rc = 0, numexts = 0, flags = 0;
+
+ ENTRY;
+
+ LASSERT(nioo == 1);
+
+ push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
+
+ dentry = filter_id2dentry(exp->exp_obd, NULL, obj->ioo_gr,
+ obj->ioo_id);
+ if (IS_ERR(dentry)) {
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
+ RETURN (PTR_ERR(dentry));
+ }
+
+ if (dentry->d_inode == NULL) {
+ CERROR("trying to write extents to non-existent file "LPU64"\n",
+ obj->ioo_id);
+ GOTO(cleanup, rc = -ENOENT);
+ }
+
+ flags = fsfilt_get_fs_flags(exp->exp_obd, dentry);
+ if (!(flags & SM_DO_COW))
+ GOTO(cleanup, rc);
+
+ OBD_ALLOC(extents, obj->ioo_bufcnt * sizeof(struct write_extents));
+ if (!extents) {
+ CERROR("No Memory\n");
+ GOTO(cleanup, rc = -ENOMEM);
+ }
+ for (j = 0; j < obj->ioo_bufcnt; j++) {
+ if (rnb[j].len != 0) {
+ extents[numexts].w_count = rnb[j].len;
+ extents[numexts].w_pos = rnb[j].offset;
+ numexts++;
+ }
+ }
+ rc = fsfilt_do_write_cow(exp->exp_obd, dentry, extents, numexts);
+ if (rc) {
+ CERROR("Do cow error id "LPU64" rc:%d \n",
+ obj->ioo_id, rc);
+ GOTO(cleanup, rc);
+ }
+
+cleanup:
+ if (extents) {
+ OBD_FREE(extents, obj->ioo_bufcnt * sizeof(struct write_extents));
+ }
+ f_dput(dentry);
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
+ RETURN(rc);
+
+}
+
+int filter_write_extents(struct obd_export *exp, struct obd_ioobj *obj, int nobj,
+ int niocount, struct niobuf_local *local, int rc)
+{
+ struct lvfs_run_ctxt saved;
+ struct dentry *dentry;
+ struct niobuf_local *lnb;
+ __u64 offset = 0;
+ __u32 len = 0;
+ int i, flags;
+
+ ENTRY;
+
+ LASSERT(nobj == 1);
+
+ push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
+ dentry = filter_id2dentry(exp->exp_obd, NULL, obj->ioo_gr,
+ obj->ioo_id);
+ if (IS_ERR(dentry)) {
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
+ RETURN (PTR_ERR(dentry));
+ }
+
+ if (dentry->d_inode == NULL) {
+ CERROR("trying to write extents to non-existent file "LPU64"\n",
+ obj->ioo_id);
+ GOTO(cleanup, rc = -ENOENT);
+ }
+
+ flags = fsfilt_get_fs_flags(exp->exp_obd, dentry);
+ if (!(flags & SM_DO_REC))
+ GOTO(cleanup, rc);
+
+ for (i = 0, lnb = local; i < obj->ioo_bufcnt; i++, lnb++) {
+ if (len == 0) {
+ offset = lnb->offset;
+ len = lnb->len;
+ } else if (lnb->offset == (offset + len)) {
+ len += lnb->len;
+ } else {
+ rc = fsfilt_write_extents(exp->exp_obd, dentry,
+ offset, len);
+ if (rc) {
+ CERROR("write exts off "LPU64" num %u rc:%d\n",
+ offset, len, rc);
+ GOTO(cleanup, rc);
+ }
+ offset = lnb->offset;
+ len = lnb->len;
+ }
+ }
+ if (len > 0) {
+ rc = fsfilt_write_extents(exp->exp_obd, dentry,
+ offset, len);
+ if (rc) {
+ CERROR("write exts off "LPU64" num %u rc:%d\n",
+ offset, len, rc);
+ GOTO(cleanup, rc);
+ }
+ }
+cleanup:
+ f_dput(dentry);
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
+ RETURN(rc);
+}