xref: /openbmc/linux/fs/nilfs2/direct.c (revision f69e8139)
1ae98043fSRyusuke Konishi // SPDX-License-Identifier: GPL-2.0+
236a580ebSKoji Sato /*
394ee1d91SRyusuke Konishi  * NILFS direct block pointer.
436a580ebSKoji Sato  *
536a580ebSKoji Sato  * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
636a580ebSKoji Sato  *
74b420ab4SRyusuke Konishi  * Written by Koji Sato.
836a580ebSKoji Sato  */
936a580ebSKoji Sato 
1036a580ebSKoji Sato #include <linux/errno.h>
1136a580ebSKoji Sato #include "nilfs.h"
1236a580ebSKoji Sato #include "page.h"
1336a580ebSKoji Sato #include "direct.h"
1436a580ebSKoji Sato #include "alloc.h"
15c3a7abf0SRyusuke Konishi #include "dat.h"
1636a580ebSKoji Sato 
nilfs_direct_dptrs(const struct nilfs_bmap * direct)1710ff885bSRyusuke Konishi static inline __le64 *nilfs_direct_dptrs(const struct nilfs_bmap *direct)
1836a580ebSKoji Sato {
1936a580ebSKoji Sato 	return (__le64 *)
2010ff885bSRyusuke Konishi 		((struct nilfs_direct_node *)direct->b_u.u_data + 1);
2136a580ebSKoji Sato }
2236a580ebSKoji Sato 
2336a580ebSKoji Sato static inline __u64
nilfs_direct_get_ptr(const struct nilfs_bmap * direct,__u64 key)2410ff885bSRyusuke Konishi nilfs_direct_get_ptr(const struct nilfs_bmap *direct, __u64 key)
2536a580ebSKoji Sato {
2625b8d7deSRyusuke Konishi 	return le64_to_cpu(*(nilfs_direct_dptrs(direct) + key));
2736a580ebSKoji Sato }
2836a580ebSKoji Sato 
nilfs_direct_set_ptr(struct nilfs_bmap * direct,__u64 key,__u64 ptr)2910ff885bSRyusuke Konishi static inline void nilfs_direct_set_ptr(struct nilfs_bmap *direct,
3036a580ebSKoji Sato 					__u64 key, __u64 ptr)
3136a580ebSKoji Sato {
3225b8d7deSRyusuke Konishi 	*(nilfs_direct_dptrs(direct) + key) = cpu_to_le64(ptr);
3336a580ebSKoji Sato }
3436a580ebSKoji Sato 
nilfs_direct_lookup(const struct nilfs_bmap * direct,__u64 key,int level,__u64 * ptrp)3510ff885bSRyusuke Konishi static int nilfs_direct_lookup(const struct nilfs_bmap *direct,
3636a580ebSKoji Sato 			       __u64 key, int level, __u64 *ptrp)
3736a580ebSKoji Sato {
3836a580ebSKoji Sato 	__u64 ptr;
3936a580ebSKoji Sato 
405ee58148SJiro SEKIBA 	if (key > NILFS_DIRECT_KEY_MAX || level != 1)
415ee58148SJiro SEKIBA 		return -ENOENT;
425ee58148SJiro SEKIBA 	ptr = nilfs_direct_get_ptr(direct, key);
435ee58148SJiro SEKIBA 	if (ptr == NILFS_BMAP_INVALID_PTR)
4436a580ebSKoji Sato 		return -ENOENT;
4536a580ebSKoji Sato 
4636a580ebSKoji Sato 	*ptrp = ptr;
4736a580ebSKoji Sato 	return 0;
4836a580ebSKoji Sato }
4936a580ebSKoji Sato 
nilfs_direct_lookup_contig(const struct nilfs_bmap * direct,__u64 key,__u64 * ptrp,unsigned int maxblocks)5010ff885bSRyusuke Konishi static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
51c3a7abf0SRyusuke Konishi 				      __u64 key, __u64 *ptrp,
520c6c44cbSRyusuke Konishi 				      unsigned int maxblocks)
53c3a7abf0SRyusuke Konishi {
54c3a7abf0SRyusuke Konishi 	struct inode *dat = NULL;
55c3a7abf0SRyusuke Konishi 	__u64 ptr, ptr2;
56c3a7abf0SRyusuke Konishi 	sector_t blocknr;
57c3a7abf0SRyusuke Konishi 	int ret, cnt;
58c3a7abf0SRyusuke Konishi 
595ee58148SJiro SEKIBA 	if (key > NILFS_DIRECT_KEY_MAX)
605ee58148SJiro SEKIBA 		return -ENOENT;
615ee58148SJiro SEKIBA 	ptr = nilfs_direct_get_ptr(direct, key);
625ee58148SJiro SEKIBA 	if (ptr == NILFS_BMAP_INVALID_PTR)
63c3a7abf0SRyusuke Konishi 		return -ENOENT;
64c3a7abf0SRyusuke Konishi 
6510ff885bSRyusuke Konishi 	if (NILFS_BMAP_USE_VBN(direct)) {
6610ff885bSRyusuke Konishi 		dat = nilfs_bmap_get_dat(direct);
67c3a7abf0SRyusuke Konishi 		ret = nilfs_dat_translate(dat, ptr, &blocknr);
68c3a7abf0SRyusuke Konishi 		if (ret < 0)
69f69e8139SRyusuke Konishi 			goto dat_error;
70c3a7abf0SRyusuke Konishi 		ptr = blocknr;
71c3a7abf0SRyusuke Konishi 	}
72c3a7abf0SRyusuke Konishi 
730c6c44cbSRyusuke Konishi 	maxblocks = min_t(unsigned int, maxblocks,
740c6c44cbSRyusuke Konishi 			  NILFS_DIRECT_KEY_MAX - key + 1);
75c3a7abf0SRyusuke Konishi 	for (cnt = 1; cnt < maxblocks &&
76c3a7abf0SRyusuke Konishi 		     (ptr2 = nilfs_direct_get_ptr(direct, key + cnt)) !=
77c3a7abf0SRyusuke Konishi 		     NILFS_BMAP_INVALID_PTR;
78c3a7abf0SRyusuke Konishi 	     cnt++) {
79c3a7abf0SRyusuke Konishi 		if (dat) {
80c3a7abf0SRyusuke Konishi 			ret = nilfs_dat_translate(dat, ptr2, &blocknr);
81c3a7abf0SRyusuke Konishi 			if (ret < 0)
82f69e8139SRyusuke Konishi 				goto dat_error;
83c3a7abf0SRyusuke Konishi 			ptr2 = blocknr;
84c3a7abf0SRyusuke Konishi 		}
85c3a7abf0SRyusuke Konishi 		if (ptr2 != ptr + cnt)
86c3a7abf0SRyusuke Konishi 			break;
87c3a7abf0SRyusuke Konishi 	}
88c3a7abf0SRyusuke Konishi 	*ptrp = ptr;
89c3a7abf0SRyusuke Konishi 	return cnt;
90f69e8139SRyusuke Konishi 
91f69e8139SRyusuke Konishi  dat_error:
92f69e8139SRyusuke Konishi 	if (ret == -ENOENT)
93f69e8139SRyusuke Konishi 		ret = -EINVAL;  /* Notify bmap layer of metadata corruption */
94f69e8139SRyusuke Konishi 	return ret;
95c3a7abf0SRyusuke Konishi }
96c3a7abf0SRyusuke Konishi 
9736a580ebSKoji Sato static __u64
nilfs_direct_find_target_v(const struct nilfs_bmap * direct,__u64 key)9810ff885bSRyusuke Konishi nilfs_direct_find_target_v(const struct nilfs_bmap *direct, __u64 key)
9936a580ebSKoji Sato {
10036a580ebSKoji Sato 	__u64 ptr;
10136a580ebSKoji Sato 
10210ff885bSRyusuke Konishi 	ptr = nilfs_bmap_find_target_seq(direct, key);
10336a580ebSKoji Sato 	if (ptr != NILFS_BMAP_INVALID_PTR)
10436a580ebSKoji Sato 		/* sequential access */
10536a580ebSKoji Sato 		return ptr;
1067f00184eSRyusuke Konishi 
10736a580ebSKoji Sato 	/* block group */
10810ff885bSRyusuke Konishi 	return nilfs_bmap_find_target_in_group(direct);
10936a580ebSKoji Sato }
11036a580ebSKoji Sato 
nilfs_direct_insert(struct nilfs_bmap * bmap,__u64 key,__u64 ptr)11136a580ebSKoji Sato static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
11236a580ebSKoji Sato {
11336a580ebSKoji Sato 	union nilfs_bmap_ptr_req req;
1142e0c2c73SRyusuke Konishi 	struct inode *dat = NULL;
1152e0c2c73SRyusuke Konishi 	struct buffer_head *bh;
11636a580ebSKoji Sato 	int ret;
11736a580ebSKoji Sato 
11836a580ebSKoji Sato 	if (key > NILFS_DIRECT_KEY_MAX)
11936a580ebSKoji Sato 		return -ENOENT;
12010ff885bSRyusuke Konishi 	if (nilfs_direct_get_ptr(bmap, key) != NILFS_BMAP_INVALID_PTR)
12136a580ebSKoji Sato 		return -EEXIST;
12236a580ebSKoji Sato 
1232e0c2c73SRyusuke Konishi 	if (NILFS_BMAP_USE_VBN(bmap)) {
12410ff885bSRyusuke Konishi 		req.bpr_ptr = nilfs_direct_find_target_v(bmap, key);
1252e0c2c73SRyusuke Konishi 		dat = nilfs_bmap_get_dat(bmap);
12636a580ebSKoji Sato 	}
1272e0c2c73SRyusuke Konishi 	ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat);
1282e0c2c73SRyusuke Konishi 	if (!ret) {
1292e0c2c73SRyusuke Konishi 		/* ptr must be a pointer to a buffer head. */
1302e0c2c73SRyusuke Konishi 		bh = (struct buffer_head *)((unsigned long)ptr);
1312e0c2c73SRyusuke Konishi 		set_buffer_nilfs_volatile(bh);
13236a580ebSKoji Sato 
1332e0c2c73SRyusuke Konishi 		nilfs_bmap_commit_alloc_ptr(bmap, &req, dat);
13410ff885bSRyusuke Konishi 		nilfs_direct_set_ptr(bmap, key, req.bpr_ptr);
13536a580ebSKoji Sato 
1362e0c2c73SRyusuke Konishi 		if (!nilfs_bmap_dirty(bmap))
1372e0c2c73SRyusuke Konishi 			nilfs_bmap_set_dirty(bmap);
1382e0c2c73SRyusuke Konishi 
1392e0c2c73SRyusuke Konishi 		if (NILFS_BMAP_USE_VBN(bmap))
140dc935be2SRyusuke Konishi 			nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr);
1412e0c2c73SRyusuke Konishi 
142be667377SRyusuke Konishi 		nilfs_inode_add_blocks(bmap->b_inode, 1);
14336a580ebSKoji Sato 	}
1442e0c2c73SRyusuke Konishi 	return ret;
14536a580ebSKoji Sato }
14636a580ebSKoji Sato 
nilfs_direct_delete(struct nilfs_bmap * bmap,__u64 key)14736a580ebSKoji Sato static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
14836a580ebSKoji Sato {
14936a580ebSKoji Sato 	union nilfs_bmap_ptr_req req;
1502e0c2c73SRyusuke Konishi 	struct inode *dat;
15136a580ebSKoji Sato 	int ret;
15236a580ebSKoji Sato 
1532e0c2c73SRyusuke Konishi 	if (key > NILFS_DIRECT_KEY_MAX ||
15410ff885bSRyusuke Konishi 	    nilfs_direct_get_ptr(bmap, key) == NILFS_BMAP_INVALID_PTR)
15536a580ebSKoji Sato 		return -ENOENT;
15636a580ebSKoji Sato 
1572e0c2c73SRyusuke Konishi 	dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
15810ff885bSRyusuke Konishi 	req.bpr_ptr = nilfs_direct_get_ptr(bmap, key);
15936a580ebSKoji Sato 
1602e0c2c73SRyusuke Konishi 	ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat);
1612e0c2c73SRyusuke Konishi 	if (!ret) {
1622e0c2c73SRyusuke Konishi 		nilfs_bmap_commit_end_ptr(bmap, &req, dat);
16310ff885bSRyusuke Konishi 		nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR);
164be667377SRyusuke Konishi 		nilfs_inode_sub_blocks(bmap->b_inode, 1);
1652e0c2c73SRyusuke Konishi 	}
1662e0c2c73SRyusuke Konishi 	return ret;
16736a580ebSKoji Sato }
16836a580ebSKoji Sato 
nilfs_direct_seek_key(const struct nilfs_bmap * direct,__u64 start,__u64 * keyp)1695b20384fSRyusuke Konishi static int nilfs_direct_seek_key(const struct nilfs_bmap *direct, __u64 start,
1705b20384fSRyusuke Konishi 				 __u64 *keyp)
1715b20384fSRyusuke Konishi {
1725b20384fSRyusuke Konishi 	__u64 key;
1735b20384fSRyusuke Konishi 
1745b20384fSRyusuke Konishi 	for (key = start; key <= NILFS_DIRECT_KEY_MAX; key++) {
1755b20384fSRyusuke Konishi 		if (nilfs_direct_get_ptr(direct, key) !=
1765b20384fSRyusuke Konishi 		    NILFS_BMAP_INVALID_PTR) {
1775b20384fSRyusuke Konishi 			*keyp = key;
1785b20384fSRyusuke Konishi 			return 0;
1795b20384fSRyusuke Konishi 		}
1805b20384fSRyusuke Konishi 	}
1815b20384fSRyusuke Konishi 	return -ENOENT;
1825b20384fSRyusuke Konishi }
1835b20384fSRyusuke Konishi 
nilfs_direct_last_key(const struct nilfs_bmap * direct,__u64 * keyp)18410ff885bSRyusuke Konishi static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp)
18536a580ebSKoji Sato {
18636a580ebSKoji Sato 	__u64 key, lastkey;
18736a580ebSKoji Sato 
18836a580ebSKoji Sato 	lastkey = NILFS_DIRECT_KEY_MAX + 1;
18936a580ebSKoji Sato 	for (key = NILFS_DIRECT_KEY_MIN; key <= NILFS_DIRECT_KEY_MAX; key++)
19036a580ebSKoji Sato 		if (nilfs_direct_get_ptr(direct, key) !=
19136a580ebSKoji Sato 		    NILFS_BMAP_INVALID_PTR)
19236a580ebSKoji Sato 			lastkey = key;
19336a580ebSKoji Sato 
19436a580ebSKoji Sato 	if (lastkey == NILFS_DIRECT_KEY_MAX + 1)
19536a580ebSKoji Sato 		return -ENOENT;
19636a580ebSKoji Sato 
19736a580ebSKoji Sato 	*keyp = lastkey;
19836a580ebSKoji Sato 
19936a580ebSKoji Sato 	return 0;
20036a580ebSKoji Sato }
20136a580ebSKoji Sato 
nilfs_direct_check_insert(const struct nilfs_bmap * bmap,__u64 key)20236a580ebSKoji Sato static int nilfs_direct_check_insert(const struct nilfs_bmap *bmap, __u64 key)
20336a580ebSKoji Sato {
20436a580ebSKoji Sato 	return key > NILFS_DIRECT_KEY_MAX;
20536a580ebSKoji Sato }
20636a580ebSKoji Sato 
nilfs_direct_gather_data(struct nilfs_bmap * direct,__u64 * keys,__u64 * ptrs,int nitems)20710ff885bSRyusuke Konishi static int nilfs_direct_gather_data(struct nilfs_bmap *direct,
20836a580ebSKoji Sato 				    __u64 *keys, __u64 *ptrs, int nitems)
20936a580ebSKoji Sato {
21036a580ebSKoji Sato 	__u64 key;
21136a580ebSKoji Sato 	__u64 ptr;
21236a580ebSKoji Sato 	int n;
21336a580ebSKoji Sato 
21436a580ebSKoji Sato 	if (nitems > NILFS_DIRECT_NBLOCKS)
21536a580ebSKoji Sato 		nitems = NILFS_DIRECT_NBLOCKS;
21636a580ebSKoji Sato 	n = 0;
21736a580ebSKoji Sato 	for (key = 0; key < nitems; key++) {
21836a580ebSKoji Sato 		ptr = nilfs_direct_get_ptr(direct, key);
21936a580ebSKoji Sato 		if (ptr != NILFS_BMAP_INVALID_PTR) {
22036a580ebSKoji Sato 			keys[n] = key;
22136a580ebSKoji Sato 			ptrs[n] = ptr;
22236a580ebSKoji Sato 			n++;
22336a580ebSKoji Sato 		}
22436a580ebSKoji Sato 	}
22536a580ebSKoji Sato 	return n;
22636a580ebSKoji Sato }
22736a580ebSKoji Sato 
nilfs_direct_delete_and_convert(struct nilfs_bmap * bmap,__u64 key,__u64 * keys,__u64 * ptrs,int n)22836a580ebSKoji Sato int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
2293033342aSRyusuke Konishi 				    __u64 key, __u64 *keys, __u64 *ptrs, int n)
23036a580ebSKoji Sato {
23136a580ebSKoji Sato 	__le64 *dptrs;
23236a580ebSKoji Sato 	int ret, i, j;
23336a580ebSKoji Sato 
23436a580ebSKoji Sato 	/* no need to allocate any resource for conversion */
23536a580ebSKoji Sato 
23636a580ebSKoji Sato 	/* delete */
2378acfbf09SPekka Enberg 	ret = bmap->b_ops->bop_delete(bmap, key);
23836a580ebSKoji Sato 	if (ret < 0)
23936a580ebSKoji Sato 		return ret;
24036a580ebSKoji Sato 
24136a580ebSKoji Sato 	/* free resources */
24236a580ebSKoji Sato 	if (bmap->b_ops->bop_clear != NULL)
2438acfbf09SPekka Enberg 		bmap->b_ops->bop_clear(bmap);
24436a580ebSKoji Sato 
24536a580ebSKoji Sato 	/* convert */
24610ff885bSRyusuke Konishi 	dptrs = nilfs_direct_dptrs(bmap);
24736a580ebSKoji Sato 	for (i = 0, j = 0; i < NILFS_DIRECT_NBLOCKS; i++) {
24836a580ebSKoji Sato 		if ((j < n) && (i == keys[j])) {
24936a580ebSKoji Sato 			dptrs[i] = (i != key) ?
25025b8d7deSRyusuke Konishi 				cpu_to_le64(ptrs[j]) :
25136a580ebSKoji Sato 				NILFS_BMAP_INVALID_PTR;
25236a580ebSKoji Sato 			j++;
25336a580ebSKoji Sato 		} else
25436a580ebSKoji Sato 			dptrs[i] = NILFS_BMAP_INVALID_PTR;
25536a580ebSKoji Sato 	}
25636a580ebSKoji Sato 
2573033342aSRyusuke Konishi 	nilfs_direct_init(bmap);
25836a580ebSKoji Sato 	return 0;
25936a580ebSKoji Sato }
26036a580ebSKoji Sato 
nilfs_direct_propagate(struct nilfs_bmap * bmap,struct buffer_head * bh)261583ada47SRyusuke Konishi static int nilfs_direct_propagate(struct nilfs_bmap *bmap,
26236a580ebSKoji Sato 				  struct buffer_head *bh)
26336a580ebSKoji Sato {
2642e0c2c73SRyusuke Konishi 	struct nilfs_palloc_req oldreq, newreq;
2652e0c2c73SRyusuke Konishi 	struct inode *dat;
2662e0c2c73SRyusuke Konishi 	__u64 key;
2672e0c2c73SRyusuke Konishi 	__u64 ptr;
2682e0c2c73SRyusuke Konishi 	int ret;
26936a580ebSKoji Sato 
2702e0c2c73SRyusuke Konishi 	if (!NILFS_BMAP_USE_VBN(bmap))
2712e0c2c73SRyusuke Konishi 		return 0;
2722e0c2c73SRyusuke Konishi 
2732e0c2c73SRyusuke Konishi 	dat = nilfs_bmap_get_dat(bmap);
2742e0c2c73SRyusuke Konishi 	key = nilfs_bmap_data_get_key(bmap, bh);
27510ff885bSRyusuke Konishi 	ptr = nilfs_direct_get_ptr(bmap, key);
2762e0c2c73SRyusuke Konishi 	if (!buffer_nilfs_volatile(bh)) {
2772e0c2c73SRyusuke Konishi 		oldreq.pr_entry_nr = ptr;
2782e0c2c73SRyusuke Konishi 		newreq.pr_entry_nr = ptr;
2792e0c2c73SRyusuke Konishi 		ret = nilfs_dat_prepare_update(dat, &oldreq, &newreq);
2802e0c2c73SRyusuke Konishi 		if (ret < 0)
2812e0c2c73SRyusuke Konishi 			return ret;
2822e0c2c73SRyusuke Konishi 		nilfs_dat_commit_update(dat, &oldreq, &newreq,
2832e0c2c73SRyusuke Konishi 					bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
2842e0c2c73SRyusuke Konishi 		set_buffer_nilfs_volatile(bh);
28510ff885bSRyusuke Konishi 		nilfs_direct_set_ptr(bmap, key, newreq.pr_entry_nr);
2862e0c2c73SRyusuke Konishi 	} else
2872e0c2c73SRyusuke Konishi 		ret = nilfs_dat_mark_dirty(dat, ptr);
2882e0c2c73SRyusuke Konishi 
2892e0c2c73SRyusuke Konishi 	return ret;
29036a580ebSKoji Sato }
29136a580ebSKoji Sato 
nilfs_direct_assign_v(struct nilfs_bmap * direct,__u64 key,__u64 ptr,struct buffer_head ** bh,sector_t blocknr,union nilfs_binfo * binfo)29210ff885bSRyusuke Konishi static int nilfs_direct_assign_v(struct nilfs_bmap *direct,
29336a580ebSKoji Sato 				 __u64 key, __u64 ptr,
29436a580ebSKoji Sato 				 struct buffer_head **bh,
29536a580ebSKoji Sato 				 sector_t blocknr,
29636a580ebSKoji Sato 				 union nilfs_binfo *binfo)
29736a580ebSKoji Sato {
29810ff885bSRyusuke Konishi 	struct inode *dat = nilfs_bmap_get_dat(direct);
29936a580ebSKoji Sato 	union nilfs_bmap_ptr_req req;
30036a580ebSKoji Sato 	int ret;
30136a580ebSKoji Sato 
30236a580ebSKoji Sato 	req.bpr_ptr = ptr;
3032e0c2c73SRyusuke Konishi 	ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
3042e0c2c73SRyusuke Konishi 	if (!ret) {
3052e0c2c73SRyusuke Konishi 		nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
30625b8d7deSRyusuke Konishi 		binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
30725b8d7deSRyusuke Konishi 		binfo->bi_v.bi_blkoff = cpu_to_le64(key);
3082e0c2c73SRyusuke Konishi 	}
3092e0c2c73SRyusuke Konishi 	return ret;
31036a580ebSKoji Sato }
31136a580ebSKoji Sato 
nilfs_direct_assign_p(struct nilfs_bmap * direct,__u64 key,__u64 ptr,struct buffer_head ** bh,sector_t blocknr,union nilfs_binfo * binfo)31210ff885bSRyusuke Konishi static int nilfs_direct_assign_p(struct nilfs_bmap *direct,
31336a580ebSKoji Sato 				 __u64 key, __u64 ptr,
31436a580ebSKoji Sato 				 struct buffer_head **bh,
31536a580ebSKoji Sato 				 sector_t blocknr,
31636a580ebSKoji Sato 				 union nilfs_binfo *binfo)
31736a580ebSKoji Sato {
31836a580ebSKoji Sato 	nilfs_direct_set_ptr(direct, key, blocknr);
31936a580ebSKoji Sato 
32025b8d7deSRyusuke Konishi 	binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
32136a580ebSKoji Sato 	binfo->bi_dat.bi_level = 0;
32273970316STetsuo Handa 	memset(binfo->bi_dat.bi_pad, 0, sizeof(binfo->bi_dat.bi_pad));
32336a580ebSKoji Sato 
32436a580ebSKoji Sato 	return 0;
32536a580ebSKoji Sato }
32636a580ebSKoji Sato 
nilfs_direct_assign(struct nilfs_bmap * bmap,struct buffer_head ** bh,sector_t blocknr,union nilfs_binfo * binfo)32736a580ebSKoji Sato static int nilfs_direct_assign(struct nilfs_bmap *bmap,
32836a580ebSKoji Sato 			       struct buffer_head **bh,
32936a580ebSKoji Sato 			       sector_t blocknr,
33036a580ebSKoji Sato 			       union nilfs_binfo *binfo)
33136a580ebSKoji Sato {
33236a580ebSKoji Sato 	__u64 key;
33336a580ebSKoji Sato 	__u64 ptr;
33436a580ebSKoji Sato 
33536a580ebSKoji Sato 	key = nilfs_bmap_data_get_key(bmap, *bh);
3361f5abe7eSRyusuke Konishi 	if (unlikely(key > NILFS_DIRECT_KEY_MAX)) {
337a1d0747aSJoe Perches 		nilfs_crit(bmap->b_inode->i_sb,
338a1d0747aSJoe Perches 			   "%s (ino=%lu): invalid key: %llu",
339a1d0747aSJoe Perches 			   __func__,
340feee880fSRyusuke Konishi 			   bmap->b_inode->i_ino, (unsigned long long)key);
3411f5abe7eSRyusuke Konishi 		return -EINVAL;
3421f5abe7eSRyusuke Konishi 	}
34310ff885bSRyusuke Konishi 	ptr = nilfs_direct_get_ptr(bmap, key);
3441f5abe7eSRyusuke Konishi 	if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) {
345a1d0747aSJoe Perches 		nilfs_crit(bmap->b_inode->i_sb,
346a1d0747aSJoe Perches 			   "%s (ino=%lu): invalid pointer: %llu",
347a1d0747aSJoe Perches 			   __func__,
348feee880fSRyusuke Konishi 			   bmap->b_inode->i_ino, (unsigned long long)ptr);
3491f5abe7eSRyusuke Konishi 		return -EINVAL;
3501f5abe7eSRyusuke Konishi 	}
35136a580ebSKoji Sato 
352355c6b61SRyusuke Konishi 	return NILFS_BMAP_USE_VBN(bmap) ?
35310ff885bSRyusuke Konishi 		nilfs_direct_assign_v(bmap, key, ptr, bh, blocknr, binfo) :
35410ff885bSRyusuke Konishi 		nilfs_direct_assign_p(bmap, key, ptr, bh, blocknr, binfo);
35536a580ebSKoji Sato }
35636a580ebSKoji Sato 
35736a580ebSKoji Sato static const struct nilfs_bmap_operations nilfs_direct_ops = {
35836a580ebSKoji Sato 	.bop_lookup		=	nilfs_direct_lookup,
359c3a7abf0SRyusuke Konishi 	.bop_lookup_contig	=	nilfs_direct_lookup_contig,
36036a580ebSKoji Sato 	.bop_insert		=	nilfs_direct_insert,
36136a580ebSKoji Sato 	.bop_delete		=	nilfs_direct_delete,
36236a580ebSKoji Sato 	.bop_clear		=	NULL,
36336a580ebSKoji Sato 
36436a580ebSKoji Sato 	.bop_propagate		=	nilfs_direct_propagate,
36536a580ebSKoji Sato 
36636a580ebSKoji Sato 	.bop_lookup_dirty_buffers	=	NULL,
36736a580ebSKoji Sato 
36836a580ebSKoji Sato 	.bop_assign		=	nilfs_direct_assign,
36936a580ebSKoji Sato 	.bop_mark		=	NULL,
37036a580ebSKoji Sato 
3715b20384fSRyusuke Konishi 	.bop_seek_key		=	nilfs_direct_seek_key,
37236a580ebSKoji Sato 	.bop_last_key		=	nilfs_direct_last_key,
3735b20384fSRyusuke Konishi 
37436a580ebSKoji Sato 	.bop_check_insert	=	nilfs_direct_check_insert,
37536a580ebSKoji Sato 	.bop_check_delete	=	NULL,
37636a580ebSKoji Sato 	.bop_gather_data	=	nilfs_direct_gather_data,
37736a580ebSKoji Sato };
37836a580ebSKoji Sato 
37936a580ebSKoji Sato 
nilfs_direct_init(struct nilfs_bmap * bmap)3803033342aSRyusuke Konishi int nilfs_direct_init(struct nilfs_bmap *bmap)
38136a580ebSKoji Sato {
38236a580ebSKoji Sato 	bmap->b_ops = &nilfs_direct_ops;
38336a580ebSKoji Sato 	return 0;
38436a580ebSKoji Sato }
385