- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- int err;
-
- if (lov->tgts[loi->loi_ost_idx].active == 0) {
- CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
- continue;
- }
-
- memcpy(tmp_oa, src_oa, sizeof(*tmp_oa));
- tmp_oa->o_id = loi->loi_id;
-
- if (src_oa->o_valid & OBD_MD_FLSIZE) {
- if (lov_stripe_offset(lsm, src_oa->o_size, i,
- &tmp_oa->o_size) < 0 &&
- tmp_oa->o_size)
- tmp_oa->o_size--;
-
- CDEBUG(D_INODE, "stripe %d has size "LPU64"/"LPU64"\n",
- i, tmp_oa->o_size, src_oa->o_size);
- }
-
- err = obd_setattr(lov->tgts[loi->loi_ost_idx].ltd_exp, tmp_oa,
- NULL, NULL);
- if (err) {
- if (lov->tgts[loi->loi_ost_idx].active) {
- CERROR("error: setattr objid "LPX64" subobj "
- LPX64" on OST idx %d: rc = %d\n",
- src_oa->o_id, loi->loi_id,
- loi->loi_ost_idx, err);
- if (!rc)
- rc = err;
- }
- continue;
- }
- lov_merge_attrs(ret_oa, tmp_oa, tmp_oa->o_valid, lsm, i, &set);
- }
- if (!set && !rc)
- rc = -EIO;
-
- ret_oa->o_id = src_oa->o_id;
- memcpy(src_oa, ret_oa, sizeof(*src_oa));
- GOTO(out_tmp, rc);
-out_tmp:
- obdo_free(tmp_oa);
-out_oa:
- obdo_free(ret_oa);
- return rc;
-}
-
-/* we have an offset in file backed by an lov and want to find out where
- * that offset lands in our given stripe of the file. for the easy
- * case where the offset is within the stripe, we just have to scale the
- * offset down to make it relative to the stripe instead of the lov.
- *
- * the harder case is what to do when the offset doesn't intersect the
- * stripe. callers will want start offsets clamped ahead to the start
- * of the nearest stripe in the file. end offsets similarly clamped to the
- * nearest ending byte of a stripe in the file:
- *
- * all this function does is move offsets to the nearest region of the
- * stripe, and it does its work "mod" the full length of all the stripes.
- * consider a file with 3 stripes:
- *
- * S E
- * ---------------------------------------------------------------------
- * | 0 | 1 | 2 | 0 | 1 | 2 |
- * ---------------------------------------------------------------------
- *
- * to find stripe 1's offsets for S and E, it divides by the full stripe
- * width and does its math in the context of a single set of stripes:
- *
- * S E
- * -----------------------------------
- * | 0 | 1 | 2 |
- * -----------------------------------
- *
- * it'll notice that E is outside stripe 1 and clamp it to the end of the
- * stripe, then multiply it back out by lov_off to give the real offsets in
- * the stripe:
- *
- * S E
- * ---------------------------------------------------------------------
- * | 1 | 1 | 1 | 1 | 1 | 1 |
- * ---------------------------------------------------------------------
- *
- * it would have done similarly and pulled S forward to the start of a 1
- * stripe if, say, S had landed in a 0 stripe.
- *
- * this rounding isn't always correct. consider an E lov offset that lands
- * on a 0 stripe, the "mod stripe width" math will pull it forward to the
- * start of a 1 stripe, when in fact it wanted to be rounded back to the end
- * of a previous 1 stripe. this logic is handled by callers and this is why:
- *
- * this function returns < 0 when the offset was "before" the stripe and
- * was moved forward to the start of the stripe in question; 0 when it
- * falls in the stripe and no shifting was done; > 0 when the offset
- * was outside the stripe and was pulled back to its final byte. */
-static int lov_stripe_offset(struct lov_stripe_md *lsm, obd_off lov_off,
- int stripeno, obd_off *obd_off)
-{
- unsigned long ssize = lsm->lsm_stripe_size;
- unsigned long swidth = ssize * lsm->lsm_stripe_count;
- unsigned long stripe_off, this_stripe;
- int ret = 0;
-
- if (lov_off == OBD_OBJECT_EOF) {
- *obd_off = OBD_OBJECT_EOF;
- return 0;
- }
-
- /* do_div(a, b) returns a % b, and a = a / b */
- stripe_off = do_div(lov_off, swidth);
-
- this_stripe = stripeno * ssize;
- if (stripe_off < this_stripe) {
- stripe_off = 0;
- ret = -1;
- } else {
- stripe_off -= this_stripe;