- RETURN(ll_lov_recreate_obj(inode, file, arg));
- case FSFILT_IOC_FIEMAP: {
- struct ll_user_fiemap *fiemap_s;
- size_t num_bytes, ret_bytes;
- unsigned int 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);
- num_bytes = sizeof(*fiemap_s) + (extent_count *
- sizeof(struct ll_fiemap_extent));
- OBD_VMALLOC(fiemap_s, num_bytes);
- if (fiemap_s == NULL)
- RETURN(-ENOMEM);
-
- if (cfs_copy_from_user(fiemap_s,
- (struct ll_user_fiemap __user *)arg,
- sizeof(*fiemap_s)))
- GOTO(error, rc = -EFAULT);
-
- if (fiemap_s->fm_flags & ~LUSTRE_FIEMAP_FLAGS_COMPAT) {
- fiemap_s->fm_flags = fiemap_s->fm_flags &
- ~LUSTRE_FIEMAP_FLAGS_COMPAT;
- if (cfs_copy_to_user((char *)arg, fiemap_s,
- sizeof(*fiemap_s)))
- GOTO(error, rc = -EFAULT);
-
- GOTO(error, rc = -EBADR);
- }
-
- /* 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 (cfs_copy_from_user(&fiemap_s->fm_extents[0],
- (char __user *)arg + sizeof(*fiemap_s),
- sizeof(struct ll_fiemap_extent)))
- GOTO(error, rc = -EFAULT);
- }
-
- if (fiemap_s->fm_flags & FIEMAP_FLAG_SYNC) {
- int rc;
-
- rc = filemap_fdatawrite(inode->i_mapping);
- if (rc)
- GOTO(error, rc);
- }
-
- rc = ll_do_fiemap(inode, fiemap_s, num_bytes);
- if (rc)
- GOTO(error, rc);
-
- ret_bytes = sizeof(struct ll_user_fiemap);
-
- if (extent_count != 0)
- ret_bytes += (fiemap_s->fm_mapped_extents *
- sizeof(struct ll_fiemap_extent));
-
- if (cfs_copy_to_user((void *)arg, fiemap_s, ret_bytes))
- rc = -EFAULT;
-
-error:
- OBD_VFREE(fiemap_s, num_bytes);
- RETURN(rc);
- }