From: Bobi Jam Date: Mon, 3 Nov 2014 10:52:29 +0000 (+0800) Subject: LU-5823 clio: add cl_object_fiemap() X-Git-Tag: 2.7.51~21 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=c16ecc8600c57f5b2338c59649654bb2716780f6 LU-5823 clio: add cl_object_fiemap() * Add cl_object_operations::coo_fiemap(). * Add cl_object_fiemap() to get FIEMAP mappings. Signed-off-by: Bobi Jam Change-Id: Ie32eb5ddb8d2daa1a66055f347cef4757d039e75 Reviewed-on: http://review.whamcloud.com/12535 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index 7c72c41..23d6ea4 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -409,6 +409,12 @@ struct cl_object_operations { */ int (*coo_find_cbdata)(const struct lu_env *env, struct cl_object *obj, ldlm_iterator_t iter, void *data); + /** + * Get FIEMAP mapping from the object. + */ + int (*coo_fiemap)(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *fmkey, + struct fiemap *fiemap, size_t *buflen); }; /** @@ -2180,6 +2186,9 @@ int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, struct lov_user_md __user *lum); int cl_object_find_cbdata(const struct lu_env *env, struct cl_object *obj, ldlm_iterator_t iter, void *data); +int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *fmkey, struct fiemap *fiemap, + size_t *buflen); /** * Returns true, iff \a o0 and \a o1 are slices of the same object. diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 349df65..7d9c922 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1696,43 +1696,34 @@ out: /** * Get size for inode for which FIEMAP mapping is requested. * Make the FIEMAP get_info call and returns the result. + * \param fiemap kernel buffer to hold extens + * \param num_bytes kernel buffer size */ -static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap, +static int ll_do_fiemap(struct inode *inode, struct fiemap *fiemap, size_t num_bytes) { - struct obd_export *exp = ll_i2dtexp(inode); - struct lov_stripe_md *lsm = NULL; - struct ll_fiemap_info_key fm_key = { .name = KEY_FIEMAP, }; - __u32 vallen = num_bytes; - int rc; - ENTRY; - - /* Checks for fiemap flags */ - if (fiemap->fm_flags & ~LUSTRE_FIEMAP_FLAGS_COMPAT) { - fiemap->fm_flags &= ~LUSTRE_FIEMAP_FLAGS_COMPAT; - return -EBADR; - } - - /* Check for FIEMAP_FLAG_SYNC */ - if (fiemap->fm_flags & FIEMAP_FLAG_SYNC) { - rc = filemap_fdatawrite(inode->i_mapping); - if (rc) - return rc; - } + struct lu_env *env; + int refcheck; + int rc = 0; + struct ll_fiemap_info_key fmkey = { .name = KEY_FIEMAP, }; + ENTRY; - lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) - return -ENOENT; + /* Checks for fiemap flags */ + if (fiemap->fm_flags & ~LUSTRE_FIEMAP_FLAGS_COMPAT) { + fiemap->fm_flags &= ~LUSTRE_FIEMAP_FLAGS_COMPAT; + return -EBADR; + } - /* If the stripe_count > 1 and the application does not understand - * DEVICE_ORDER flag, then it cannot interpret the extents correctly. - */ - if (lsm->lsm_stripe_count > 1 && - !(fiemap->fm_flags & FIEMAP_FLAG_DEVICE_ORDER)) - GOTO(out, rc = -EOPNOTSUPP); + /* Check for FIEMAP_FLAG_SYNC */ + if (fiemap->fm_flags & FIEMAP_FLAG_SYNC) { + rc = filemap_fdatawrite(inode->i_mapping); + if (rc) + return rc; + } - fm_key.oa.o_oi = lsm->lsm_oi; - fm_key.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP; + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + RETURN(PTR_ERR(env)); if (i_size_read(inode) == 0) { rc = ll_glimpse_size(inode); @@ -1740,23 +1731,22 @@ static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap, GOTO(out, rc); } - obdo_from_inode(&fm_key.oa, inode, OBD_MD_FLSIZE); - obdo_set_parent_fid(&fm_key.oa, &ll_i2info(inode)->lli_fid); - /* If filesize is 0, then there would be no objects for mapping */ - if (fm_key.oa.o_size == 0) { - fiemap->fm_mapped_extents = 0; - GOTO(out, rc = 0); - } + fmkey.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP; + obdo_from_inode(&fmkey.oa, inode, OBD_MD_FLSIZE); + obdo_set_parent_fid(&fmkey.oa, &ll_i2info(inode)->lli_fid); - memcpy(&fm_key.fiemap, fiemap, sizeof(*fiemap)); + /* If filesize is 0, then there would be no objects for mapping */ + if (fmkey.oa.o_size == 0) { + fiemap->fm_mapped_extents = 0; + GOTO(out, rc = 0); + } - rc = obd_get_info(NULL, exp, sizeof(fm_key), &fm_key, &vallen, - fiemap, lsm); - if (rc) - CERROR("obd_get_info failed: rc = %d\n", rc); + fmkey.fiemap = *fiemap; + rc = cl_object_fiemap(env, ll_i2info(inode)->lli_clob, + &fmkey, fiemap, &num_bytes); out: - ccc_inode_lsm_put(inode, lsm); + cl_env_put(env, &refcheck); RETURN(rc); } @@ -1803,60 +1793,59 @@ gf_free: RETURN(rc); } -static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg) +static int ll_ioctl_fiemap(struct inode *inode, struct fiemap __user *arg) { - struct ll_user_fiemap *fiemap_s; - size_t num_bytes, ret_bytes; - unsigned int extent_count; - int rc = 0; + struct fiemap *fiemap; + size_t num_bytes; + size_t ret_bytes; + __u32 extent_count; + int rc = 0; - /* Get the extent count so we can calculate the size of - * required fiemap buffer */ - if (get_user(extent_count, - &((struct ll_user_fiemap __user *)arg)->fm_extent_count)) - RETURN(-EFAULT); + /* Get the extent count so we can calculate the size of + * required fiemap buffer */ + if (get_user(extent_count, &arg->fm_extent_count)) + RETURN(-EFAULT); if (extent_count >= - (SIZE_MAX - sizeof(*fiemap_s)) / sizeof(struct ll_fiemap_extent)) + (SIZE_MAX - sizeof(*fiemap)) / sizeof(struct ll_fiemap_extent)) RETURN(-EINVAL); - num_bytes = sizeof(*fiemap_s) + (extent_count * - sizeof(struct ll_fiemap_extent)); + num_bytes = sizeof(*fiemap) + (extent_count * + sizeof(struct ll_fiemap_extent)); - OBD_ALLOC_LARGE(fiemap_s, num_bytes); - if (fiemap_s == NULL) - RETURN(-ENOMEM); + OBD_ALLOC_LARGE(fiemap, num_bytes); + if (fiemap == NULL) + RETURN(-ENOMEM); /* get the fiemap value */ - if (copy_from_user(fiemap_s, (struct ll_user_fiemap __user *)arg, - sizeof(*fiemap_s))) + if (copy_from_user(fiemap, arg, sizeof(*fiemap))) GOTO(error, rc = -EFAULT); - /* If fm_extent_count is non-zero, read the first extent since - * it is used to calculate end_offset and device from previous - * fiemap call. */ - if (extent_count) { - if (copy_from_user(&fiemap_s->fm_extents[0], - (char __user *)arg + sizeof(*fiemap_s), - sizeof(struct ll_fiemap_extent))) - GOTO(error, rc = -EFAULT); - } + /* If fm_extent_count is non-zero, read the first extent since + * it is used to calculate end_offset and device from previous + * fiemap call. */ + if (extent_count != 0) { + if (copy_from_user(&fiemap->fm_extents[0], + (char __user *)arg + sizeof(*fiemap), + sizeof(struct ll_fiemap_extent))) + GOTO(error, rc = -EFAULT); + } - rc = ll_do_fiemap(inode, fiemap_s, num_bytes); - if (rc) - GOTO(error, rc); + rc = ll_do_fiemap(inode, fiemap, num_bytes); + if (rc) + GOTO(error, rc); - ret_bytes = sizeof(struct ll_user_fiemap); + ret_bytes = sizeof(struct fiemap); - if (extent_count != 0) - ret_bytes += (fiemap_s->fm_mapped_extents * - sizeof(struct ll_fiemap_extent)); + if (extent_count != 0) + ret_bytes += (fiemap->fm_mapped_extents * + sizeof(struct ll_fiemap_extent)); - if (copy_to_user((void __user *)arg, fiemap_s, ret_bytes)) + if (copy_to_user((void __user *)arg, fiemap, ret_bytes)) rc = -EFAULT; error: - OBD_FREE_LARGE(fiemap_s, num_bytes); - RETURN(rc); + OBD_FREE_LARGE(fiemap, num_bytes); + RETURN(rc); } /* @@ -2273,8 +2262,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_LOV_GETSTRIPE: RETURN(ll_file_getstripe(inode, (struct lov_user_md __user *)arg)); - case FSFILT_IOC_FIEMAP: - RETURN(ll_ioctl_fiemap(inode, arg)); + case FSFILT_IOC_FIEMAP: + RETURN(ll_ioctl_fiemap(inode, (struct fiemap __user *)arg)); case FSFILT_IOC_GETFLAGS: case FSFILT_IOC_SETFLAGS: RETURN(ll_iocontrol(inode, file, cmd, arg)); diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 0b62a00..49f332e 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include "lov_internal.h" @@ -1453,411 +1452,6 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, RETURN(rc); } -#define FIEMAP_BUFFER_SIZE 4096 - -/** - * Non-zero fe_logical indicates that this is a continuation FIEMAP - * call. The local end offset and the device are sent in the first - * fm_extent. This function calculates the stripe number from the index. - * This function returns a stripe_no on which mapping is to be restarted. - * - * This function returns fm_end_offset which is the in-OST offset at which - * mapping should be restarted. If fm_end_offset=0 is returned then caller - * will re-calculate proper offset in next stripe. - * Note that the first extent is passed to lov_get_info via the value field. - * - * \param fiemap fiemap request header - * \param lsm striping information for the file - * \param fm_start logical start of mapping - * \param fm_end logical end of mapping - * \param start_stripe starting stripe will be returned in this - */ -static loff_t fiemap_calc_fm_end_offset(struct ll_user_fiemap *fiemap, - struct lov_stripe_md *lsm, - loff_t fm_start, - loff_t fm_end, int *start_stripe) -{ - loff_t local_end = fiemap->fm_extents[0].fe_logical; - loff_t lun_start; - loff_t lun_end; - loff_t fm_end_offset; - int stripe_no = -1; - int i; - - if (fiemap->fm_extent_count == 0 || - fiemap->fm_extents[0].fe_logical == 0) - return 0; - - /* Find out stripe_no from ost_index saved in the fe_device */ - for (i = 0; i < lsm->lsm_stripe_count; i++) { - struct lov_oinfo *oinfo = lsm->lsm_oinfo[i]; - - if (lov_oinfo_is_dummy(oinfo)) - continue; - - if (oinfo->loi_ost_idx == fiemap->fm_extents[0].fe_device) { - stripe_no = i; - break; - } - } - - if (stripe_no == -1) - return -EINVAL; - - /* If we have finished mapping on previous device, shift logical - * offset to start of next device */ - if ((lov_stripe_intersects(lsm, stripe_no, fm_start, fm_end, - &lun_start, &lun_end)) != 0 && - local_end < lun_end) { - fm_end_offset = local_end; - *start_stripe = stripe_no; - } else { - /* This is a special value to indicate that caller should - * calculate offset in next stripe. */ - fm_end_offset = 0; - *start_stripe = (stripe_no + 1) % lsm->lsm_stripe_count; - } - - return fm_end_offset; -} - -/** - * We calculate on which OST the mapping will end. If the length of mapping - * is greater than (stripe_size * stripe_count) then the last_stripe will - * will be one just before start_stripe. Else we check if the mapping - * intersects each OST and find last_stripe. - * This function returns the last_stripe and also sets the stripe_count - * over which the mapping is spread - * - * \param lsm striping information for the file - * \param fm_start logical start of mapping - * \param fm_end logical end of mapping - * \param start_stripe starting stripe of the mapping - * \param stripe_count the number of stripes across which to map is returned - * - * \retval last_stripe return the last stripe of the mapping - */ -static int fiemap_calc_last_stripe(struct lov_stripe_md *lsm, - loff_t fm_start, loff_t fm_end, - int start_stripe, int *stripe_count) -{ - int last_stripe; - loff_t obd_start; - loff_t obd_end; - int i, j; - - if (fm_end - fm_start > lsm->lsm_stripe_size * lsm->lsm_stripe_count) { - last_stripe = (start_stripe < 1 ? lsm->lsm_stripe_count - 1 : - start_stripe - 1); - *stripe_count = lsm->lsm_stripe_count; - } else { - for (j = 0, i = start_stripe; j < lsm->lsm_stripe_count; - i = (i + 1) % lsm->lsm_stripe_count, j++) { - if ((lov_stripe_intersects(lsm, i, fm_start, fm_end, - &obd_start, &obd_end)) == 0) - break; - } - *stripe_count = j; - last_stripe = (start_stripe + j - 1) %lsm->lsm_stripe_count; - } - - return last_stripe; -} - -/** - * Set fe_device and copy extents from local buffer into main return buffer. - * - * \param fiemap fiemap request header - * \param lcl_fm_ext array of local fiemap extents to be copied - * \param ost_index OST index to be written into the fm_device field for each - extent - * \param ext_count number of extents to be copied - * \param current_extent where to start copying in main extent array - */ -static void fiemap_prepare_and_copy_exts(struct ll_user_fiemap *fiemap, - struct ll_fiemap_extent *lcl_fm_ext, - int ost_index, unsigned int ext_count, - int current_extent) -{ - char *to; - int ext; - - for (ext = 0; ext < ext_count; ext++) { - lcl_fm_ext[ext].fe_device = ost_index; - lcl_fm_ext[ext].fe_flags |= FIEMAP_EXTENT_NET; - } - - /* Copy fm_extent's from fm_local to return buffer */ - to = (char *)fiemap + fiemap_count_to_size(current_extent); - memcpy(to, lcl_fm_ext, ext_count * sizeof(struct ll_fiemap_extent)); -} - -/** - * Break down the FIEMAP request and send appropriate calls to individual OSTs. - * This also handles the restarting of FIEMAP calls in case mapping overflows - * the available number of extents in single call. - */ -static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, - __u32 *vallen, void *val, struct lov_stripe_md *lsm) -{ - struct ll_fiemap_info_key *fm_key = key; - struct ll_user_fiemap *fiemap = val; - struct ll_user_fiemap *fm_local = NULL; - struct ll_fiemap_extent *lcl_fm_ext; - int count_local; - unsigned int get_num_extents = 0; - int ost_index = 0, actual_start_stripe, start_stripe; - loff_t fm_start; - loff_t fm_end; - loff_t fm_length; - loff_t fm_end_offset; - u64 curr_loc; - int current_extent = 0, rc = 0, i; - /* Whether have we collected enough extents */ - bool enough = false; - int ost_eof = 0; /* EOF for object */ - int ost_done = 0; /* done with required mapping for this OST? */ - int last_stripe; - int cur_stripe = 0, cur_stripe_wrap = 0, stripe_count; - unsigned int buffer_size = FIEMAP_BUFFER_SIZE; - - if (!lsm_has_objects(lsm)) { - if (lsm && lsm_is_released(lsm) && (fm_key->fiemap.fm_start < - fm_key->oa.o_size)) { - /* released file, return a minimal FIEMAP if - * request fits in file-size. - */ - fiemap->fm_mapped_extents = 1; - fiemap->fm_extents[0].fe_logical = - fm_key->fiemap.fm_start; - if (fm_key->fiemap.fm_start + fm_key->fiemap.fm_length < - fm_key->oa.o_size) - fiemap->fm_extents[0].fe_length = - fm_key->fiemap.fm_length; - else - fiemap->fm_extents[0].fe_length = - fm_key->oa.o_size - - fm_key->fiemap.fm_start; - fiemap->fm_extents[0].fe_flags |= - (FIEMAP_EXTENT_UNKNOWN | - FIEMAP_EXTENT_LAST); - } - GOTO(out, rc = 0); - } - - if (fiemap_count_to_size(fm_key->fiemap.fm_extent_count) < buffer_size) - buffer_size = fiemap_count_to_size(fm_key->fiemap.fm_extent_count); - - OBD_ALLOC_LARGE(fm_local, buffer_size); - if (fm_local == NULL) - GOTO(out, rc = -ENOMEM); - lcl_fm_ext = &fm_local->fm_extents[0]; - - count_local = fiemap_size_to_count(buffer_size); - - memcpy(fiemap, &fm_key->fiemap, sizeof(*fiemap)); - fm_start = fiemap->fm_start; - fm_length = fiemap->fm_length; - /* Calculate start stripe, last stripe and length of mapping */ - actual_start_stripe = start_stripe = lov_stripe_number(lsm, fm_start); - fm_end = (fm_length == ~0ULL ? fm_key->oa.o_size : - fm_start + fm_length - 1); - /* If fm_length != ~0ULL but fm_start+fm_length-1 exceeds file size */ - if (fm_end > fm_key->oa.o_size) - fm_end = fm_key->oa.o_size; - - last_stripe = fiemap_calc_last_stripe(lsm, fm_start, fm_end, - actual_start_stripe, &stripe_count); - - fm_end_offset = fiemap_calc_fm_end_offset(fiemap, lsm, fm_start, - fm_end, &start_stripe); - if (fm_end_offset == -EINVAL) - GOTO(out, rc = -EINVAL); - - if (fiemap_count_to_size(fiemap->fm_extent_count) > *vallen) - fiemap->fm_extent_count = fiemap_size_to_count(*vallen); - if (fiemap->fm_extent_count == 0) { - get_num_extents = 1; - count_local = 0; - } - /* Check each stripe */ - for (cur_stripe = start_stripe, i = 0; i < stripe_count; - i++, cur_stripe = (cur_stripe + 1) % lsm->lsm_stripe_count) { - loff_t req_fm_len; /* Stores length of required mapping */ - loff_t len_mapped_single_call; - loff_t lun_start; - loff_t lun_end; - loff_t obd_object_end; - unsigned int ext_count; - - cur_stripe_wrap = cur_stripe; - - /* Find out range of mapping on this stripe */ - if ((lov_stripe_intersects(lsm, cur_stripe, fm_start, fm_end, - &lun_start, &obd_object_end)) == 0) - continue; - - if (lov_oinfo_is_dummy(lsm->lsm_oinfo[cur_stripe])) - GOTO(out, rc = -EIO); - - /* 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 = enough ? 1 : 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; - } else if (enough) { - /* - * We've collected enough extents and there are - * more extents after it. - */ - goto finish; - } - - /* 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) - enough = true; - } 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; -} - static int lov_get_info(const struct lu_env *env, struct obd_export *exp, __u32 keylen, void *key, __u32 *vallen, void *val, @@ -1878,9 +1472,6 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp, *desc_ret = lov->desc; GOTO(out, rc = 0); - } else if (KEY_IS(KEY_FIEMAP)) { - rc = lov_fiemap(lov, keylen, key, vallen, val, lsm); - GOTO(out, rc); } else if (KEY_IS(KEY_TGT_COUNT)) { *((int *)val) = lov->desc.ld_tgt_count; GOTO(out, rc = 0); diff --git a/lustre/lov/lov_object.c b/lustre/lov/lov_object.c index 7d66e66..8feeee2 100644 --- a/lustre/lov/lov_object.c +++ b/lustre/lov/lov_object.c @@ -333,6 +333,36 @@ static int lov_init_released(const struct lu_env *env, return 0; } +static struct cl_object *lov_find_subobj(const struct lu_env *env, + struct lov_object *lov, + struct lov_stripe_md *lsm, + int stripe_idx) +{ + struct lov_device *dev = lu2lov_dev(lov2lu(lov)->lo_dev); + struct lov_oinfo *oinfo = lsm->lsm_oinfo[stripe_idx]; + struct lov_thread_info *lti = lov_env_info(env); + struct lu_fid *ofid = <i->lti_fid; + struct cl_device *subdev; + int ost_idx; + int rc; + struct cl_object *result; + + if (lov->lo_type != LLT_RAID0) + GOTO(out, result = NULL); + + ost_idx = oinfo->loi_ost_idx; + rc = ostid_to_fid(ofid, &oinfo->loi_oi, ost_idx); + if (rc != 0) + GOTO(out, result = NULL); + + subdev = lovsub2cl_dev(dev->ld_target[ost_idx]); + result = lov_sub_find(env, subdev, ofid, NULL); +out: + if (result == NULL) + result = ERR_PTR(-EINVAL); + return result; +} + static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov, union lov_layout_state *state) { @@ -975,6 +1005,446 @@ int lov_lock_init(const struct lu_env *env, struct cl_object *obj, io); } +/** + * We calculate on which OST the mapping will end. If the length of mapping + * is greater than (stripe_size * stripe_count) then the last_stripe will + * will be one just before start_stripe. Else we check if the mapping + * intersects each OST and find last_stripe. + * This function returns the last_stripe and also sets the stripe_count + * over which the mapping is spread + * + * \param lsm [in] striping information for the file + * \param fm_start [in] logical start of mapping + * \param fm_end [in] logical end of mapping + * \param start_stripe [in] starting stripe of the mapping + * \param stripe_count [out] the number of stripes across which to map is + * returned + * + * \retval last_stripe return the last stripe of the mapping + */ +static int fiemap_calc_last_stripe(struct lov_stripe_md *lsm, + loff_t fm_start, loff_t fm_end, + int start_stripe, int *stripe_count) +{ + int last_stripe; + loff_t obd_start; + loff_t obd_end; + int i, j; + + if (fm_end - fm_start > lsm->lsm_stripe_size * lsm->lsm_stripe_count) { + last_stripe = (start_stripe < 1 ? lsm->lsm_stripe_count - 1 : + start_stripe - 1); + *stripe_count = lsm->lsm_stripe_count; + } else { + for (j = 0, i = start_stripe; j < lsm->lsm_stripe_count; + i = (i + 1) % lsm->lsm_stripe_count, j++) { + if ((lov_stripe_intersects(lsm, i, fm_start, fm_end, + &obd_start, &obd_end)) == 0) + break; + } + *stripe_count = j; + last_stripe = (start_stripe + j - 1) % lsm->lsm_stripe_count; + } + + return last_stripe; +} + +/** + * Set fe_device and copy extents from local buffer into main return buffer. + * + * \param fiemap [out] fiemap to hold all extents + * \param lcl_fm_ext [in] array of fiemap extents get from OSC layer + * \param ost_index [in] OST index to be written into the fm_device + * field for each extent + * \param ext_count [in] number of extents to be copied + * \param current_extent [in] where to start copying in the extent array + */ +static void fiemap_prepare_and_copy_exts(struct fiemap *fiemap, + struct ll_fiemap_extent *lcl_fm_ext, + int ost_index, unsigned int ext_count, + int current_extent) +{ + char *to; + unsigned int ext; + + for (ext = 0; ext < ext_count; ext++) { + lcl_fm_ext[ext].fe_device = ost_index; + lcl_fm_ext[ext].fe_flags |= FIEMAP_EXTENT_NET; + } + + /* Copy fm_extent's from fm_local to return buffer */ + to = (char *)fiemap + fiemap_count_to_size(current_extent); + memcpy(to, lcl_fm_ext, ext_count * sizeof(struct ll_fiemap_extent)); +} + +#define FIEMAP_BUFFER_SIZE 4096 + +/** + * Non-zero fe_logical indicates that this is a continuation FIEMAP + * call. The local end offset and the device are sent in the first + * fm_extent. This function calculates the stripe number from the index. + * This function returns a stripe_no on which mapping is to be restarted. + * + * This function returns fm_end_offset which is the in-OST offset at which + * mapping should be restarted. If fm_end_offset=0 is returned then caller + * will re-calculate proper offset in next stripe. + * Note that the first extent is passed to lov_get_info via the value field. + * + * \param fiemap [in] fiemap request header + * \param lsm [in] striping information for the file + * \param fm_start [in] logical start of mapping + * \param fm_end [in] logical end of mapping + * \param start_stripe [out] starting stripe will be returned in this + */ +static loff_t fiemap_calc_fm_end_offset(struct fiemap *fiemap, + struct lov_stripe_md *lsm, + loff_t fm_start, loff_t fm_end, + int *start_stripe) +{ + loff_t local_end = fiemap->fm_extents[0].fe_logical; + loff_t lun_start; + loff_t lun_end; + loff_t fm_end_offset; + int stripe_no = -1; + int i; + + if (fiemap->fm_extent_count == 0 || + fiemap->fm_extents[0].fe_logical == 0) + return 0; + + /* Find out stripe_no from ost_index saved in the fe_device */ + for (i = 0; i < lsm->lsm_stripe_count; i++) { + struct lov_oinfo *oinfo = lsm->lsm_oinfo[i]; + + if (lov_oinfo_is_dummy(oinfo)) + continue; + + if (oinfo->loi_ost_idx == fiemap->fm_extents[0].fe_device) { + stripe_no = i; + break; + } + } + + if (stripe_no == -1) + return -EINVAL; + + /* If we have finished mapping on previous device, shift logical + * offset to start of next device */ + if (lov_stripe_intersects(lsm, stripe_no, fm_start, fm_end, + &lun_start, &lun_end) != 0 && + local_end < lun_end) { + fm_end_offset = local_end; + *start_stripe = stripe_no; + } else { + /* This is a special value to indicate that caller should + * calculate offset in next stripe. */ + fm_end_offset = 0; + *start_stripe = (stripe_no + 1) % lsm->lsm_stripe_count; + } + + return fm_end_offset; +} + +/** + * Break down the FIEMAP request and send appropriate calls to individual OSTs. + * This also handles the restarting of FIEMAP calls in case mapping overflows + * the available number of extents in single call. + * + * \param env [in] lustre environment + * \param obj [in] file object + * \param fmkey [in] fiemap request header and other info + * \param fiemap [out] fiemap buffer holding retrived map extents + * \param buflen [in/out] max buffer length of @fiemap, when iterate + * each OST, it is used to limit max map needed + * \retval 0 success + * \retval < 0 error + */ +static int lov_object_fiemap(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *fmkey, + struct fiemap *fiemap, size_t *buflen) +{ + struct lov_stripe_md *lsm; + struct cl_object *subobj = NULL; + struct lov_obd *lov = lu2lov_dev(obj->co_lu.lo_dev)->ld_lov; + struct fiemap *fm_local = NULL; + struct ll_fiemap_extent *lcl_fm_ext; + loff_t fm_start; + loff_t fm_end; + loff_t fm_length; + loff_t fm_end_offset; + int count_local; + int ost_index = 0; + int start_stripe; + int current_extent = 0; + int rc = 0; + int last_stripe; + int cur_stripe = 0; + int cur_stripe_wrap = 0; + int stripe_count; + unsigned int buffer_size = FIEMAP_BUFFER_SIZE; + /* Whether have we collected enough extents */ + bool enough = false; + /* EOF for object */ + bool ost_eof = false; + /* done with required mapping for this OST? */ + bool ost_done = false; + ENTRY; + + lsm = lov_lsm_addref(cl2lov(obj)); + if (lsm == NULL) + RETURN(-ENODATA); + + /** + * If the stripe_count > 1 and the application does not understand + * DEVICE_ORDER flag, it cannot interpret the extents correctly. + */ + if (lsm->lsm_stripe_count > 1 && !(fiemap->fm_flags & + FIEMAP_FLAG_DEVICE_ORDER)) + GOTO(out, rc = -ENOTSUPP); + + if (lsm_is_released(lsm)) { + if (fiemap->fm_start < fmkey->oa.o_size) { + /** + * released file, return a minimal FIEMAP if + * request fits in file-size. + */ + fiemap->fm_mapped_extents = 1; + fiemap->fm_extents[0].fe_logical = fiemap->fm_start; + if (fiemap->fm_start + fiemap->fm_length < + fmkey->oa.o_size) + fiemap->fm_extents[0].fe_length = + fiemap->fm_length; + else + fiemap->fm_extents[0].fe_length = + fmkey->oa.o_size - fiemap->fm_start; + fiemap->fm_extents[0].fe_flags |= + FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_LAST; + } + GOTO(out, rc = 0); + } + + if (fiemap_count_to_size(fiemap->fm_extent_count) < buffer_size) + buffer_size = fiemap_count_to_size(fiemap->fm_extent_count); + + OBD_ALLOC_LARGE(fm_local, buffer_size); + if (fm_local == NULL) + GOTO(out, rc = -ENOMEM); + lcl_fm_ext = &fm_local->fm_extents[0]; + count_local = fiemap_size_to_count(buffer_size); + + fm_start = fiemap->fm_start; + fm_length = fiemap->fm_length; + /* Calculate start stripe, last stripe and length of mapping */ + start_stripe = lov_stripe_number(lsm, fm_start); + fm_end = (fm_length == ~0ULL) ? fmkey->oa.o_size : + fm_start + fm_length - 1; + /* If fm_length != ~0ULL but fm_start_fm_length-1 exceeds file size */ + if (fm_end > fmkey->oa.o_size) + fm_end = fmkey->oa.o_size; + + last_stripe = fiemap_calc_last_stripe(lsm, fm_start, fm_end, + start_stripe, &stripe_count); + fm_end_offset = fiemap_calc_fm_end_offset(fiemap, lsm, fm_start, fm_end, + &start_stripe); + if (fm_end_offset == -EINVAL) + GOTO(out, rc = -EINVAL); + + /** + * Requested extent count exceeds the fiemap buffer size, shrink our + * ambition. + */ + if (fiemap_count_to_size(fiemap->fm_extent_count) > *buflen) + fiemap->fm_extent_count = fiemap_size_to_count(*buflen); + if (fiemap->fm_extent_count == 0) + count_local = 0; + + /* Check each stripe */ + for (cur_stripe = start_stripe; stripe_count > 0; + --stripe_count, + cur_stripe = (cur_stripe + 1) % lsm->lsm_stripe_count) { + loff_t req_fm_len; /* Stores length of required mapping */ + loff_t len_mapped_single_call; + loff_t lun_start; + loff_t lun_end; + loff_t obd_object_end; + unsigned int ext_count; + + cur_stripe_wrap = cur_stripe; + + /* Find out range of mapping on this stripe */ + if ((lov_stripe_intersects(lsm, cur_stripe, fm_start, fm_end, + &lun_start, &obd_object_end)) == 0) + continue; + + if (lov_oinfo_is_dummy(lsm->lsm_oinfo[cur_stripe])) + GOTO(out, rc = -EIO); + + /* 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; + + /* find lobsub object */ + subobj = lov_find_subobj(env, cl2lov(obj), lsm, + cur_stripe); + if (IS_ERR(subobj)) + GOTO(out, rc = PTR_ERR(subobj)); + /* 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 = false; + ost_done = false; + do { + if (fiemap->fm_extent_count > 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 = enough ? 1 : count_local; + fm_local->fm_mapped_extents = 0; + fm_local->fm_flags = fiemap->fm_flags; + + ost_index = lsm->lsm_oinfo[cur_stripe]->loi_ost_idx; + + if (ost_index < 0 || + ost_index >= lov->desc.ld_tgt_count) + GOTO(obj_put, 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(&fmkey->fiemap, fm_local, sizeof(*fm_local)); + *buflen = fiemap_count_to_size( + fm_local->fm_extent_count); + + rc = cl_object_fiemap(env, subobj, fmkey, fm_local, + buflen); + if (rc != 0) + GOTO(obj_put, rc); +inactive_tgt: + ext_count = fm_local->fm_mapped_extents; + if (ext_count == 0) { + ost_done = true; + /* If last stripe has hold at the end, + * we need to return */ + if (cur_stripe_wrap == last_stripe) { + fiemap->fm_mapped_extents = 0; + goto finish; + } + break; + } else if (enough) { + /* + * We've collected enough extents and there are + * more extents after it. + */ + goto finish; + } + + /* If we just need num of extents, got to next device */ + if (fiemap->fm_extent_count == 0) { + current_extent += ext_count; + break; + } + + /* prepare to copy retrived map extents */ + 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 = true; + + /* Clear the EXTENT_LAST flag which can be present on + * the 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; + if (lov_stripe_size(lsm, + lcl_fm_ext[ext_count - 1].fe_logical + + lcl_fm_ext[ext_count - 1].fe_length, + cur_stripe) >= fmkey->oa.o_size) + ost_eof = true; + + 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) + enough = true; + } while (!ost_done && !ost_eof); + + cl_object_put(env, subobj); + subobj = NULL; + + if (cur_stripe_wrap == last_stripe) + goto finish; + } /* for each stripe */ +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 (fiemap->fm_extent_count == 0) + 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) && (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; +obj_put: + if (subobj != NULL) + cl_object_put(env, subobj); +out: + if (fm_local != NULL) + OBD_FREE_LARGE(fm_local, buffer_size); + lov_lsm_put(obj, lsm); + RETURN(rc); +} + static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj, struct lov_user_md __user *lum) { @@ -1006,14 +1476,15 @@ static int lov_object_find_cbdata(const struct lu_env *env, } static const struct cl_object_operations lov_ops = { - .coo_page_init = lov_page_init, - .coo_lock_init = lov_lock_init, - .coo_io_init = lov_io_init, - .coo_attr_get = lov_attr_get, - .coo_attr_update = lov_attr_update, - .coo_conf_set = lov_conf_set, - .coo_getstripe = lov_object_getstripe, - .coo_find_cbdata = lov_object_find_cbdata + .coo_page_init = lov_page_init, + .coo_lock_init = lov_lock_init, + .coo_io_init = lov_io_init, + .coo_attr_get = lov_attr_get, + .coo_attr_update = lov_attr_update, + .coo_conf_set = lov_conf_set, + .coo_getstripe = lov_object_getstripe, + .coo_find_cbdata = lov_object_find_cbdata, + .coo_fiemap = lov_object_fiemap, }; static const struct lu_object_operations lov_lu_obj_ops = { diff --git a/lustre/obdclass/cl_object.c b/lustre/obdclass/cl_object.c index ad3f5ea..59ce8de 100644 --- a/lustre/obdclass/cl_object.c +++ b/lustre/obdclass/cl_object.c @@ -386,6 +386,39 @@ int cl_object_find_cbdata(const struct lu_env *env, struct cl_object *obj, EXPORT_SYMBOL(cl_object_find_cbdata); /** + * Get fiemap extents from file object. + * + * \param env [in] lustre environment + * \param obj [in] file object + * \param key [in] fiemap request argument + * \param fiemap [out] fiemap extents mapping retrived + * \param buflen [in] max buffer length of @fiemap + * + * \retval 0 success + * \retval < 0 error + */ +int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *key, + struct fiemap *fiemap, size_t *buflen) +{ + struct lu_object_header *top; + int result = 0; + ENTRY; + + top = obj->co_lu.lo_header; + list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) { + if (obj->co_ops->coo_fiemap != NULL) { + result = obj->co_ops->coo_fiemap(env, obj, key, fiemap, + buflen); + if (result != 0) + break; + } + } + RETURN(result); +} +EXPORT_SYMBOL(cl_object_fiemap); + +/** * Helper function removing all object locks, and marking object for * deletion. All object pages must have been deleted at this point. * diff --git a/lustre/osc/osc_object.c b/lustre/osc/osc_object.c index c03582a..b3614f8 100644 --- a/lustre/osc/osc_object.c +++ b/lustre/osc/osc_object.c @@ -256,6 +256,91 @@ static int osc_object_find_cbdata(const struct lu_env *env, return rc; } +static int osc_object_fiemap(const struct lu_env *env, struct cl_object *obj, + struct ll_fiemap_info_key *fmkey, + struct fiemap *fiemap, size_t *buflen) +{ + struct obd_export *exp = osc_export(cl2osc(obj)); + struct ldlm_res_id resid; + ldlm_policy_data_t policy; + struct lustre_handle lockh; + ldlm_mode_t mode = 0; + struct ptlrpc_request *req; + struct fiemap *reply; + char *tmp; + int rc; + ENTRY; + + fmkey->oa.o_oi = cl2osc(obj)->oo_oinfo->loi_oi; + if (!(fmkey->fiemap.fm_flags & FIEMAP_FLAG_SYNC)) + goto skip_locking; + + policy.l_extent.start = fmkey->fiemap.fm_start & PAGE_CACHE_MASK; + + if (OBD_OBJECT_EOF - fmkey->fiemap.fm_length <= + fmkey->fiemap.fm_start + PAGE_CACHE_SIZE - 1) + policy.l_extent.end = OBD_OBJECT_EOF; + else + policy.l_extent.end = (fmkey->fiemap.fm_start + + fmkey->fiemap.fm_length + + PAGE_CACHE_SIZE - 1) & PAGE_CACHE_MASK; + + ostid_build_res_name(&fmkey->oa.o_oi, &resid); + mode = ldlm_lock_match(exp->exp_obd->obd_namespace, + LDLM_FL_BLOCK_GRANTED | LDLM_FL_LVB_READY, + &resid, LDLM_EXTENT, &policy, + LCK_PR | LCK_PW, &lockh, 0); + if (mode) { /* lock is cached on client */ + if (mode != LCK_PR) { + ldlm_lock_addref(&lockh, LCK_PR); + ldlm_lock_decref(&lockh, LCK_PW); + } + } else { /* no cached lock, needs acquire lock on server side */ + fmkey->oa.o_valid |= OBD_MD_FLFLAGS; + fmkey->oa.o_flags |= OBD_FL_SRVLOCK; + } + +skip_locking: + req = ptlrpc_request_alloc(class_exp2cliimp(exp), + &RQF_OST_GET_INFO_FIEMAP); + if (req == NULL) + GOTO(drop_lock, rc = -ENOMEM); + + req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_KEY, RCL_CLIENT, + sizeof(*fmkey)); + req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, RCL_CLIENT, + *buflen); + req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, RCL_SERVER, + *buflen); + + rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO); + if (rc != 0) { + ptlrpc_request_free(req); + GOTO(drop_lock, rc); + } + tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_KEY); + memcpy(tmp, fmkey, sizeof(*fmkey)); + tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_VAL); + memcpy(tmp, fiemap, *buflen); + ptlrpc_request_set_replen(req); + + rc = ptlrpc_queue_wait(req); + if (rc != 0) + GOTO(fini_req, rc); + + reply = req_capsule_server_get(&req->rq_pill, &RMF_FIEMAP_VAL); + if (reply == NULL) + GOTO(fini_req, rc = -EPROTO); + + memcpy(fiemap, reply, *buflen); +fini_req: + ptlrpc_req_finished(req); +drop_lock: + if (mode) + ldlm_lock_decref(&lockh, LCK_PR); + RETURN(rc); +} + void osc_object_set_contended(struct osc_object *obj) { obj->oo_contention_time = cfs_time_current(); @@ -295,14 +380,15 @@ int osc_object_is_contended(struct osc_object *obj) } static const struct cl_object_operations osc_ops = { - .coo_page_init = osc_page_init, - .coo_lock_init = osc_lock_init, - .coo_io_init = osc_io_init, - .coo_attr_get = osc_attr_get, - .coo_attr_update = osc_attr_update, - .coo_glimpse = osc_object_glimpse, - .coo_prune = osc_object_prune, - .coo_find_cbdata = osc_object_find_cbdata + .coo_page_init = osc_page_init, + .coo_lock_init = osc_lock_init, + .coo_io_init = osc_io_init, + .coo_attr_get = osc_attr_get, + .coo_attr_update = osc_attr_update, + .coo_glimpse = osc_object_glimpse, + .coo_prune = osc_object_prune, + .coo_find_cbdata = osc_object_find_cbdata, + .coo_fiemap = osc_object_fiemap, }; static const struct lu_object_operations osc_lu_obj_ops = { diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index 7ed4225..b64ad9a 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -2506,101 +2506,6 @@ out: return err; } -static int osc_get_info(const struct lu_env *env, struct obd_export *exp, - obd_count keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm) -{ - ENTRY; - if (!vallen || !val) - RETURN(-EFAULT); - - if (KEY_IS(KEY_FIEMAP)) { - struct ll_fiemap_info_key *fm_key = - (struct ll_fiemap_info_key *)key; - struct ldlm_res_id res_id; - ldlm_policy_data_t policy; - struct lustre_handle lockh; - ldlm_mode_t mode = 0; - struct ptlrpc_request *req; - struct ll_user_fiemap *reply; - char *tmp; - int rc; - - if (!(fm_key->fiemap.fm_flags & FIEMAP_FLAG_SYNC)) - goto skip_locking; - - policy.l_extent.start = fm_key->fiemap.fm_start & - CFS_PAGE_MASK; - - if (OBD_OBJECT_EOF - fm_key->fiemap.fm_length <= - fm_key->fiemap.fm_start + PAGE_CACHE_SIZE - 1) - policy.l_extent.end = OBD_OBJECT_EOF; - else - policy.l_extent.end = (fm_key->fiemap.fm_start + - fm_key->fiemap.fm_length + - PAGE_CACHE_SIZE - 1) & CFS_PAGE_MASK; - - ostid_build_res_name(&fm_key->oa.o_oi, &res_id); - mode = ldlm_lock_match(exp->exp_obd->obd_namespace, - LDLM_FL_BLOCK_GRANTED | - LDLM_FL_LVB_READY, - &res_id, LDLM_EXTENT, &policy, - LCK_PR | LCK_PW, &lockh, 0); - if (mode) { /* lock is cached on client */ - if (mode != LCK_PR) { - ldlm_lock_addref(&lockh, LCK_PR); - ldlm_lock_decref(&lockh, LCK_PW); - } - } else { /* no cached lock, needs acquire lock on server side */ - fm_key->oa.o_valid |= OBD_MD_FLFLAGS; - fm_key->oa.o_flags |= OBD_FL_SRVLOCK; - } - -skip_locking: - req = ptlrpc_request_alloc(class_exp2cliimp(exp), - &RQF_OST_GET_INFO_FIEMAP); - if (req == NULL) - GOTO(drop_lock, rc = -ENOMEM); - - req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_KEY, - RCL_CLIENT, keylen); - req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, - RCL_CLIENT, *vallen); - req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, - RCL_SERVER, *vallen); - - rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO); - if (rc) { - ptlrpc_request_free(req); - GOTO(drop_lock, rc); - } - - tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_KEY); - memcpy(tmp, key, keylen); - tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_VAL); - memcpy(tmp, val, *vallen); - - ptlrpc_request_set_replen(req); - rc = ptlrpc_queue_wait(req); - if (rc) - GOTO(fini_req, rc); - - reply = req_capsule_server_get(&req->rq_pill, &RMF_FIEMAP_VAL); - if (reply == NULL) - GOTO(fini_req, rc = -EPROTO); - - memcpy(val, reply, *vallen); -fini_req: - ptlrpc_req_finished(req); -drop_lock: - if (mode) - ldlm_lock_decref(&lockh, LCK_PR); - RETURN(rc); - } - - RETURN(-EINVAL); -} - static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp, obd_count keylen, void *key, obd_count vallen, void *val, struct ptlrpc_request_set *set) @@ -3073,7 +2978,6 @@ static struct obd_ops osc_obd_ops = { .o_setattr = osc_setattr, .o_setattr_async = osc_setattr_async, .o_iocontrol = osc_iocontrol, - .o_get_info = osc_get_info, .o_set_info_async = osc_set_info_async, .o_import_event = osc_import_event, .o_process_config = osc_process_config,