1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * bmap.c - NILFS block mapping.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Written by Koji Sato.
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/fs.h>
11*4882a593Smuzhiyun #include <linux/string.h>
12*4882a593Smuzhiyun #include <linux/errno.h>
13*4882a593Smuzhiyun #include "nilfs.h"
14*4882a593Smuzhiyun #include "bmap.h"
15*4882a593Smuzhiyun #include "btree.h"
16*4882a593Smuzhiyun #include "direct.h"
17*4882a593Smuzhiyun #include "btnode.h"
18*4882a593Smuzhiyun #include "mdt.h"
19*4882a593Smuzhiyun #include "dat.h"
20*4882a593Smuzhiyun #include "alloc.h"
21*4882a593Smuzhiyun
nilfs_bmap_get_dat(const struct nilfs_bmap * bmap)22*4882a593Smuzhiyun struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun struct the_nilfs *nilfs = bmap->b_inode->i_sb->s_fs_info;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun return nilfs->ns_dat;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun
nilfs_bmap_convert_error(struct nilfs_bmap * bmap,const char * fname,int err)29*4882a593Smuzhiyun static int nilfs_bmap_convert_error(struct nilfs_bmap *bmap,
30*4882a593Smuzhiyun const char *fname, int err)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun struct inode *inode = bmap->b_inode;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun if (err == -EINVAL) {
35*4882a593Smuzhiyun __nilfs_error(inode->i_sb, fname,
36*4882a593Smuzhiyun "broken bmap (inode number=%lu)", inode->i_ino);
37*4882a593Smuzhiyun err = -EIO;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun return err;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /**
43*4882a593Smuzhiyun * nilfs_bmap_lookup_at_level - find a data block or node block
44*4882a593Smuzhiyun * @bmap: bmap
45*4882a593Smuzhiyun * @key: key
46*4882a593Smuzhiyun * @level: level
47*4882a593Smuzhiyun * @ptrp: place to store the value associated to @key
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun * Description: nilfs_bmap_lookup_at_level() finds a record whose key
50*4882a593Smuzhiyun * matches @key in the block at @level of the bmap.
51*4882a593Smuzhiyun *
52*4882a593Smuzhiyun * Return Value: On success, 0 is returned and the record associated with @key
53*4882a593Smuzhiyun * is stored in the place pointed by @ptrp. On error, one of the following
54*4882a593Smuzhiyun * negative error codes is returned.
55*4882a593Smuzhiyun *
56*4882a593Smuzhiyun * %-EIO - I/O error.
57*4882a593Smuzhiyun *
58*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
59*4882a593Smuzhiyun *
60*4882a593Smuzhiyun * %-ENOENT - A record associated with @key does not exist.
61*4882a593Smuzhiyun */
nilfs_bmap_lookup_at_level(struct nilfs_bmap * bmap,__u64 key,int level,__u64 * ptrp)62*4882a593Smuzhiyun int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
63*4882a593Smuzhiyun __u64 *ptrp)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun sector_t blocknr;
66*4882a593Smuzhiyun int ret;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun down_read(&bmap->b_sem);
69*4882a593Smuzhiyun ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
70*4882a593Smuzhiyun if (ret < 0) {
71*4882a593Smuzhiyun ret = nilfs_bmap_convert_error(bmap, __func__, ret);
72*4882a593Smuzhiyun goto out;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun if (NILFS_BMAP_USE_VBN(bmap)) {
75*4882a593Smuzhiyun ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
76*4882a593Smuzhiyun &blocknr);
77*4882a593Smuzhiyun if (!ret)
78*4882a593Smuzhiyun *ptrp = blocknr;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun out:
82*4882a593Smuzhiyun up_read(&bmap->b_sem);
83*4882a593Smuzhiyun return ret;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
nilfs_bmap_lookup_contig(struct nilfs_bmap * bmap,__u64 key,__u64 * ptrp,unsigned int maxblocks)86*4882a593Smuzhiyun int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp,
87*4882a593Smuzhiyun unsigned int maxblocks)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun int ret;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun down_read(&bmap->b_sem);
92*4882a593Smuzhiyun ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks);
93*4882a593Smuzhiyun up_read(&bmap->b_sem);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun return nilfs_bmap_convert_error(bmap, __func__, ret);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
nilfs_bmap_do_insert(struct nilfs_bmap * bmap,__u64 key,__u64 ptr)98*4882a593Smuzhiyun static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun __u64 keys[NILFS_BMAP_SMALL_HIGH + 1];
101*4882a593Smuzhiyun __u64 ptrs[NILFS_BMAP_SMALL_HIGH + 1];
102*4882a593Smuzhiyun int ret, n;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun if (bmap->b_ops->bop_check_insert != NULL) {
105*4882a593Smuzhiyun ret = bmap->b_ops->bop_check_insert(bmap, key);
106*4882a593Smuzhiyun if (ret > 0) {
107*4882a593Smuzhiyun n = bmap->b_ops->bop_gather_data(
108*4882a593Smuzhiyun bmap, keys, ptrs, NILFS_BMAP_SMALL_HIGH + 1);
109*4882a593Smuzhiyun if (n < 0)
110*4882a593Smuzhiyun return n;
111*4882a593Smuzhiyun ret = nilfs_btree_convert_and_insert(
112*4882a593Smuzhiyun bmap, key, ptr, keys, ptrs, n);
113*4882a593Smuzhiyun if (ret == 0)
114*4882a593Smuzhiyun bmap->b_u.u_flags |= NILFS_BMAP_LARGE;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun return ret;
117*4882a593Smuzhiyun } else if (ret < 0)
118*4882a593Smuzhiyun return ret;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun return bmap->b_ops->bop_insert(bmap, key, ptr);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /**
125*4882a593Smuzhiyun * nilfs_bmap_insert - insert a new key-record pair into a bmap
126*4882a593Smuzhiyun * @bmap: bmap
127*4882a593Smuzhiyun * @key: key
128*4882a593Smuzhiyun * @rec: record
129*4882a593Smuzhiyun *
130*4882a593Smuzhiyun * Description: nilfs_bmap_insert() inserts the new key-record pair specified
131*4882a593Smuzhiyun * by @key and @rec into @bmap.
132*4882a593Smuzhiyun *
133*4882a593Smuzhiyun * Return Value: On success, 0 is returned. On error, one of the following
134*4882a593Smuzhiyun * negative error codes is returned.
135*4882a593Smuzhiyun *
136*4882a593Smuzhiyun * %-EIO - I/O error.
137*4882a593Smuzhiyun *
138*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
139*4882a593Smuzhiyun *
140*4882a593Smuzhiyun * %-EEXIST - A record associated with @key already exist.
141*4882a593Smuzhiyun */
nilfs_bmap_insert(struct nilfs_bmap * bmap,__u64 key,unsigned long rec)142*4882a593Smuzhiyun int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun int ret;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun down_write(&bmap->b_sem);
147*4882a593Smuzhiyun ret = nilfs_bmap_do_insert(bmap, key, rec);
148*4882a593Smuzhiyun up_write(&bmap->b_sem);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun return nilfs_bmap_convert_error(bmap, __func__, ret);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
nilfs_bmap_do_delete(struct nilfs_bmap * bmap,__u64 key)153*4882a593Smuzhiyun static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun __u64 keys[NILFS_BMAP_LARGE_LOW + 1];
156*4882a593Smuzhiyun __u64 ptrs[NILFS_BMAP_LARGE_LOW + 1];
157*4882a593Smuzhiyun int ret, n;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun if (bmap->b_ops->bop_check_delete != NULL) {
160*4882a593Smuzhiyun ret = bmap->b_ops->bop_check_delete(bmap, key);
161*4882a593Smuzhiyun if (ret > 0) {
162*4882a593Smuzhiyun n = bmap->b_ops->bop_gather_data(
163*4882a593Smuzhiyun bmap, keys, ptrs, NILFS_BMAP_LARGE_LOW + 1);
164*4882a593Smuzhiyun if (n < 0)
165*4882a593Smuzhiyun return n;
166*4882a593Smuzhiyun ret = nilfs_direct_delete_and_convert(
167*4882a593Smuzhiyun bmap, key, keys, ptrs, n);
168*4882a593Smuzhiyun if (ret == 0)
169*4882a593Smuzhiyun bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun return ret;
172*4882a593Smuzhiyun } else if (ret < 0)
173*4882a593Smuzhiyun return ret;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun return bmap->b_ops->bop_delete(bmap, key);
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /**
180*4882a593Smuzhiyun * nilfs_bmap_seek_key - seek a valid entry and return its key
181*4882a593Smuzhiyun * @bmap: bmap struct
182*4882a593Smuzhiyun * @start: start key number
183*4882a593Smuzhiyun * @keyp: place to store valid key
184*4882a593Smuzhiyun *
185*4882a593Smuzhiyun * Description: nilfs_bmap_seek_key() seeks a valid key on @bmap
186*4882a593Smuzhiyun * starting from @start, and stores it to @keyp if found.
187*4882a593Smuzhiyun *
188*4882a593Smuzhiyun * Return Value: On success, 0 is returned. On error, one of the following
189*4882a593Smuzhiyun * negative error codes is returned.
190*4882a593Smuzhiyun *
191*4882a593Smuzhiyun * %-EIO - I/O error.
192*4882a593Smuzhiyun *
193*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
194*4882a593Smuzhiyun *
195*4882a593Smuzhiyun * %-ENOENT - No valid entry was found
196*4882a593Smuzhiyun */
nilfs_bmap_seek_key(struct nilfs_bmap * bmap,__u64 start,__u64 * keyp)197*4882a593Smuzhiyun int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun int ret;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun down_read(&bmap->b_sem);
202*4882a593Smuzhiyun ret = bmap->b_ops->bop_seek_key(bmap, start, keyp);
203*4882a593Smuzhiyun up_read(&bmap->b_sem);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun if (ret < 0)
206*4882a593Smuzhiyun ret = nilfs_bmap_convert_error(bmap, __func__, ret);
207*4882a593Smuzhiyun return ret;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
nilfs_bmap_last_key(struct nilfs_bmap * bmap,__u64 * keyp)210*4882a593Smuzhiyun int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun int ret;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun down_read(&bmap->b_sem);
215*4882a593Smuzhiyun ret = bmap->b_ops->bop_last_key(bmap, keyp);
216*4882a593Smuzhiyun up_read(&bmap->b_sem);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun if (ret < 0)
219*4882a593Smuzhiyun ret = nilfs_bmap_convert_error(bmap, __func__, ret);
220*4882a593Smuzhiyun return ret;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /**
224*4882a593Smuzhiyun * nilfs_bmap_delete - delete a key-record pair from a bmap
225*4882a593Smuzhiyun * @bmap: bmap
226*4882a593Smuzhiyun * @key: key
227*4882a593Smuzhiyun *
228*4882a593Smuzhiyun * Description: nilfs_bmap_delete() deletes the key-record pair specified by
229*4882a593Smuzhiyun * @key from @bmap.
230*4882a593Smuzhiyun *
231*4882a593Smuzhiyun * Return Value: On success, 0 is returned. On error, one of the following
232*4882a593Smuzhiyun * negative error codes is returned.
233*4882a593Smuzhiyun *
234*4882a593Smuzhiyun * %-EIO - I/O error.
235*4882a593Smuzhiyun *
236*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
237*4882a593Smuzhiyun *
238*4882a593Smuzhiyun * %-ENOENT - A record associated with @key does not exist.
239*4882a593Smuzhiyun */
nilfs_bmap_delete(struct nilfs_bmap * bmap,__u64 key)240*4882a593Smuzhiyun int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun int ret;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun down_write(&bmap->b_sem);
245*4882a593Smuzhiyun ret = nilfs_bmap_do_delete(bmap, key);
246*4882a593Smuzhiyun up_write(&bmap->b_sem);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun return nilfs_bmap_convert_error(bmap, __func__, ret);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
nilfs_bmap_do_truncate(struct nilfs_bmap * bmap,__u64 key)251*4882a593Smuzhiyun static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, __u64 key)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun __u64 lastkey;
254*4882a593Smuzhiyun int ret;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
257*4882a593Smuzhiyun if (ret < 0) {
258*4882a593Smuzhiyun if (ret == -ENOENT)
259*4882a593Smuzhiyun ret = 0;
260*4882a593Smuzhiyun return ret;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun while (key <= lastkey) {
264*4882a593Smuzhiyun ret = nilfs_bmap_do_delete(bmap, lastkey);
265*4882a593Smuzhiyun if (ret < 0)
266*4882a593Smuzhiyun return ret;
267*4882a593Smuzhiyun ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
268*4882a593Smuzhiyun if (ret < 0) {
269*4882a593Smuzhiyun if (ret == -ENOENT)
270*4882a593Smuzhiyun ret = 0;
271*4882a593Smuzhiyun return ret;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun return 0;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun /**
278*4882a593Smuzhiyun * nilfs_bmap_truncate - truncate a bmap to a specified key
279*4882a593Smuzhiyun * @bmap: bmap
280*4882a593Smuzhiyun * @key: key
281*4882a593Smuzhiyun *
282*4882a593Smuzhiyun * Description: nilfs_bmap_truncate() removes key-record pairs whose keys are
283*4882a593Smuzhiyun * greater than or equal to @key from @bmap.
284*4882a593Smuzhiyun *
285*4882a593Smuzhiyun * Return Value: On success, 0 is returned. On error, one of the following
286*4882a593Smuzhiyun * negative error codes is returned.
287*4882a593Smuzhiyun *
288*4882a593Smuzhiyun * %-EIO - I/O error.
289*4882a593Smuzhiyun *
290*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
291*4882a593Smuzhiyun */
nilfs_bmap_truncate(struct nilfs_bmap * bmap,__u64 key)292*4882a593Smuzhiyun int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun int ret;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun down_write(&bmap->b_sem);
297*4882a593Smuzhiyun ret = nilfs_bmap_do_truncate(bmap, key);
298*4882a593Smuzhiyun up_write(&bmap->b_sem);
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun return nilfs_bmap_convert_error(bmap, __func__, ret);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /**
304*4882a593Smuzhiyun * nilfs_bmap_clear - free resources a bmap holds
305*4882a593Smuzhiyun * @bmap: bmap
306*4882a593Smuzhiyun *
307*4882a593Smuzhiyun * Description: nilfs_bmap_clear() frees resources associated with @bmap.
308*4882a593Smuzhiyun */
nilfs_bmap_clear(struct nilfs_bmap * bmap)309*4882a593Smuzhiyun void nilfs_bmap_clear(struct nilfs_bmap *bmap)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun down_write(&bmap->b_sem);
312*4882a593Smuzhiyun if (bmap->b_ops->bop_clear != NULL)
313*4882a593Smuzhiyun bmap->b_ops->bop_clear(bmap);
314*4882a593Smuzhiyun up_write(&bmap->b_sem);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun /**
318*4882a593Smuzhiyun * nilfs_bmap_propagate - propagate dirty state
319*4882a593Smuzhiyun * @bmap: bmap
320*4882a593Smuzhiyun * @bh: buffer head
321*4882a593Smuzhiyun *
322*4882a593Smuzhiyun * Description: nilfs_bmap_propagate() marks the buffers that directly or
323*4882a593Smuzhiyun * indirectly refer to the block specified by @bh dirty.
324*4882a593Smuzhiyun *
325*4882a593Smuzhiyun * Return Value: On success, 0 is returned. On error, one of the following
326*4882a593Smuzhiyun * negative error codes is returned.
327*4882a593Smuzhiyun *
328*4882a593Smuzhiyun * %-EIO - I/O error.
329*4882a593Smuzhiyun *
330*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
331*4882a593Smuzhiyun */
nilfs_bmap_propagate(struct nilfs_bmap * bmap,struct buffer_head * bh)332*4882a593Smuzhiyun int nilfs_bmap_propagate(struct nilfs_bmap *bmap, struct buffer_head *bh)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun int ret;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun down_write(&bmap->b_sem);
337*4882a593Smuzhiyun ret = bmap->b_ops->bop_propagate(bmap, bh);
338*4882a593Smuzhiyun up_write(&bmap->b_sem);
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun return nilfs_bmap_convert_error(bmap, __func__, ret);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun /**
344*4882a593Smuzhiyun * nilfs_bmap_lookup_dirty_buffers -
345*4882a593Smuzhiyun * @bmap: bmap
346*4882a593Smuzhiyun * @listp: pointer to buffer head list
347*4882a593Smuzhiyun */
nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap * bmap,struct list_head * listp)348*4882a593Smuzhiyun void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *bmap,
349*4882a593Smuzhiyun struct list_head *listp)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun if (bmap->b_ops->bop_lookup_dirty_buffers != NULL)
352*4882a593Smuzhiyun bmap->b_ops->bop_lookup_dirty_buffers(bmap, listp);
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun /**
356*4882a593Smuzhiyun * nilfs_bmap_assign - assign a new block number to a block
357*4882a593Smuzhiyun * @bmap: bmap
358*4882a593Smuzhiyun * @bh: pointer to buffer head
359*4882a593Smuzhiyun * @blocknr: block number
360*4882a593Smuzhiyun * @binfo: block information
361*4882a593Smuzhiyun *
362*4882a593Smuzhiyun * Description: nilfs_bmap_assign() assigns the block number @blocknr to the
363*4882a593Smuzhiyun * buffer specified by @bh.
364*4882a593Smuzhiyun *
365*4882a593Smuzhiyun * Return Value: On success, 0 is returned and the buffer head of a newly
366*4882a593Smuzhiyun * create buffer and the block information associated with the buffer are
367*4882a593Smuzhiyun * stored in the place pointed by @bh and @binfo, respectively. On error, one
368*4882a593Smuzhiyun * of the following negative error codes is returned.
369*4882a593Smuzhiyun *
370*4882a593Smuzhiyun * %-EIO - I/O error.
371*4882a593Smuzhiyun *
372*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
373*4882a593Smuzhiyun */
nilfs_bmap_assign(struct nilfs_bmap * bmap,struct buffer_head ** bh,unsigned long blocknr,union nilfs_binfo * binfo)374*4882a593Smuzhiyun int nilfs_bmap_assign(struct nilfs_bmap *bmap,
375*4882a593Smuzhiyun struct buffer_head **bh,
376*4882a593Smuzhiyun unsigned long blocknr,
377*4882a593Smuzhiyun union nilfs_binfo *binfo)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun int ret;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun down_write(&bmap->b_sem);
382*4882a593Smuzhiyun ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo);
383*4882a593Smuzhiyun up_write(&bmap->b_sem);
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun return nilfs_bmap_convert_error(bmap, __func__, ret);
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun /**
389*4882a593Smuzhiyun * nilfs_bmap_mark - mark block dirty
390*4882a593Smuzhiyun * @bmap: bmap
391*4882a593Smuzhiyun * @key: key
392*4882a593Smuzhiyun * @level: level
393*4882a593Smuzhiyun *
394*4882a593Smuzhiyun * Description: nilfs_bmap_mark() marks the block specified by @key and @level
395*4882a593Smuzhiyun * as dirty.
396*4882a593Smuzhiyun *
397*4882a593Smuzhiyun * Return Value: On success, 0 is returned. On error, one of the following
398*4882a593Smuzhiyun * negative error codes is returned.
399*4882a593Smuzhiyun *
400*4882a593Smuzhiyun * %-EIO - I/O error.
401*4882a593Smuzhiyun *
402*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
403*4882a593Smuzhiyun */
nilfs_bmap_mark(struct nilfs_bmap * bmap,__u64 key,int level)404*4882a593Smuzhiyun int nilfs_bmap_mark(struct nilfs_bmap *bmap, __u64 key, int level)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun int ret;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun if (bmap->b_ops->bop_mark == NULL)
409*4882a593Smuzhiyun return 0;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun down_write(&bmap->b_sem);
412*4882a593Smuzhiyun ret = bmap->b_ops->bop_mark(bmap, key, level);
413*4882a593Smuzhiyun up_write(&bmap->b_sem);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun return nilfs_bmap_convert_error(bmap, __func__, ret);
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun /**
419*4882a593Smuzhiyun * nilfs_bmap_test_and_clear_dirty - test and clear a bmap dirty state
420*4882a593Smuzhiyun * @bmap: bmap
421*4882a593Smuzhiyun *
422*4882a593Smuzhiyun * Description: nilfs_test_and_clear() is the atomic operation to test and
423*4882a593Smuzhiyun * clear the dirty state of @bmap.
424*4882a593Smuzhiyun *
425*4882a593Smuzhiyun * Return Value: 1 is returned if @bmap is dirty, or 0 if clear.
426*4882a593Smuzhiyun */
nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap * bmap)427*4882a593Smuzhiyun int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun int ret;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun down_write(&bmap->b_sem);
432*4882a593Smuzhiyun ret = nilfs_bmap_dirty(bmap);
433*4882a593Smuzhiyun nilfs_bmap_clear_dirty(bmap);
434*4882a593Smuzhiyun up_write(&bmap->b_sem);
435*4882a593Smuzhiyun return ret;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun /*
440*4882a593Smuzhiyun * Internal use only
441*4882a593Smuzhiyun */
nilfs_bmap_data_get_key(const struct nilfs_bmap * bmap,const struct buffer_head * bh)442*4882a593Smuzhiyun __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
443*4882a593Smuzhiyun const struct buffer_head *bh)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun struct buffer_head *pbh;
446*4882a593Smuzhiyun __u64 key;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun key = page_index(bh->b_page) << (PAGE_SHIFT -
449*4882a593Smuzhiyun bmap->b_inode->i_blkbits);
450*4882a593Smuzhiyun for (pbh = page_buffers(bh->b_page); pbh != bh; pbh = pbh->b_this_page)
451*4882a593Smuzhiyun key++;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun return key;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
nilfs_bmap_find_target_seq(const struct nilfs_bmap * bmap,__u64 key)456*4882a593Smuzhiyun __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *bmap, __u64 key)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun __s64 diff;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun diff = key - bmap->b_last_allocated_key;
461*4882a593Smuzhiyun if ((nilfs_bmap_keydiff_abs(diff) < NILFS_INODE_BMAP_SIZE) &&
462*4882a593Smuzhiyun (bmap->b_last_allocated_ptr != NILFS_BMAP_INVALID_PTR) &&
463*4882a593Smuzhiyun (bmap->b_last_allocated_ptr + diff > 0))
464*4882a593Smuzhiyun return bmap->b_last_allocated_ptr + diff;
465*4882a593Smuzhiyun else
466*4882a593Smuzhiyun return NILFS_BMAP_INVALID_PTR;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun #define NILFS_BMAP_GROUP_DIV 8
nilfs_bmap_find_target_in_group(const struct nilfs_bmap * bmap)470*4882a593Smuzhiyun __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun struct inode *dat = nilfs_bmap_get_dat(bmap);
473*4882a593Smuzhiyun unsigned long entries_per_group = nilfs_palloc_entries_per_group(dat);
474*4882a593Smuzhiyun unsigned long group = bmap->b_inode->i_ino / entries_per_group;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun return group * entries_per_group +
477*4882a593Smuzhiyun (bmap->b_inode->i_ino % NILFS_BMAP_GROUP_DIV) *
478*4882a593Smuzhiyun (entries_per_group / NILFS_BMAP_GROUP_DIV);
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun static struct lock_class_key nilfs_bmap_dat_lock_key;
482*4882a593Smuzhiyun static struct lock_class_key nilfs_bmap_mdt_lock_key;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun /**
485*4882a593Smuzhiyun * nilfs_bmap_read - read a bmap from an inode
486*4882a593Smuzhiyun * @bmap: bmap
487*4882a593Smuzhiyun * @raw_inode: on-disk inode
488*4882a593Smuzhiyun *
489*4882a593Smuzhiyun * Description: nilfs_bmap_read() initializes the bmap @bmap.
490*4882a593Smuzhiyun *
491*4882a593Smuzhiyun * Return Value: On success, 0 is returned. On error, the following negative
492*4882a593Smuzhiyun * error code is returned.
493*4882a593Smuzhiyun *
494*4882a593Smuzhiyun * %-ENOMEM - Insufficient amount of memory available.
495*4882a593Smuzhiyun */
nilfs_bmap_read(struct nilfs_bmap * bmap,struct nilfs_inode * raw_inode)496*4882a593Smuzhiyun int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun if (raw_inode == NULL)
499*4882a593Smuzhiyun memset(bmap->b_u.u_data, 0, NILFS_BMAP_SIZE);
500*4882a593Smuzhiyun else
501*4882a593Smuzhiyun memcpy(bmap->b_u.u_data, raw_inode->i_bmap, NILFS_BMAP_SIZE);
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun init_rwsem(&bmap->b_sem);
504*4882a593Smuzhiyun bmap->b_state = 0;
505*4882a593Smuzhiyun bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
506*4882a593Smuzhiyun switch (bmap->b_inode->i_ino) {
507*4882a593Smuzhiyun case NILFS_DAT_INO:
508*4882a593Smuzhiyun bmap->b_ptr_type = NILFS_BMAP_PTR_P;
509*4882a593Smuzhiyun bmap->b_last_allocated_key = 0;
510*4882a593Smuzhiyun bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
511*4882a593Smuzhiyun lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
512*4882a593Smuzhiyun break;
513*4882a593Smuzhiyun case NILFS_CPFILE_INO:
514*4882a593Smuzhiyun case NILFS_SUFILE_INO:
515*4882a593Smuzhiyun bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
516*4882a593Smuzhiyun bmap->b_last_allocated_key = 0;
517*4882a593Smuzhiyun bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
518*4882a593Smuzhiyun lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
519*4882a593Smuzhiyun break;
520*4882a593Smuzhiyun case NILFS_IFILE_INO:
521*4882a593Smuzhiyun lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
522*4882a593Smuzhiyun fallthrough;
523*4882a593Smuzhiyun default:
524*4882a593Smuzhiyun bmap->b_ptr_type = NILFS_BMAP_PTR_VM;
525*4882a593Smuzhiyun bmap->b_last_allocated_key = 0;
526*4882a593Smuzhiyun bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
527*4882a593Smuzhiyun break;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ?
531*4882a593Smuzhiyun nilfs_btree_init(bmap) : nilfs_direct_init(bmap);
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun /**
535*4882a593Smuzhiyun * nilfs_bmap_write - write back a bmap to an inode
536*4882a593Smuzhiyun * @bmap: bmap
537*4882a593Smuzhiyun * @raw_inode: on-disk inode
538*4882a593Smuzhiyun *
539*4882a593Smuzhiyun * Description: nilfs_bmap_write() stores @bmap in @raw_inode.
540*4882a593Smuzhiyun */
nilfs_bmap_write(struct nilfs_bmap * bmap,struct nilfs_inode * raw_inode)541*4882a593Smuzhiyun void nilfs_bmap_write(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun down_write(&bmap->b_sem);
544*4882a593Smuzhiyun memcpy(raw_inode->i_bmap, bmap->b_u.u_data,
545*4882a593Smuzhiyun NILFS_INODE_BMAP_SIZE * sizeof(__le64));
546*4882a593Smuzhiyun if (bmap->b_inode->i_ino == NILFS_DAT_INO)
547*4882a593Smuzhiyun bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun up_write(&bmap->b_sem);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
nilfs_bmap_init_gc(struct nilfs_bmap * bmap)552*4882a593Smuzhiyun void nilfs_bmap_init_gc(struct nilfs_bmap *bmap)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun memset(&bmap->b_u, 0, NILFS_BMAP_SIZE);
555*4882a593Smuzhiyun init_rwsem(&bmap->b_sem);
556*4882a593Smuzhiyun bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
557*4882a593Smuzhiyun bmap->b_ptr_type = NILFS_BMAP_PTR_U;
558*4882a593Smuzhiyun bmap->b_last_allocated_key = 0;
559*4882a593Smuzhiyun bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
560*4882a593Smuzhiyun bmap->b_state = 0;
561*4882a593Smuzhiyun nilfs_btree_init_gc(bmap);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
nilfs_bmap_save(const struct nilfs_bmap * bmap,struct nilfs_bmap_store * store)564*4882a593Smuzhiyun void nilfs_bmap_save(const struct nilfs_bmap *bmap,
565*4882a593Smuzhiyun struct nilfs_bmap_store *store)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun memcpy(store->data, bmap->b_u.u_data, sizeof(store->data));
568*4882a593Smuzhiyun store->last_allocated_key = bmap->b_last_allocated_key;
569*4882a593Smuzhiyun store->last_allocated_ptr = bmap->b_last_allocated_ptr;
570*4882a593Smuzhiyun store->state = bmap->b_state;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
nilfs_bmap_restore(struct nilfs_bmap * bmap,const struct nilfs_bmap_store * store)573*4882a593Smuzhiyun void nilfs_bmap_restore(struct nilfs_bmap *bmap,
574*4882a593Smuzhiyun const struct nilfs_bmap_store *store)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun memcpy(bmap->b_u.u_data, store->data, sizeof(store->data));
577*4882a593Smuzhiyun bmap->b_last_allocated_key = store->last_allocated_key;
578*4882a593Smuzhiyun bmap->b_last_allocated_ptr = store->last_allocated_ptr;
579*4882a593Smuzhiyun bmap->b_state = store->state;
580*4882a593Smuzhiyun }
581