xref: /kernel/linux/linux-5.10/fs/ocfs2/extent_map.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*-
38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0:
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * extent_map.c
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Block/Cluster mapping functions
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (C) 2004 Oracle.  All rights reserved.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/fs.h>
138c2ecf20Sopenharmony_ci#include <linux/init.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <linux/types.h>
168c2ecf20Sopenharmony_ci#include <linux/fiemap.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <cluster/masklog.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "ocfs2.h"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "alloc.h"
238c2ecf20Sopenharmony_ci#include "dlmglue.h"
248c2ecf20Sopenharmony_ci#include "extent_map.h"
258c2ecf20Sopenharmony_ci#include "inode.h"
268c2ecf20Sopenharmony_ci#include "super.h"
278c2ecf20Sopenharmony_ci#include "symlink.h"
288c2ecf20Sopenharmony_ci#include "aops.h"
298c2ecf20Sopenharmony_ci#include "ocfs2_trace.h"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include "buffer_head_io.h"
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/*
348c2ecf20Sopenharmony_ci * The extent caching implementation is intentionally trivial.
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci * We only cache a small number of extents stored directly on the
378c2ecf20Sopenharmony_ci * inode, so linear order operations are acceptable. If we ever want
388c2ecf20Sopenharmony_ci * to increase the size of the extent map, then these algorithms must
398c2ecf20Sopenharmony_ci * get smarter.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_civoid ocfs2_extent_map_init(struct inode *inode)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	oi->ip_extent_map.em_num_items = 0;
478c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&oi->ip_extent_map.em_list);
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic void __ocfs2_extent_map_lookup(struct ocfs2_extent_map *em,
518c2ecf20Sopenharmony_ci				      unsigned int cpos,
528c2ecf20Sopenharmony_ci				      struct ocfs2_extent_map_item **ret_emi)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	unsigned int range;
558c2ecf20Sopenharmony_ci	struct ocfs2_extent_map_item *emi;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	*ret_emi = NULL;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	list_for_each_entry(emi, &em->em_list, ei_list) {
608c2ecf20Sopenharmony_ci		range = emi->ei_cpos + emi->ei_clusters;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci		if (cpos >= emi->ei_cpos && cpos < range) {
638c2ecf20Sopenharmony_ci			list_move(&emi->ei_list, &em->em_list);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci			*ret_emi = emi;
668c2ecf20Sopenharmony_ci			break;
678c2ecf20Sopenharmony_ci		}
688c2ecf20Sopenharmony_ci	}
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic int ocfs2_extent_map_lookup(struct inode *inode, unsigned int cpos,
728c2ecf20Sopenharmony_ci				   unsigned int *phys, unsigned int *len,
738c2ecf20Sopenharmony_ci				   unsigned int *flags)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	unsigned int coff;
768c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
778c2ecf20Sopenharmony_ci	struct ocfs2_extent_map_item *emi;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	spin_lock(&oi->ip_lock);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	__ocfs2_extent_map_lookup(&oi->ip_extent_map, cpos, &emi);
828c2ecf20Sopenharmony_ci	if (emi) {
838c2ecf20Sopenharmony_ci		coff = cpos - emi->ei_cpos;
848c2ecf20Sopenharmony_ci		*phys = emi->ei_phys + coff;
858c2ecf20Sopenharmony_ci		if (len)
868c2ecf20Sopenharmony_ci			*len = emi->ei_clusters - coff;
878c2ecf20Sopenharmony_ci		if (flags)
888c2ecf20Sopenharmony_ci			*flags = emi->ei_flags;
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	spin_unlock(&oi->ip_lock);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (emi == NULL)
948c2ecf20Sopenharmony_ci		return -ENOENT;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	return 0;
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/*
1008c2ecf20Sopenharmony_ci * Forget about all clusters equal to or greater than cpos.
1018c2ecf20Sopenharmony_ci */
1028c2ecf20Sopenharmony_civoid ocfs2_extent_map_trunc(struct inode *inode, unsigned int cpos)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	struct ocfs2_extent_map_item *emi, *n;
1058c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
1068c2ecf20Sopenharmony_ci	struct ocfs2_extent_map *em = &oi->ip_extent_map;
1078c2ecf20Sopenharmony_ci	LIST_HEAD(tmp_list);
1088c2ecf20Sopenharmony_ci	unsigned int range;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	spin_lock(&oi->ip_lock);
1118c2ecf20Sopenharmony_ci	list_for_each_entry_safe(emi, n, &em->em_list, ei_list) {
1128c2ecf20Sopenharmony_ci		if (emi->ei_cpos >= cpos) {
1138c2ecf20Sopenharmony_ci			/* Full truncate of this record. */
1148c2ecf20Sopenharmony_ci			list_move(&emi->ei_list, &tmp_list);
1158c2ecf20Sopenharmony_ci			BUG_ON(em->em_num_items == 0);
1168c2ecf20Sopenharmony_ci			em->em_num_items--;
1178c2ecf20Sopenharmony_ci			continue;
1188c2ecf20Sopenharmony_ci		}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci		range = emi->ei_cpos + emi->ei_clusters;
1218c2ecf20Sopenharmony_ci		if (range > cpos) {
1228c2ecf20Sopenharmony_ci			/* Partial truncate */
1238c2ecf20Sopenharmony_ci			emi->ei_clusters = cpos - emi->ei_cpos;
1248c2ecf20Sopenharmony_ci		}
1258c2ecf20Sopenharmony_ci	}
1268c2ecf20Sopenharmony_ci	spin_unlock(&oi->ip_lock);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	list_for_each_entry_safe(emi, n, &tmp_list, ei_list) {
1298c2ecf20Sopenharmony_ci		list_del(&emi->ei_list);
1308c2ecf20Sopenharmony_ci		kfree(emi);
1318c2ecf20Sopenharmony_ci	}
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci/*
1358c2ecf20Sopenharmony_ci * Is any part of emi2 contained within emi1
1368c2ecf20Sopenharmony_ci */
1378c2ecf20Sopenharmony_cistatic int ocfs2_ei_is_contained(struct ocfs2_extent_map_item *emi1,
1388c2ecf20Sopenharmony_ci				 struct ocfs2_extent_map_item *emi2)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	unsigned int range1, range2;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	/*
1438c2ecf20Sopenharmony_ci	 * Check if logical start of emi2 is inside emi1
1448c2ecf20Sopenharmony_ci	 */
1458c2ecf20Sopenharmony_ci	range1 = emi1->ei_cpos + emi1->ei_clusters;
1468c2ecf20Sopenharmony_ci	if (emi2->ei_cpos >= emi1->ei_cpos && emi2->ei_cpos < range1)
1478c2ecf20Sopenharmony_ci		return 1;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	/*
1508c2ecf20Sopenharmony_ci	 * Check if logical end of emi2 is inside emi1
1518c2ecf20Sopenharmony_ci	 */
1528c2ecf20Sopenharmony_ci	range2 = emi2->ei_cpos + emi2->ei_clusters;
1538c2ecf20Sopenharmony_ci	if (range2 > emi1->ei_cpos && range2 <= range1)
1548c2ecf20Sopenharmony_ci		return 1;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	return 0;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic void ocfs2_copy_emi_fields(struct ocfs2_extent_map_item *dest,
1608c2ecf20Sopenharmony_ci				  struct ocfs2_extent_map_item *src)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	dest->ei_cpos = src->ei_cpos;
1638c2ecf20Sopenharmony_ci	dest->ei_phys = src->ei_phys;
1648c2ecf20Sopenharmony_ci	dest->ei_clusters = src->ei_clusters;
1658c2ecf20Sopenharmony_ci	dest->ei_flags = src->ei_flags;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci/*
1698c2ecf20Sopenharmony_ci * Try to merge emi with ins. Returns 1 if merge succeeds, zero
1708c2ecf20Sopenharmony_ci * otherwise.
1718c2ecf20Sopenharmony_ci */
1728c2ecf20Sopenharmony_cistatic int ocfs2_try_to_merge_extent_map(struct ocfs2_extent_map_item *emi,
1738c2ecf20Sopenharmony_ci					 struct ocfs2_extent_map_item *ins)
1748c2ecf20Sopenharmony_ci{
1758c2ecf20Sopenharmony_ci	/*
1768c2ecf20Sopenharmony_ci	 * Handle contiguousness
1778c2ecf20Sopenharmony_ci	 */
1788c2ecf20Sopenharmony_ci	if (ins->ei_phys == (emi->ei_phys + emi->ei_clusters) &&
1798c2ecf20Sopenharmony_ci	    ins->ei_cpos == (emi->ei_cpos + emi->ei_clusters) &&
1808c2ecf20Sopenharmony_ci	    ins->ei_flags == emi->ei_flags) {
1818c2ecf20Sopenharmony_ci		emi->ei_clusters += ins->ei_clusters;
1828c2ecf20Sopenharmony_ci		return 1;
1838c2ecf20Sopenharmony_ci	} else if ((ins->ei_phys + ins->ei_clusters) == emi->ei_phys &&
1848c2ecf20Sopenharmony_ci		   (ins->ei_cpos + ins->ei_clusters) == emi->ei_cpos &&
1858c2ecf20Sopenharmony_ci		   ins->ei_flags == emi->ei_flags) {
1868c2ecf20Sopenharmony_ci		emi->ei_phys = ins->ei_phys;
1878c2ecf20Sopenharmony_ci		emi->ei_cpos = ins->ei_cpos;
1888c2ecf20Sopenharmony_ci		emi->ei_clusters += ins->ei_clusters;
1898c2ecf20Sopenharmony_ci		return 1;
1908c2ecf20Sopenharmony_ci	}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	/*
1938c2ecf20Sopenharmony_ci	 * Overlapping extents - this shouldn't happen unless we've
1948c2ecf20Sopenharmony_ci	 * split an extent to change it's flags. That is exceedingly
1958c2ecf20Sopenharmony_ci	 * rare, so there's no sense in trying to optimize it yet.
1968c2ecf20Sopenharmony_ci	 */
1978c2ecf20Sopenharmony_ci	if (ocfs2_ei_is_contained(emi, ins) ||
1988c2ecf20Sopenharmony_ci	    ocfs2_ei_is_contained(ins, emi)) {
1998c2ecf20Sopenharmony_ci		ocfs2_copy_emi_fields(emi, ins);
2008c2ecf20Sopenharmony_ci		return 1;
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	/* No merge was possible. */
2048c2ecf20Sopenharmony_ci	return 0;
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci/*
2088c2ecf20Sopenharmony_ci * In order to reduce complexity on the caller, this insert function
2098c2ecf20Sopenharmony_ci * is intentionally liberal in what it will accept.
2108c2ecf20Sopenharmony_ci *
2118c2ecf20Sopenharmony_ci * The only rule is that the truncate call *must* be used whenever
2128c2ecf20Sopenharmony_ci * records have been deleted. This avoids inserting overlapping
2138c2ecf20Sopenharmony_ci * records with different physical mappings.
2148c2ecf20Sopenharmony_ci */
2158c2ecf20Sopenharmony_civoid ocfs2_extent_map_insert_rec(struct inode *inode,
2168c2ecf20Sopenharmony_ci				 struct ocfs2_extent_rec *rec)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
2198c2ecf20Sopenharmony_ci	struct ocfs2_extent_map *em = &oi->ip_extent_map;
2208c2ecf20Sopenharmony_ci	struct ocfs2_extent_map_item *emi, *new_emi = NULL;
2218c2ecf20Sopenharmony_ci	struct ocfs2_extent_map_item ins;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	ins.ei_cpos = le32_to_cpu(rec->e_cpos);
2248c2ecf20Sopenharmony_ci	ins.ei_phys = ocfs2_blocks_to_clusters(inode->i_sb,
2258c2ecf20Sopenharmony_ci					       le64_to_cpu(rec->e_blkno));
2268c2ecf20Sopenharmony_ci	ins.ei_clusters = le16_to_cpu(rec->e_leaf_clusters);
2278c2ecf20Sopenharmony_ci	ins.ei_flags = rec->e_flags;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cisearch:
2308c2ecf20Sopenharmony_ci	spin_lock(&oi->ip_lock);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	list_for_each_entry(emi, &em->em_list, ei_list) {
2338c2ecf20Sopenharmony_ci		if (ocfs2_try_to_merge_extent_map(emi, &ins)) {
2348c2ecf20Sopenharmony_ci			list_move(&emi->ei_list, &em->em_list);
2358c2ecf20Sopenharmony_ci			spin_unlock(&oi->ip_lock);
2368c2ecf20Sopenharmony_ci			goto out;
2378c2ecf20Sopenharmony_ci		}
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	/*
2418c2ecf20Sopenharmony_ci	 * No item could be merged.
2428c2ecf20Sopenharmony_ci	 *
2438c2ecf20Sopenharmony_ci	 * Either allocate and add a new item, or overwrite the last recently
2448c2ecf20Sopenharmony_ci	 * inserted.
2458c2ecf20Sopenharmony_ci	 */
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (em->em_num_items < OCFS2_MAX_EXTENT_MAP_ITEMS) {
2488c2ecf20Sopenharmony_ci		if (new_emi == NULL) {
2498c2ecf20Sopenharmony_ci			spin_unlock(&oi->ip_lock);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci			new_emi = kmalloc(sizeof(*new_emi), GFP_NOFS);
2528c2ecf20Sopenharmony_ci			if (new_emi == NULL)
2538c2ecf20Sopenharmony_ci				goto out;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci			goto search;
2568c2ecf20Sopenharmony_ci		}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci		ocfs2_copy_emi_fields(new_emi, &ins);
2598c2ecf20Sopenharmony_ci		list_add(&new_emi->ei_list, &em->em_list);
2608c2ecf20Sopenharmony_ci		em->em_num_items++;
2618c2ecf20Sopenharmony_ci		new_emi = NULL;
2628c2ecf20Sopenharmony_ci	} else {
2638c2ecf20Sopenharmony_ci		BUG_ON(list_empty(&em->em_list) || em->em_num_items == 0);
2648c2ecf20Sopenharmony_ci		emi = list_entry(em->em_list.prev,
2658c2ecf20Sopenharmony_ci				 struct ocfs2_extent_map_item, ei_list);
2668c2ecf20Sopenharmony_ci		list_move(&emi->ei_list, &em->em_list);
2678c2ecf20Sopenharmony_ci		ocfs2_copy_emi_fields(emi, &ins);
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	spin_unlock(&oi->ip_lock);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ciout:
2738c2ecf20Sopenharmony_ci	kfree(new_emi);
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_cistatic int ocfs2_last_eb_is_empty(struct inode *inode,
2778c2ecf20Sopenharmony_ci				  struct ocfs2_dinode *di)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	int ret, next_free;
2808c2ecf20Sopenharmony_ci	u64 last_eb_blk = le64_to_cpu(di->i_last_eb_blk);
2818c2ecf20Sopenharmony_ci	struct buffer_head *eb_bh = NULL;
2828c2ecf20Sopenharmony_ci	struct ocfs2_extent_block *eb;
2838c2ecf20Sopenharmony_ci	struct ocfs2_extent_list *el;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	ret = ocfs2_read_extent_block(INODE_CACHE(inode), last_eb_blk, &eb_bh);
2868c2ecf20Sopenharmony_ci	if (ret) {
2878c2ecf20Sopenharmony_ci		mlog_errno(ret);
2888c2ecf20Sopenharmony_ci		goto out;
2898c2ecf20Sopenharmony_ci	}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	eb = (struct ocfs2_extent_block *) eb_bh->b_data;
2928c2ecf20Sopenharmony_ci	el = &eb->h_list;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (el->l_tree_depth) {
2958c2ecf20Sopenharmony_ci		ocfs2_error(inode->i_sb,
2968c2ecf20Sopenharmony_ci			    "Inode %lu has non zero tree depth in leaf block %llu\n",
2978c2ecf20Sopenharmony_ci			    inode->i_ino,
2988c2ecf20Sopenharmony_ci			    (unsigned long long)eb_bh->b_blocknr);
2998c2ecf20Sopenharmony_ci		ret = -EROFS;
3008c2ecf20Sopenharmony_ci		goto out;
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	next_free = le16_to_cpu(el->l_next_free_rec);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	if (next_free == 0 ||
3068c2ecf20Sopenharmony_ci	    (next_free == 1 && ocfs2_is_empty_extent(&el->l_recs[0])))
3078c2ecf20Sopenharmony_ci		ret = 1;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ciout:
3108c2ecf20Sopenharmony_ci	brelse(eb_bh);
3118c2ecf20Sopenharmony_ci	return ret;
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci/*
3158c2ecf20Sopenharmony_ci * Return the 1st index within el which contains an extent start
3168c2ecf20Sopenharmony_ci * larger than v_cluster.
3178c2ecf20Sopenharmony_ci */
3188c2ecf20Sopenharmony_cistatic int ocfs2_search_for_hole_index(struct ocfs2_extent_list *el,
3198c2ecf20Sopenharmony_ci				       u32 v_cluster)
3208c2ecf20Sopenharmony_ci{
3218c2ecf20Sopenharmony_ci	int i;
3228c2ecf20Sopenharmony_ci	struct ocfs2_extent_rec *rec;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
3258c2ecf20Sopenharmony_ci		rec = &el->l_recs[i];
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci		if (v_cluster < le32_to_cpu(rec->e_cpos))
3288c2ecf20Sopenharmony_ci			break;
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	return i;
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci/*
3358c2ecf20Sopenharmony_ci * Figure out the size of a hole which starts at v_cluster within the given
3368c2ecf20Sopenharmony_ci * extent list.
3378c2ecf20Sopenharmony_ci *
3388c2ecf20Sopenharmony_ci * If there is no more allocation past v_cluster, we return the maximum
3398c2ecf20Sopenharmony_ci * cluster size minus v_cluster.
3408c2ecf20Sopenharmony_ci *
3418c2ecf20Sopenharmony_ci * If we have in-inode extents, then el points to the dinode list and
3428c2ecf20Sopenharmony_ci * eb_bh is NULL. Otherwise, eb_bh should point to the extent block
3438c2ecf20Sopenharmony_ci * containing el.
3448c2ecf20Sopenharmony_ci */
3458c2ecf20Sopenharmony_ciint ocfs2_figure_hole_clusters(struct ocfs2_caching_info *ci,
3468c2ecf20Sopenharmony_ci			       struct ocfs2_extent_list *el,
3478c2ecf20Sopenharmony_ci			       struct buffer_head *eb_bh,
3488c2ecf20Sopenharmony_ci			       u32 v_cluster,
3498c2ecf20Sopenharmony_ci			       u32 *num_clusters)
3508c2ecf20Sopenharmony_ci{
3518c2ecf20Sopenharmony_ci	int ret, i;
3528c2ecf20Sopenharmony_ci	struct buffer_head *next_eb_bh = NULL;
3538c2ecf20Sopenharmony_ci	struct ocfs2_extent_block *eb, *next_eb;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	i = ocfs2_search_for_hole_index(el, v_cluster);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	if (i == le16_to_cpu(el->l_next_free_rec) && eb_bh) {
3588c2ecf20Sopenharmony_ci		eb = (struct ocfs2_extent_block *)eb_bh->b_data;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci		/*
3618c2ecf20Sopenharmony_ci		 * Check the next leaf for any extents.
3628c2ecf20Sopenharmony_ci		 */
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci		if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
3658c2ecf20Sopenharmony_ci			goto no_more_extents;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci		ret = ocfs2_read_extent_block(ci,
3688c2ecf20Sopenharmony_ci					      le64_to_cpu(eb->h_next_leaf_blk),
3698c2ecf20Sopenharmony_ci					      &next_eb_bh);
3708c2ecf20Sopenharmony_ci		if (ret) {
3718c2ecf20Sopenharmony_ci			mlog_errno(ret);
3728c2ecf20Sopenharmony_ci			goto out;
3738c2ecf20Sopenharmony_ci		}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci		next_eb = (struct ocfs2_extent_block *)next_eb_bh->b_data;
3768c2ecf20Sopenharmony_ci		el = &next_eb->h_list;
3778c2ecf20Sopenharmony_ci		i = ocfs2_search_for_hole_index(el, v_cluster);
3788c2ecf20Sopenharmony_ci	}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_cino_more_extents:
3818c2ecf20Sopenharmony_ci	if (i == le16_to_cpu(el->l_next_free_rec)) {
3828c2ecf20Sopenharmony_ci		/*
3838c2ecf20Sopenharmony_ci		 * We're at the end of our existing allocation. Just
3848c2ecf20Sopenharmony_ci		 * return the maximum number of clusters we could
3858c2ecf20Sopenharmony_ci		 * possibly allocate.
3868c2ecf20Sopenharmony_ci		 */
3878c2ecf20Sopenharmony_ci		*num_clusters = UINT_MAX - v_cluster;
3888c2ecf20Sopenharmony_ci	} else {
3898c2ecf20Sopenharmony_ci		*num_clusters = le32_to_cpu(el->l_recs[i].e_cpos) - v_cluster;
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	ret = 0;
3938c2ecf20Sopenharmony_ciout:
3948c2ecf20Sopenharmony_ci	brelse(next_eb_bh);
3958c2ecf20Sopenharmony_ci	return ret;
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic int ocfs2_get_clusters_nocache(struct inode *inode,
3998c2ecf20Sopenharmony_ci				      struct buffer_head *di_bh,
4008c2ecf20Sopenharmony_ci				      u32 v_cluster, unsigned int *hole_len,
4018c2ecf20Sopenharmony_ci				      struct ocfs2_extent_rec *ret_rec,
4028c2ecf20Sopenharmony_ci				      unsigned int *is_last)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	int i, ret, tree_height, len;
4058c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di;
4068c2ecf20Sopenharmony_ci	struct ocfs2_extent_block *eb;
4078c2ecf20Sopenharmony_ci	struct ocfs2_extent_list *el;
4088c2ecf20Sopenharmony_ci	struct ocfs2_extent_rec *rec;
4098c2ecf20Sopenharmony_ci	struct buffer_head *eb_bh = NULL;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	memset(ret_rec, 0, sizeof(*ret_rec));
4128c2ecf20Sopenharmony_ci	if (is_last)
4138c2ecf20Sopenharmony_ci		*is_last = 0;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *) di_bh->b_data;
4168c2ecf20Sopenharmony_ci	el = &di->id2.i_list;
4178c2ecf20Sopenharmony_ci	tree_height = le16_to_cpu(el->l_tree_depth);
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if (tree_height > 0) {
4208c2ecf20Sopenharmony_ci		ret = ocfs2_find_leaf(INODE_CACHE(inode), el, v_cluster,
4218c2ecf20Sopenharmony_ci				      &eb_bh);
4228c2ecf20Sopenharmony_ci		if (ret) {
4238c2ecf20Sopenharmony_ci			mlog_errno(ret);
4248c2ecf20Sopenharmony_ci			goto out;
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci		eb = (struct ocfs2_extent_block *) eb_bh->b_data;
4288c2ecf20Sopenharmony_ci		el = &eb->h_list;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci		if (el->l_tree_depth) {
4318c2ecf20Sopenharmony_ci			ocfs2_error(inode->i_sb,
4328c2ecf20Sopenharmony_ci				    "Inode %lu has non zero tree depth in leaf block %llu\n",
4338c2ecf20Sopenharmony_ci				    inode->i_ino,
4348c2ecf20Sopenharmony_ci				    (unsigned long long)eb_bh->b_blocknr);
4358c2ecf20Sopenharmony_ci			ret = -EROFS;
4368c2ecf20Sopenharmony_ci			goto out;
4378c2ecf20Sopenharmony_ci		}
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	i = ocfs2_search_extent_list(el, v_cluster);
4418c2ecf20Sopenharmony_ci	if (i == -1) {
4428c2ecf20Sopenharmony_ci		/*
4438c2ecf20Sopenharmony_ci		 * Holes can be larger than the maximum size of an
4448c2ecf20Sopenharmony_ci		 * extent, so we return their lengths in a separate
4458c2ecf20Sopenharmony_ci		 * field.
4468c2ecf20Sopenharmony_ci		 */
4478c2ecf20Sopenharmony_ci		if (hole_len) {
4488c2ecf20Sopenharmony_ci			ret = ocfs2_figure_hole_clusters(INODE_CACHE(inode),
4498c2ecf20Sopenharmony_ci							 el, eb_bh,
4508c2ecf20Sopenharmony_ci							 v_cluster, &len);
4518c2ecf20Sopenharmony_ci			if (ret) {
4528c2ecf20Sopenharmony_ci				mlog_errno(ret);
4538c2ecf20Sopenharmony_ci				goto out;
4548c2ecf20Sopenharmony_ci			}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci			*hole_len = len;
4578c2ecf20Sopenharmony_ci		}
4588c2ecf20Sopenharmony_ci		goto out_hole;
4598c2ecf20Sopenharmony_ci	}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	rec = &el->l_recs[i];
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos));
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	if (!rec->e_blkno) {
4668c2ecf20Sopenharmony_ci		ocfs2_error(inode->i_sb,
4678c2ecf20Sopenharmony_ci			    "Inode %lu has bad extent record (%u, %u, 0)\n",
4688c2ecf20Sopenharmony_ci			    inode->i_ino,
4698c2ecf20Sopenharmony_ci			    le32_to_cpu(rec->e_cpos),
4708c2ecf20Sopenharmony_ci			    ocfs2_rec_clusters(el, rec));
4718c2ecf20Sopenharmony_ci		ret = -EROFS;
4728c2ecf20Sopenharmony_ci		goto out;
4738c2ecf20Sopenharmony_ci	}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	*ret_rec = *rec;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	/*
4788c2ecf20Sopenharmony_ci	 * Checking for last extent is potentially expensive - we
4798c2ecf20Sopenharmony_ci	 * might have to look at the next leaf over to see if it's
4808c2ecf20Sopenharmony_ci	 * empty.
4818c2ecf20Sopenharmony_ci	 *
4828c2ecf20Sopenharmony_ci	 * The first two checks are to see whether the caller even
4838c2ecf20Sopenharmony_ci	 * cares for this information, and if the extent is at least
4848c2ecf20Sopenharmony_ci	 * the last in it's list.
4858c2ecf20Sopenharmony_ci	 *
4868c2ecf20Sopenharmony_ci	 * If those hold true, then the extent is last if any of the
4878c2ecf20Sopenharmony_ci	 * additional conditions hold true:
4888c2ecf20Sopenharmony_ci	 *  - Extent list is in-inode
4898c2ecf20Sopenharmony_ci	 *  - Extent list is right-most
4908c2ecf20Sopenharmony_ci	 *  - Extent list is 2nd to rightmost, with empty right-most
4918c2ecf20Sopenharmony_ci	 */
4928c2ecf20Sopenharmony_ci	if (is_last) {
4938c2ecf20Sopenharmony_ci		if (i == (le16_to_cpu(el->l_next_free_rec) - 1)) {
4948c2ecf20Sopenharmony_ci			if (tree_height == 0)
4958c2ecf20Sopenharmony_ci				*is_last = 1;
4968c2ecf20Sopenharmony_ci			else if (eb->h_blkno == di->i_last_eb_blk)
4978c2ecf20Sopenharmony_ci				*is_last = 1;
4988c2ecf20Sopenharmony_ci			else if (eb->h_next_leaf_blk == di->i_last_eb_blk) {
4998c2ecf20Sopenharmony_ci				ret = ocfs2_last_eb_is_empty(inode, di);
5008c2ecf20Sopenharmony_ci				if (ret < 0) {
5018c2ecf20Sopenharmony_ci					mlog_errno(ret);
5028c2ecf20Sopenharmony_ci					goto out;
5038c2ecf20Sopenharmony_ci				}
5048c2ecf20Sopenharmony_ci				if (ret == 1)
5058c2ecf20Sopenharmony_ci					*is_last = 1;
5068c2ecf20Sopenharmony_ci			}
5078c2ecf20Sopenharmony_ci		}
5088c2ecf20Sopenharmony_ci	}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ciout_hole:
5118c2ecf20Sopenharmony_ci	ret = 0;
5128c2ecf20Sopenharmony_ciout:
5138c2ecf20Sopenharmony_ci	brelse(eb_bh);
5148c2ecf20Sopenharmony_ci	return ret;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic void ocfs2_relative_extent_offsets(struct super_block *sb,
5188c2ecf20Sopenharmony_ci					  u32 v_cluster,
5198c2ecf20Sopenharmony_ci					  struct ocfs2_extent_rec *rec,
5208c2ecf20Sopenharmony_ci					  u32 *p_cluster, u32 *num_clusters)
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci{
5238c2ecf20Sopenharmony_ci	u32 coff = v_cluster - le32_to_cpu(rec->e_cpos);
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	*p_cluster = ocfs2_blocks_to_clusters(sb, le64_to_cpu(rec->e_blkno));
5268c2ecf20Sopenharmony_ci	*p_cluster = *p_cluster + coff;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	if (num_clusters)
5298c2ecf20Sopenharmony_ci		*num_clusters = le16_to_cpu(rec->e_leaf_clusters) - coff;
5308c2ecf20Sopenharmony_ci}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ciint ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
5338c2ecf20Sopenharmony_ci			     u32 *p_cluster, u32 *num_clusters,
5348c2ecf20Sopenharmony_ci			     struct ocfs2_extent_list *el,
5358c2ecf20Sopenharmony_ci			     unsigned int *extent_flags)
5368c2ecf20Sopenharmony_ci{
5378c2ecf20Sopenharmony_ci	int ret = 0, i;
5388c2ecf20Sopenharmony_ci	struct buffer_head *eb_bh = NULL;
5398c2ecf20Sopenharmony_ci	struct ocfs2_extent_block *eb;
5408c2ecf20Sopenharmony_ci	struct ocfs2_extent_rec *rec;
5418c2ecf20Sopenharmony_ci	u32 coff;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (el->l_tree_depth) {
5448c2ecf20Sopenharmony_ci		ret = ocfs2_find_leaf(INODE_CACHE(inode), el, v_cluster,
5458c2ecf20Sopenharmony_ci				      &eb_bh);
5468c2ecf20Sopenharmony_ci		if (ret) {
5478c2ecf20Sopenharmony_ci			mlog_errno(ret);
5488c2ecf20Sopenharmony_ci			goto out;
5498c2ecf20Sopenharmony_ci		}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci		eb = (struct ocfs2_extent_block *) eb_bh->b_data;
5528c2ecf20Sopenharmony_ci		el = &eb->h_list;
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci		if (el->l_tree_depth) {
5558c2ecf20Sopenharmony_ci			ocfs2_error(inode->i_sb,
5568c2ecf20Sopenharmony_ci				    "Inode %lu has non zero tree depth in xattr leaf block %llu\n",
5578c2ecf20Sopenharmony_ci				    inode->i_ino,
5588c2ecf20Sopenharmony_ci				    (unsigned long long)eb_bh->b_blocknr);
5598c2ecf20Sopenharmony_ci			ret = -EROFS;
5608c2ecf20Sopenharmony_ci			goto out;
5618c2ecf20Sopenharmony_ci		}
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	i = ocfs2_search_extent_list(el, v_cluster);
5658c2ecf20Sopenharmony_ci	if (i == -1) {
5668c2ecf20Sopenharmony_ci		ret = -EROFS;
5678c2ecf20Sopenharmony_ci		mlog_errno(ret);
5688c2ecf20Sopenharmony_ci		goto out;
5698c2ecf20Sopenharmony_ci	} else {
5708c2ecf20Sopenharmony_ci		rec = &el->l_recs[i];
5718c2ecf20Sopenharmony_ci		BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos));
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci		if (!rec->e_blkno) {
5748c2ecf20Sopenharmony_ci			ocfs2_error(inode->i_sb,
5758c2ecf20Sopenharmony_ci				    "Inode %lu has bad extent record (%u, %u, 0) in xattr\n",
5768c2ecf20Sopenharmony_ci				    inode->i_ino,
5778c2ecf20Sopenharmony_ci				    le32_to_cpu(rec->e_cpos),
5788c2ecf20Sopenharmony_ci				    ocfs2_rec_clusters(el, rec));
5798c2ecf20Sopenharmony_ci			ret = -EROFS;
5808c2ecf20Sopenharmony_ci			goto out;
5818c2ecf20Sopenharmony_ci		}
5828c2ecf20Sopenharmony_ci		coff = v_cluster - le32_to_cpu(rec->e_cpos);
5838c2ecf20Sopenharmony_ci		*p_cluster = ocfs2_blocks_to_clusters(inode->i_sb,
5848c2ecf20Sopenharmony_ci						    le64_to_cpu(rec->e_blkno));
5858c2ecf20Sopenharmony_ci		*p_cluster = *p_cluster + coff;
5868c2ecf20Sopenharmony_ci		if (num_clusters)
5878c2ecf20Sopenharmony_ci			*num_clusters = ocfs2_rec_clusters(el, rec) - coff;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci		if (extent_flags)
5908c2ecf20Sopenharmony_ci			*extent_flags = rec->e_flags;
5918c2ecf20Sopenharmony_ci	}
5928c2ecf20Sopenharmony_ciout:
5938c2ecf20Sopenharmony_ci	brelse(eb_bh);
5948c2ecf20Sopenharmony_ci	return ret;
5958c2ecf20Sopenharmony_ci}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ciint ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
5988c2ecf20Sopenharmony_ci		       u32 *p_cluster, u32 *num_clusters,
5998c2ecf20Sopenharmony_ci		       unsigned int *extent_flags)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	int ret;
6028c2ecf20Sopenharmony_ci	unsigned int hole_len, flags = 0;
6038c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
6048c2ecf20Sopenharmony_ci	struct ocfs2_extent_rec rec;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
6078c2ecf20Sopenharmony_ci		ret = -ERANGE;
6088c2ecf20Sopenharmony_ci		mlog_errno(ret);
6098c2ecf20Sopenharmony_ci		goto out;
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	ret = ocfs2_extent_map_lookup(inode, v_cluster, p_cluster,
6138c2ecf20Sopenharmony_ci				      num_clusters, extent_flags);
6148c2ecf20Sopenharmony_ci	if (ret == 0)
6158c2ecf20Sopenharmony_ci		goto out;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	ret = ocfs2_read_inode_block(inode, &di_bh);
6188c2ecf20Sopenharmony_ci	if (ret) {
6198c2ecf20Sopenharmony_ci		mlog_errno(ret);
6208c2ecf20Sopenharmony_ci		goto out;
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	ret = ocfs2_get_clusters_nocache(inode, di_bh, v_cluster, &hole_len,
6248c2ecf20Sopenharmony_ci					 &rec, NULL);
6258c2ecf20Sopenharmony_ci	if (ret) {
6268c2ecf20Sopenharmony_ci		mlog_errno(ret);
6278c2ecf20Sopenharmony_ci		goto out;
6288c2ecf20Sopenharmony_ci	}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	if (rec.e_blkno == 0ULL) {
6318c2ecf20Sopenharmony_ci		/*
6328c2ecf20Sopenharmony_ci		 * A hole was found. Return some canned values that
6338c2ecf20Sopenharmony_ci		 * callers can key on. If asked for, num_clusters will
6348c2ecf20Sopenharmony_ci		 * be populated with the size of the hole.
6358c2ecf20Sopenharmony_ci		 */
6368c2ecf20Sopenharmony_ci		*p_cluster = 0;
6378c2ecf20Sopenharmony_ci		if (num_clusters) {
6388c2ecf20Sopenharmony_ci			*num_clusters = hole_len;
6398c2ecf20Sopenharmony_ci		}
6408c2ecf20Sopenharmony_ci	} else {
6418c2ecf20Sopenharmony_ci		ocfs2_relative_extent_offsets(inode->i_sb, v_cluster, &rec,
6428c2ecf20Sopenharmony_ci					      p_cluster, num_clusters);
6438c2ecf20Sopenharmony_ci		flags = rec.e_flags;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci		ocfs2_extent_map_insert_rec(inode, &rec);
6468c2ecf20Sopenharmony_ci	}
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	if (extent_flags)
6498c2ecf20Sopenharmony_ci		*extent_flags = flags;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ciout:
6528c2ecf20Sopenharmony_ci	brelse(di_bh);
6538c2ecf20Sopenharmony_ci	return ret;
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci/*
6578c2ecf20Sopenharmony_ci * This expects alloc_sem to be held. The allocation cannot change at
6588c2ecf20Sopenharmony_ci * all while the map is in the process of being updated.
6598c2ecf20Sopenharmony_ci */
6608c2ecf20Sopenharmony_ciint ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
6618c2ecf20Sopenharmony_ci				u64 *ret_count, unsigned int *extent_flags)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	int ret;
6648c2ecf20Sopenharmony_ci	int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
6658c2ecf20Sopenharmony_ci	u32 cpos, num_clusters, p_cluster;
6668c2ecf20Sopenharmony_ci	u64 boff = 0;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	cpos = ocfs2_blocks_to_clusters(inode->i_sb, v_blkno);
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	ret = ocfs2_get_clusters(inode, cpos, &p_cluster, &num_clusters,
6718c2ecf20Sopenharmony_ci				 extent_flags);
6728c2ecf20Sopenharmony_ci	if (ret) {
6738c2ecf20Sopenharmony_ci		mlog_errno(ret);
6748c2ecf20Sopenharmony_ci		goto out;
6758c2ecf20Sopenharmony_ci	}
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	/*
6788c2ecf20Sopenharmony_ci	 * p_cluster == 0 indicates a hole.
6798c2ecf20Sopenharmony_ci	 */
6808c2ecf20Sopenharmony_ci	if (p_cluster) {
6818c2ecf20Sopenharmony_ci		boff = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster);
6828c2ecf20Sopenharmony_ci		boff += (v_blkno & (u64)(bpc - 1));
6838c2ecf20Sopenharmony_ci	}
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	*p_blkno = boff;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	if (ret_count) {
6888c2ecf20Sopenharmony_ci		*ret_count = ocfs2_clusters_to_blocks(inode->i_sb, num_clusters);
6898c2ecf20Sopenharmony_ci		*ret_count -= v_blkno & (u64)(bpc - 1);
6908c2ecf20Sopenharmony_ci	}
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ciout:
6938c2ecf20Sopenharmony_ci	return ret;
6948c2ecf20Sopenharmony_ci}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci/*
6978c2ecf20Sopenharmony_ci * The ocfs2_fiemap_inline() may be a little bit misleading, since
6988c2ecf20Sopenharmony_ci * it not only handles the fiemap for inlined files, but also deals
6998c2ecf20Sopenharmony_ci * with the fast symlink, cause they have no difference for extent
7008c2ecf20Sopenharmony_ci * mapping per se.
7018c2ecf20Sopenharmony_ci */
7028c2ecf20Sopenharmony_cistatic int ocfs2_fiemap_inline(struct inode *inode, struct buffer_head *di_bh,
7038c2ecf20Sopenharmony_ci			       struct fiemap_extent_info *fieinfo,
7048c2ecf20Sopenharmony_ci			       u64 map_start)
7058c2ecf20Sopenharmony_ci{
7068c2ecf20Sopenharmony_ci	int ret;
7078c2ecf20Sopenharmony_ci	unsigned int id_count;
7088c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di;
7098c2ecf20Sopenharmony_ci	u64 phys;
7108c2ecf20Sopenharmony_ci	u32 flags = FIEMAP_EXTENT_DATA_INLINE|FIEMAP_EXTENT_LAST;
7118c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
7148c2ecf20Sopenharmony_ci	if (ocfs2_inode_is_fast_symlink(inode))
7158c2ecf20Sopenharmony_ci		id_count = ocfs2_fast_symlink_chars(inode->i_sb);
7168c2ecf20Sopenharmony_ci	else
7178c2ecf20Sopenharmony_ci		id_count = le16_to_cpu(di->id2.i_data.id_count);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	if (map_start < id_count) {
7208c2ecf20Sopenharmony_ci		phys = oi->ip_blkno << inode->i_sb->s_blocksize_bits;
7218c2ecf20Sopenharmony_ci		if (ocfs2_inode_is_fast_symlink(inode))
7228c2ecf20Sopenharmony_ci			phys += offsetof(struct ocfs2_dinode, id2.i_symlink);
7238c2ecf20Sopenharmony_ci		else
7248c2ecf20Sopenharmony_ci			phys += offsetof(struct ocfs2_dinode,
7258c2ecf20Sopenharmony_ci					 id2.i_data.id_data);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci		ret = fiemap_fill_next_extent(fieinfo, 0, phys, id_count,
7288c2ecf20Sopenharmony_ci					      flags);
7298c2ecf20Sopenharmony_ci		if (ret < 0)
7308c2ecf20Sopenharmony_ci			return ret;
7318c2ecf20Sopenharmony_ci	}
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	return 0;
7348c2ecf20Sopenharmony_ci}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ciint ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
7378c2ecf20Sopenharmony_ci		 u64 map_start, u64 map_len)
7388c2ecf20Sopenharmony_ci{
7398c2ecf20Sopenharmony_ci	int ret, is_last;
7408c2ecf20Sopenharmony_ci	u32 mapping_end, cpos;
7418c2ecf20Sopenharmony_ci	unsigned int hole_size;
7428c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
7438c2ecf20Sopenharmony_ci	u64 len_bytes, phys_bytes, virt_bytes;
7448c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
7458c2ecf20Sopenharmony_ci	struct ocfs2_extent_rec rec;
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	ret = fiemap_prep(inode, fieinfo, map_start, &map_len, 0);
7488c2ecf20Sopenharmony_ci	if (ret)
7498c2ecf20Sopenharmony_ci		return ret;
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	ret = ocfs2_inode_lock(inode, &di_bh, 0);
7528c2ecf20Sopenharmony_ci	if (ret) {
7538c2ecf20Sopenharmony_ci		mlog_errno(ret);
7548c2ecf20Sopenharmony_ci		goto out;
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	down_read(&OCFS2_I(inode)->ip_alloc_sem);
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	/*
7608c2ecf20Sopenharmony_ci	 * Handle inline-data and fast symlink separately.
7618c2ecf20Sopenharmony_ci	 */
7628c2ecf20Sopenharmony_ci	if ((OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) ||
7638c2ecf20Sopenharmony_ci	    ocfs2_inode_is_fast_symlink(inode)) {
7648c2ecf20Sopenharmony_ci		ret = ocfs2_fiemap_inline(inode, di_bh, fieinfo, map_start);
7658c2ecf20Sopenharmony_ci		goto out_unlock;
7668c2ecf20Sopenharmony_ci	}
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	cpos = map_start >> osb->s_clustersize_bits;
7698c2ecf20Sopenharmony_ci	mapping_end = ocfs2_clusters_for_bytes(inode->i_sb,
7708c2ecf20Sopenharmony_ci					       map_start + map_len);
7718c2ecf20Sopenharmony_ci	is_last = 0;
7728c2ecf20Sopenharmony_ci	while (cpos < mapping_end && !is_last) {
7738c2ecf20Sopenharmony_ci		u32 fe_flags;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci		ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos,
7768c2ecf20Sopenharmony_ci						 &hole_size, &rec, &is_last);
7778c2ecf20Sopenharmony_ci		if (ret) {
7788c2ecf20Sopenharmony_ci			mlog_errno(ret);
7798c2ecf20Sopenharmony_ci			goto out_unlock;
7808c2ecf20Sopenharmony_ci		}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci		if (rec.e_blkno == 0ULL) {
7838c2ecf20Sopenharmony_ci			cpos += hole_size;
7848c2ecf20Sopenharmony_ci			continue;
7858c2ecf20Sopenharmony_ci		}
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci		fe_flags = 0;
7888c2ecf20Sopenharmony_ci		if (rec.e_flags & OCFS2_EXT_UNWRITTEN)
7898c2ecf20Sopenharmony_ci			fe_flags |= FIEMAP_EXTENT_UNWRITTEN;
7908c2ecf20Sopenharmony_ci		if (rec.e_flags & OCFS2_EXT_REFCOUNTED)
7918c2ecf20Sopenharmony_ci			fe_flags |= FIEMAP_EXTENT_SHARED;
7928c2ecf20Sopenharmony_ci		if (is_last)
7938c2ecf20Sopenharmony_ci			fe_flags |= FIEMAP_EXTENT_LAST;
7948c2ecf20Sopenharmony_ci		len_bytes = (u64)le16_to_cpu(rec.e_leaf_clusters) << osb->s_clustersize_bits;
7958c2ecf20Sopenharmony_ci		phys_bytes = le64_to_cpu(rec.e_blkno) << osb->sb->s_blocksize_bits;
7968c2ecf20Sopenharmony_ci		virt_bytes = (u64)le32_to_cpu(rec.e_cpos) << osb->s_clustersize_bits;
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci		ret = fiemap_fill_next_extent(fieinfo, virt_bytes, phys_bytes,
7998c2ecf20Sopenharmony_ci					      len_bytes, fe_flags);
8008c2ecf20Sopenharmony_ci		if (ret)
8018c2ecf20Sopenharmony_ci			break;
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci		cpos = le32_to_cpu(rec.e_cpos)+ le16_to_cpu(rec.e_leaf_clusters);
8048c2ecf20Sopenharmony_ci	}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	if (ret > 0)
8078c2ecf20Sopenharmony_ci		ret = 0;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ciout_unlock:
8108c2ecf20Sopenharmony_ci	brelse(di_bh);
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	up_read(&OCFS2_I(inode)->ip_alloc_sem);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	ocfs2_inode_unlock(inode, 0);
8158c2ecf20Sopenharmony_ciout:
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	return ret;
8188c2ecf20Sopenharmony_ci}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci/* Is IO overwriting allocated blocks? */
8218c2ecf20Sopenharmony_ciint ocfs2_overwrite_io(struct inode *inode, struct buffer_head *di_bh,
8228c2ecf20Sopenharmony_ci		       u64 map_start, u64 map_len)
8238c2ecf20Sopenharmony_ci{
8248c2ecf20Sopenharmony_ci	int ret = 0, is_last;
8258c2ecf20Sopenharmony_ci	u32 mapping_end, cpos;
8268c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
8278c2ecf20Sopenharmony_ci	struct ocfs2_extent_rec rec;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
8308c2ecf20Sopenharmony_ci		if (ocfs2_size_fits_inline_data(di_bh, map_start + map_len))
8318c2ecf20Sopenharmony_ci			return ret;
8328c2ecf20Sopenharmony_ci		else
8338c2ecf20Sopenharmony_ci			return -EAGAIN;
8348c2ecf20Sopenharmony_ci	}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	cpos = map_start >> osb->s_clustersize_bits;
8378c2ecf20Sopenharmony_ci	mapping_end = ocfs2_clusters_for_bytes(inode->i_sb,
8388c2ecf20Sopenharmony_ci					       map_start + map_len);
8398c2ecf20Sopenharmony_ci	is_last = 0;
8408c2ecf20Sopenharmony_ci	while (cpos < mapping_end && !is_last) {
8418c2ecf20Sopenharmony_ci		ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos,
8428c2ecf20Sopenharmony_ci						 NULL, &rec, &is_last);
8438c2ecf20Sopenharmony_ci		if (ret) {
8448c2ecf20Sopenharmony_ci			mlog_errno(ret);
8458c2ecf20Sopenharmony_ci			goto out;
8468c2ecf20Sopenharmony_ci		}
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci		if (rec.e_blkno == 0ULL)
8498c2ecf20Sopenharmony_ci			break;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci		if (rec.e_flags & OCFS2_EXT_REFCOUNTED)
8528c2ecf20Sopenharmony_ci			break;
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci		cpos = le32_to_cpu(rec.e_cpos) +
8558c2ecf20Sopenharmony_ci			le16_to_cpu(rec.e_leaf_clusters);
8568c2ecf20Sopenharmony_ci	}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	if (cpos < mapping_end)
8598c2ecf20Sopenharmony_ci		ret = -EAGAIN;
8608c2ecf20Sopenharmony_ciout:
8618c2ecf20Sopenharmony_ci	return ret;
8628c2ecf20Sopenharmony_ci}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ciint ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int whence)
8658c2ecf20Sopenharmony_ci{
8668c2ecf20Sopenharmony_ci	struct inode *inode = file->f_mapping->host;
8678c2ecf20Sopenharmony_ci	int ret;
8688c2ecf20Sopenharmony_ci	unsigned int is_last = 0, is_data = 0;
8698c2ecf20Sopenharmony_ci	u16 cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits;
8708c2ecf20Sopenharmony_ci	u32 cpos, cend, clen, hole_size;
8718c2ecf20Sopenharmony_ci	u64 extoff, extlen;
8728c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
8738c2ecf20Sopenharmony_ci	struct ocfs2_extent_rec rec;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	BUG_ON(whence != SEEK_DATA && whence != SEEK_HOLE);
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	ret = ocfs2_inode_lock(inode, &di_bh, 0);
8788c2ecf20Sopenharmony_ci	if (ret) {
8798c2ecf20Sopenharmony_ci		mlog_errno(ret);
8808c2ecf20Sopenharmony_ci		goto out;
8818c2ecf20Sopenharmony_ci	}
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	down_read(&OCFS2_I(inode)->ip_alloc_sem);
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	if (*offset >= i_size_read(inode)) {
8868c2ecf20Sopenharmony_ci		ret = -ENXIO;
8878c2ecf20Sopenharmony_ci		goto out_unlock;
8888c2ecf20Sopenharmony_ci	}
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
8918c2ecf20Sopenharmony_ci		if (whence == SEEK_HOLE)
8928c2ecf20Sopenharmony_ci			*offset = i_size_read(inode);
8938c2ecf20Sopenharmony_ci		goto out_unlock;
8948c2ecf20Sopenharmony_ci	}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	clen = 0;
8978c2ecf20Sopenharmony_ci	cpos = *offset >> cs_bits;
8988c2ecf20Sopenharmony_ci	cend = ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	while (cpos < cend && !is_last) {
9018c2ecf20Sopenharmony_ci		ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos, &hole_size,
9028c2ecf20Sopenharmony_ci						 &rec, &is_last);
9038c2ecf20Sopenharmony_ci		if (ret) {
9048c2ecf20Sopenharmony_ci			mlog_errno(ret);
9058c2ecf20Sopenharmony_ci			goto out_unlock;
9068c2ecf20Sopenharmony_ci		}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci		extoff = cpos;
9098c2ecf20Sopenharmony_ci		extoff <<= cs_bits;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci		if (rec.e_blkno == 0ULL) {
9128c2ecf20Sopenharmony_ci			clen = hole_size;
9138c2ecf20Sopenharmony_ci			is_data = 0;
9148c2ecf20Sopenharmony_ci		} else {
9158c2ecf20Sopenharmony_ci			clen = le16_to_cpu(rec.e_leaf_clusters) -
9168c2ecf20Sopenharmony_ci				(cpos - le32_to_cpu(rec.e_cpos));
9178c2ecf20Sopenharmony_ci			is_data = (rec.e_flags & OCFS2_EXT_UNWRITTEN) ?  0 : 1;
9188c2ecf20Sopenharmony_ci		}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci		if ((!is_data && whence == SEEK_HOLE) ||
9218c2ecf20Sopenharmony_ci		    (is_data && whence == SEEK_DATA)) {
9228c2ecf20Sopenharmony_ci			if (extoff > *offset)
9238c2ecf20Sopenharmony_ci				*offset = extoff;
9248c2ecf20Sopenharmony_ci			goto out_unlock;
9258c2ecf20Sopenharmony_ci		}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci		if (!is_last)
9288c2ecf20Sopenharmony_ci			cpos += clen;
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	if (whence == SEEK_HOLE) {
9328c2ecf20Sopenharmony_ci		extoff = cpos;
9338c2ecf20Sopenharmony_ci		extoff <<= cs_bits;
9348c2ecf20Sopenharmony_ci		extlen = clen;
9358c2ecf20Sopenharmony_ci		extlen <<=  cs_bits;
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci		if ((extoff + extlen) > i_size_read(inode))
9388c2ecf20Sopenharmony_ci			extlen = i_size_read(inode) - extoff;
9398c2ecf20Sopenharmony_ci		extoff += extlen;
9408c2ecf20Sopenharmony_ci		if (extoff > *offset)
9418c2ecf20Sopenharmony_ci			*offset = extoff;
9428c2ecf20Sopenharmony_ci		goto out_unlock;
9438c2ecf20Sopenharmony_ci	}
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	ret = -ENXIO;
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ciout_unlock:
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	brelse(di_bh);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	up_read(&OCFS2_I(inode)->ip_alloc_sem);
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	ocfs2_inode_unlock(inode, 0);
9548c2ecf20Sopenharmony_ciout:
9558c2ecf20Sopenharmony_ci	return ret;
9568c2ecf20Sopenharmony_ci}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ciint ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
9598c2ecf20Sopenharmony_ci			   struct buffer_head *bhs[], int flags,
9608c2ecf20Sopenharmony_ci			   int (*validate)(struct super_block *sb,
9618c2ecf20Sopenharmony_ci					   struct buffer_head *bh))
9628c2ecf20Sopenharmony_ci{
9638c2ecf20Sopenharmony_ci	int rc = 0;
9648c2ecf20Sopenharmony_ci	u64 p_block, p_count;
9658c2ecf20Sopenharmony_ci	int i, count, done = 0;
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	trace_ocfs2_read_virt_blocks(
9688c2ecf20Sopenharmony_ci	     inode, (unsigned long long)v_block, nr, bhs, flags,
9698c2ecf20Sopenharmony_ci	     validate);
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	if (((v_block + nr - 1) << inode->i_sb->s_blocksize_bits) >=
9728c2ecf20Sopenharmony_ci	    i_size_read(inode)) {
9738c2ecf20Sopenharmony_ci		BUG_ON(!(flags & OCFS2_BH_READAHEAD));
9748c2ecf20Sopenharmony_ci		goto out;
9758c2ecf20Sopenharmony_ci	}
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci	while (done < nr) {
9788c2ecf20Sopenharmony_ci		down_read(&OCFS2_I(inode)->ip_alloc_sem);
9798c2ecf20Sopenharmony_ci		rc = ocfs2_extent_map_get_blocks(inode, v_block + done,
9808c2ecf20Sopenharmony_ci						 &p_block, &p_count, NULL);
9818c2ecf20Sopenharmony_ci		up_read(&OCFS2_I(inode)->ip_alloc_sem);
9828c2ecf20Sopenharmony_ci		if (rc) {
9838c2ecf20Sopenharmony_ci			mlog_errno(rc);
9848c2ecf20Sopenharmony_ci			break;
9858c2ecf20Sopenharmony_ci		}
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci		if (!p_block) {
9888c2ecf20Sopenharmony_ci			rc = -EIO;
9898c2ecf20Sopenharmony_ci			mlog(ML_ERROR,
9908c2ecf20Sopenharmony_ci			     "Inode #%llu contains a hole at offset %llu\n",
9918c2ecf20Sopenharmony_ci			     (unsigned long long)OCFS2_I(inode)->ip_blkno,
9928c2ecf20Sopenharmony_ci			     (unsigned long long)(v_block + done) <<
9938c2ecf20Sopenharmony_ci			     inode->i_sb->s_blocksize_bits);
9948c2ecf20Sopenharmony_ci			break;
9958c2ecf20Sopenharmony_ci		}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci		count = nr - done;
9988c2ecf20Sopenharmony_ci		if (p_count < count)
9998c2ecf20Sopenharmony_ci			count = p_count;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci		/*
10028c2ecf20Sopenharmony_ci		 * If the caller passed us bhs, they should have come
10038c2ecf20Sopenharmony_ci		 * from a previous readahead call to this function.  Thus,
10048c2ecf20Sopenharmony_ci		 * they should have the right b_blocknr.
10058c2ecf20Sopenharmony_ci		 */
10068c2ecf20Sopenharmony_ci		for (i = 0; i < count; i++) {
10078c2ecf20Sopenharmony_ci			if (!bhs[done + i])
10088c2ecf20Sopenharmony_ci				continue;
10098c2ecf20Sopenharmony_ci			BUG_ON(bhs[done + i]->b_blocknr != (p_block + i));
10108c2ecf20Sopenharmony_ci		}
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci		rc = ocfs2_read_blocks(INODE_CACHE(inode), p_block, count,
10138c2ecf20Sopenharmony_ci				       bhs + done, flags, validate);
10148c2ecf20Sopenharmony_ci		if (rc) {
10158c2ecf20Sopenharmony_ci			mlog_errno(rc);
10168c2ecf20Sopenharmony_ci			break;
10178c2ecf20Sopenharmony_ci		}
10188c2ecf20Sopenharmony_ci		done += count;
10198c2ecf20Sopenharmony_ci	}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ciout:
10228c2ecf20Sopenharmony_ci	return rc;
10238c2ecf20Sopenharmony_ci}
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci
1026