- /* If this is a continuation FIEMAP call and we are on
- * starting stripe then lun_start needs to be set to
- * fm_end_offset */
- if (fm_end_offset != 0 && cur_stripe == start_stripe)
- lun_start = fm_end_offset;
-
- if (fm_length != ~0ULL) {
- /* Handle fm_start + fm_length overflow */
- if (fm_start + fm_length < fm_start)
- fm_length = ~0ULL - fm_start;
- lun_end = lov_size_to_stripe(lsm, fm_start + fm_length,
- cur_stripe);
- } else {
- lun_end = ~0ULL;
- }
-
- if (lun_start == lun_end)
- continue;
-
- req_fm_len = obd_object_end - lun_start;
- fm_local->fm_length = 0;
- len_mapped_single_call = 0;
-
- /* If the output buffer is very large and the objects have many
- * extents we may need to loop on a single OST repeatedly */
- ost_eof = 0;
- ost_done = 0;
- do {
- if (get_num_extents == 0) {
- /* Don't get too many extents. */
- if (current_extent + count_local >
- fiemap->fm_extent_count)
- count_local = fiemap->fm_extent_count -
- current_extent;
- }
-
- lun_start += len_mapped_single_call;
- fm_local->fm_length = req_fm_len - len_mapped_single_call;
- req_fm_len = fm_local->fm_length;
- fm_local->fm_extent_count = count_local;
- fm_local->fm_mapped_extents = 0;
- fm_local->fm_flags = fiemap->fm_flags;
-
- fm_key->oa.o_oi = lsm->lsm_oinfo[cur_stripe]->loi_oi;
- ost_index = lsm->lsm_oinfo[cur_stripe]->loi_ost_idx;
-
- if (ost_index < 0 || ost_index >=lov->desc.ld_tgt_count)
- GOTO(out, rc = -EINVAL);
-
- /* If OST is inactive, return extent with UNKNOWN flag */
- if (!lov->lov_tgts[ost_index]->ltd_active) {
- fm_local->fm_flags |= FIEMAP_EXTENT_LAST;
- fm_local->fm_mapped_extents = 1;
-
- lcl_fm_ext[0].fe_logical = lun_start;
- lcl_fm_ext[0].fe_length = obd_object_end -
- lun_start;
- lcl_fm_ext[0].fe_flags |= FIEMAP_EXTENT_UNKNOWN;
-
- goto inactive_tgt;
- }
-
- fm_local->fm_start = lun_start;
- fm_local->fm_flags &= ~FIEMAP_FLAG_DEVICE_ORDER;
- memcpy(&fm_key->fiemap, fm_local, sizeof(*fm_local));
- *vallen=fiemap_count_to_size(fm_local->fm_extent_count);
- rc = obd_get_info(NULL,
- lov->lov_tgts[ost_index]->ltd_exp,
- keylen, key, vallen, fm_local, lsm);
- if (rc != 0)
- GOTO(out, rc);
-
-inactive_tgt:
- ext_count = fm_local->fm_mapped_extents;
- if (ext_count == 0) {
- ost_done = 1;
- /* If last stripe has hole at the end,
- * then we need to return */
- if (cur_stripe_wrap == last_stripe) {
- fiemap->fm_mapped_extents = 0;
- goto finish;
- }
- break;
- }
-
- /* If we just need num of extents then go to next device */
- if (get_num_extents) {
- current_extent += ext_count;
- break;
- }
-
- len_mapped_single_call = lcl_fm_ext[ext_count-1].fe_logical -
- lun_start + lcl_fm_ext[ext_count - 1].fe_length;
-
- /* Have we finished mapping on this device? */
- if (req_fm_len <= len_mapped_single_call)
- ost_done = 1;
-
- /* Clear the EXTENT_LAST flag which can be present on
- * last extent */
- if (lcl_fm_ext[ext_count-1].fe_flags & FIEMAP_EXTENT_LAST)
- lcl_fm_ext[ext_count - 1].fe_flags &=
- ~FIEMAP_EXTENT_LAST;
-
- curr_loc = lov_stripe_size(lsm,
- lcl_fm_ext[ext_count - 1].fe_logical+
- lcl_fm_ext[ext_count - 1].fe_length,
- cur_stripe);
- if (curr_loc >= fm_key->oa.o_size)
- ost_eof = 1;
-
- fiemap_prepare_and_copy_exts(fiemap, lcl_fm_ext,
- ost_index, ext_count,
- current_extent);
-
- current_extent += ext_count;
-
- /* Ran out of available extents? */
- if (current_extent >= fiemap->fm_extent_count)
- goto finish;
- } while (ost_done == 0 && ost_eof == 0);
-
- if (cur_stripe_wrap == last_stripe)
- goto finish;
- }
-
-finish:
- /* Indicate that we are returning device offsets unless file just has
- * single stripe */
- if (lsm->lsm_stripe_count > 1)
- fiemap->fm_flags |= FIEMAP_FLAG_DEVICE_ORDER;
-
- if (get_num_extents)
- goto skip_last_device_calc;
-
- /* Check if we have reached the last stripe and whether mapping for that
- * stripe is done. */
- if (cur_stripe_wrap == last_stripe) {
- if (ost_done || ost_eof)
- fiemap->fm_extents[current_extent - 1].fe_flags |=
- FIEMAP_EXTENT_LAST;
- }
-
-skip_last_device_calc:
- fiemap->fm_mapped_extents = current_extent;
-
-out:
- if (fm_local)
- OBD_FREE_LARGE(fm_local, buffer_size);
- return rc;