+struct locked_region {
+ cfs_list_t list;
+ struct lustre_handle lh;
+};
+
+static int lock_region(struct obd_export *exp, struct obdo *oa,
+ unsigned long long begin, unsigned long long end,
+ cfs_list_t *locked)
+{
+ struct locked_region *region = NULL;
+ int rc;
+
+ LASSERT(begin <= end);
+ OBD_ALLOC_PTR(region);
+ if (region == NULL)
+ return -ENOMEM;
+
+ rc = ost_lock_get(exp, oa, begin, end - begin, ®ion->lh, LCK_PR, 0);
+ if (rc) {
+ OBD_FREE_PTR(region);
+ return rc;
+ }
+
+ CDEBUG(D_OTHER, "ost lock [%llu,%llu], lh=%p\n",
+ begin, end, ®ion->lh);
+ cfs_list_add(®ion->list, locked);
+
+ return 0;
+}
+
+static int lock_zero_regions(struct obd_export *exp, struct obdo *oa,
+ struct ll_user_fiemap *fiemap,
+ cfs_list_t *locked)
+{
+ __u64 begin = fiemap->fm_start;
+ unsigned int i;
+ int rc = 0;
+ struct ll_fiemap_extent *fiemap_start = fiemap->fm_extents;
+ ENTRY;
+
+ CDEBUG(D_OTHER, "extents count %u\n", fiemap->fm_mapped_extents);
+ for (i = 0; i < fiemap->fm_mapped_extents; i++) {
+ if (fiemap_start[i].fe_logical > begin) {
+ CDEBUG(D_OTHER, "ost lock [%llu,%llu]\n",
+ begin, fiemap_start[i].fe_logical);
+ rc = lock_region(exp, oa, begin,
+ fiemap_start[i].fe_logical, locked);
+ if (rc)
+ RETURN(rc);
+ }
+
+ begin = fiemap_start[i].fe_logical + fiemap_start[i].fe_length;
+ }
+
+ if (begin < (fiemap->fm_start + fiemap->fm_length)) {
+ CDEBUG(D_OTHER, "ost lock [%llu,%llu]\n",
+ begin, fiemap->fm_start + fiemap->fm_length);
+ rc = lock_region(exp, oa, begin,
+ fiemap->fm_start + fiemap->fm_length, locked);
+ }
+
+ RETURN(rc);
+}
+
+static void unlock_zero_regions(struct obd_export *exp, cfs_list_t *locked)
+{
+ struct locked_region *entry, *temp;
+ cfs_list_for_each_entry_safe(entry, temp, locked, list) {
+ CDEBUG(D_OTHER, "ost unlock lh=%p\n", &entry->lh);
+ ost_lock_put(exp, &entry->lh, LCK_PR);
+ cfs_list_del(&entry->list);
+ OBD_FREE_PTR(entry);
+ }
+}
+