/** * Prepare buffers for read request processing. * * This function converts remote buffers from client to local buffers * and prepares the latter. * * \param[in] env execution environment * \param[in] exp OBD export of client * \param[in] ofd OFD device * \param[in] fid FID of object * \param[in] la object attributes * \param[in] oa OBDO structure from client * \param[in] niocount number of remote buffers * \param[in] rnb remote buffers * \param[in] nr_local number of local buffers * \param[in] lnb local buffers * \param[in] jobid job ID name * * \retval 0 on successful prepare * \retval negative value on error */ static int ofd_preprw_read(const struct lu_env *env, struct obd_export *exp, struct ofd_device *ofd, const struct lu_fid *fid, struct lu_attr *la, struct obdo *oa, int niocount, struct niobuf_remote *rnb, int *nr_local, struct niobuf_local *lnb, char *jobid) { struct ofd_object *fo; int i, j, rc, tot_bytes = 0; ENTRY; LASSERT(env != NULL); fo = ofd_object_find(env, ofd, fid); if (IS_ERR(fo)) RETURN(PTR_ERR(fo)); LASSERT(fo != NULL); ofd_read_lock(env, fo); if (!ofd_object_exists(fo)) GOTO(unlock, rc = -ENOENT); if (ofd->ofd_lfsck_verify_pfid && oa->o_valid & OBD_MD_FLFID) { rc = ofd_verify_ff(env, fo, oa); if (rc != 0) GOTO(unlock, rc); } *nr_local = 0; for (i = 0, j = 0; i < niocount; i++) { rc = dt_bufs_get(env, ofd_object_child(fo), rnb + i, lnb + j, 0); if (unlikely(rc < 0)) GOTO(buf_put, rc); LASSERT(rc <= PTLRPC_MAX_BRW_PAGES); /* correct index for local buffers to continue with */ j += rc; *nr_local += rc; LASSERT(j <= PTLRPC_MAX_BRW_PAGES); tot_bytes += rnb[i].rnb_len; } LASSERT(*nr_local > 0 && *nr_local <= PTLRPC_MAX_BRW_PAGES); rc = dt_attr_get(env, ofd_object_child(fo), la); if (unlikely(rc)) GOTO(buf_put, rc); rc = dt_read_prep(env, ofd_object_child(fo), lnb, *nr_local); if (unlikely(rc)) GOTO(buf_put, rc); ofd_counter_incr(exp, LPROC_OFD_STATS_READ, jobid, tot_bytes); RETURN(0); buf_put: dt_bufs_put(env, ofd_object_child(fo), lnb, *nr_local); unlock: ofd_read_unlock(env, fo); ofd_object_put(env, fo); return rc; }
/** * Prepare buffers for write request processing. * * This function converts remote buffers from client to local buffers * and prepares the latter. If there is recovery in progress and required * object is missing then it can be re-created before write. * * \param[in] env execution environment * \param[in] exp OBD export of client * \param[in] ofd OFD device * \param[in] fid FID of object * \param[in] la object attributes * \param[in] oa OBDO structure from client * \param[in] objcount always 1 * \param[in] obj object data * \param[in] rnb remote buffers * \param[in] nr_local number of local buffers * \param[in] lnb local buffers * \param[in] jobid job ID name * * \retval 0 on successful prepare * \retval negative value on error */ static int ofd_preprw_write(const struct lu_env *env, struct obd_export *exp, struct ofd_device *ofd, const struct lu_fid *fid, struct lu_attr *la, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *rnb, int *nr_local, struct niobuf_local *lnb, char *jobid) { struct ofd_object *fo; int i, j, k, rc = 0, tot_bytes = 0; ENTRY; LASSERT(env != NULL); LASSERT(objcount == 1); if (unlikely(exp->exp_obd->obd_recovering)) { u64 seq = fid_seq(fid); u64 oid = fid_oid(fid); struct ofd_seq *oseq; oseq = ofd_seq_load(env, ofd, seq); if (IS_ERR(oseq)) { CERROR("%s: Can't find FID Sequence "LPX64": rc = %d\n", ofd_name(ofd), seq, (int)PTR_ERR(oseq)); GOTO(out, rc = -EINVAL); } if (oid > ofd_seq_last_oid(oseq)) { int sync = 0; int diff; mutex_lock(&oseq->os_create_lock); diff = oid - ofd_seq_last_oid(oseq); /* Do sync create if the seq is about to used up */ if (fid_seq_is_idif(seq) || fid_seq_is_mdt0(seq)) { if (unlikely(oid >= IDIF_MAX_OID - 1)) sync = 1; } else if (fid_seq_is_norm(seq)) { if (unlikely(oid >= LUSTRE_DATA_SEQ_MAX_WIDTH - 1)) sync = 1; } else { CERROR("%s : invalid o_seq "DOSTID"\n", ofd_name(ofd), POSTID(&oa->o_oi)); mutex_unlock(&oseq->os_create_lock); ofd_seq_put(env, oseq); GOTO(out, rc = -EINVAL); } while (diff > 0) { u64 next_id = ofd_seq_last_oid(oseq) + 1; int count = ofd_precreate_batch(ofd, diff); rc = ofd_precreate_objects(env, ofd, next_id, oseq, count, sync); if (rc < 0) { mutex_unlock(&oseq->os_create_lock); ofd_seq_put(env, oseq); GOTO(out, rc); } diff -= rc; } mutex_unlock(&oseq->os_create_lock); } ofd_seq_put(env, oseq); } fo = ofd_object_find(env, ofd, fid); if (IS_ERR(fo)) GOTO(out, rc = PTR_ERR(fo)); LASSERT(fo != NULL); ofd_read_lock(env, fo); if (!ofd_object_exists(fo)) { CERROR("%s: BRW to missing obj "DOSTID"\n", exp->exp_obd->obd_name, POSTID(&obj->ioo_oid)); ofd_read_unlock(env, fo); ofd_object_put(env, fo); GOTO(out, rc = -ENOENT); } if (ofd->ofd_lfsck_verify_pfid && oa->o_valid & OBD_MD_FLFID) { rc = ofd_verify_ff(env, fo, oa); if (rc != 0) { ofd_read_unlock(env, fo); ofd_object_put(env, fo); GOTO(out, rc); } } /* Process incoming grant info, set OBD_BRW_GRANTED flag and grant some * space back if possible */ ofd_grant_prepare_write(env, exp, oa, rnb, obj->ioo_bufcnt); /* parse remote buffers to local buffers and prepare the latter */ *nr_local = 0; for (i = 0, j = 0; i < obj->ioo_bufcnt; i++) { rc = dt_bufs_get(env, ofd_object_child(fo), rnb + i, lnb + j, 1); if (unlikely(rc < 0)) GOTO(err, rc); LASSERT(rc <= PTLRPC_MAX_BRW_PAGES); /* correct index for local buffers to continue with */ for (k = 0; k < rc; k++) { lnb[j+k].lnb_flags = rnb[i].rnb_flags; if (!(rnb[i].rnb_flags & OBD_BRW_GRANTED)) lnb[j+k].lnb_rc = -ENOSPC; } j += rc; *nr_local += rc; LASSERT(j <= PTLRPC_MAX_BRW_PAGES); tot_bytes += rnb[i].rnb_len; } LASSERT(*nr_local > 0 && *nr_local <= PTLRPC_MAX_BRW_PAGES); rc = dt_write_prep(env, ofd_object_child(fo), lnb, *nr_local); if (unlikely(rc != 0)) GOTO(err, rc); ofd_counter_incr(exp, LPROC_OFD_STATS_WRITE, jobid, tot_bytes); RETURN(0); err: dt_bufs_put(env, ofd_object_child(fo), lnb, *nr_local); ofd_read_unlock(env, fo); ofd_object_put(env, fo); /* ofd_grant_prepare_write() was called, so we must commit */ ofd_grant_commit(exp, oa->o_grant_used, rc); out: /* let's still process incoming grant information packed in the oa, * but without enforcing grant since we won't proceed with the write. * Just like a read request actually. */ ofd_grant_prepare_read(env, exp, oa); return rc; }
int ofd_object_punch(const struct lu_env *env, struct ofd_object *fo, __u64 start, __u64 end, struct lu_attr *la, struct filter_fid *ff, struct obdo *oa) { struct ofd_thread_info *info = ofd_info(env); struct ofd_device *ofd = ofd_obj2dev(fo); struct ofd_mod_data *fmd; struct dt_object *dob = ofd_object_child(fo); struct thandle *th; int ff_needed = 0; int rc; ENTRY; /* we support truncate, not punch yet */ LASSERT(end == OBD_OBJECT_EOF); fmd = ofd_fmd_get(info->fti_exp, &fo->ofo_header.loh_fid); if (fmd && fmd->fmd_mactime_xid < info->fti_xid) fmd->fmd_mactime_xid = info->fti_xid; ofd_fmd_put(info->fti_exp, fmd); ofd_write_lock(env, fo); if (!ofd_object_exists(fo)) GOTO(unlock, rc = -ENOENT); if (ofd->ofd_lfsck_verify_pfid && oa->o_valid & OBD_MD_FLFID) { rc = ofd_verify_ff(env, fo, oa); if (rc != 0) GOTO(unlock, rc); } /* VBR: version recovery check */ rc = ofd_version_get_check(info, fo); if (rc) GOTO(unlock, rc); rc = ofd_attr_handle_ugid(env, fo, la, 0 /* !is_setattr */); if (rc != 0) GOTO(unlock, rc); if (ff != NULL) { rc = ofd_object_ff_load(env, fo); if (rc == -ENODATA) ff_needed = 1; else if (rc < 0) GOTO(unlock, rc); } th = ofd_trans_create(env, ofd); if (IS_ERR(th)) GOTO(unlock, rc = PTR_ERR(th)); rc = dt_declare_attr_set(env, dob, la, th); if (rc) GOTO(stop, rc); rc = dt_declare_punch(env, dob, start, OBD_OBJECT_EOF, th); if (rc) GOTO(stop, rc); if (ff_needed) { info->fti_buf.lb_buf = ff; info->fti_buf.lb_len = sizeof(*ff); rc = dt_declare_xattr_set(env, ofd_object_child(fo), &info->fti_buf, XATTR_NAME_FID, 0, th); if (rc) GOTO(stop, rc); } rc = ofd_trans_start(env, ofd, fo, th); if (rc) GOTO(stop, rc); rc = dt_punch(env, dob, start, OBD_OBJECT_EOF, th, ofd_object_capa(env, fo)); if (rc) GOTO(stop, rc); rc = dt_attr_set(env, dob, la, th, ofd_object_capa(env, fo)); if (rc) GOTO(stop, rc); if (ff_needed) { rc = dt_xattr_set(env, ofd_object_child(fo), &info->fti_buf, XATTR_NAME_FID, 0, th, BYPASS_CAPA); if (rc == 0) { fo->ofo_pfid.f_seq = le64_to_cpu(ff->ff_parent.f_seq); fo->ofo_pfid.f_oid = le32_to_cpu(ff->ff_parent.f_oid); /* Currently, the filter_fid::ff_parent::f_ver is not * the real parent MDT-object's FID::f_ver, instead it * is the OST-object index in its parent MDT-object's * layout EA. */ fo->ofo_pfid.f_stripe_idx = le32_to_cpu(ff->ff_parent.f_stripe_idx); } } GOTO(stop, rc); stop: ofd_trans_stop(env, ofd, th, rc); unlock: ofd_write_unlock(env, fo); return rc; }