xref: /openbmc/linux/fs/nilfs2/dat.c (revision 4652ae7a)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * NILFS disk address translation.
4  *
5  * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
6  *
7  * Written by Koji Sato.
8  */
9 
10 #include <linux/types.h>
11 #include <linux/buffer_head.h>
12 #include <linux/string.h>
13 #include <linux/errno.h>
14 #include "nilfs.h"
15 #include "mdt.h"
16 #include "alloc.h"
17 #include "dat.h"
18 
19 
20 #define NILFS_CNO_MIN	((__u64)1)
21 #define NILFS_CNO_MAX	(~(__u64)0)
22 
23 /**
24  * struct nilfs_dat_info - on-memory private data of DAT file
25  * @mi: on-memory private data of metadata file
26  * @palloc_cache: persistent object allocator cache of DAT file
27  * @shadow: shadow map of DAT file
28  */
29 struct nilfs_dat_info {
30 	struct nilfs_mdt_info mi;
31 	struct nilfs_palloc_cache palloc_cache;
32 	struct nilfs_shadow_map shadow;
33 };
34 
35 static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat)
36 {
37 	return (struct nilfs_dat_info *)NILFS_MDT(dat);
38 }
39 
40 static int nilfs_dat_prepare_entry(struct inode *dat,
41 				   struct nilfs_palloc_req *req, int create)
42 {
43 	return nilfs_palloc_get_entry_block(dat, req->pr_entry_nr,
44 					    create, &req->pr_entry_bh);
45 }
46 
47 static void nilfs_dat_commit_entry(struct inode *dat,
48 				   struct nilfs_palloc_req *req)
49 {
50 	mark_buffer_dirty(req->pr_entry_bh);
51 	nilfs_mdt_mark_dirty(dat);
52 	brelse(req->pr_entry_bh);
53 }
54 
55 static void nilfs_dat_abort_entry(struct inode *dat,
56 				  struct nilfs_palloc_req *req)
57 {
58 	brelse(req->pr_entry_bh);
59 }
60 
61 int nilfs_dat_prepare_alloc(struct inode *dat, struct nilfs_palloc_req *req)
62 {
63 	int ret;
64 
65 	ret = nilfs_palloc_prepare_alloc_entry(dat, req);
66 	if (ret < 0)
67 		return ret;
68 
69 	ret = nilfs_dat_prepare_entry(dat, req, 1);
70 	if (ret < 0)
71 		nilfs_palloc_abort_alloc_entry(dat, req);
72 
73 	return ret;
74 }
75 
76 void nilfs_dat_commit_alloc(struct inode *dat, struct nilfs_palloc_req *req)
77 {
78 	struct nilfs_dat_entry *entry;
79 	void *kaddr;
80 
81 	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
82 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
83 					     req->pr_entry_bh, kaddr);
84 	entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
85 	entry->de_end = cpu_to_le64(NILFS_CNO_MAX);
86 	entry->de_blocknr = cpu_to_le64(0);
87 	kunmap_atomic(kaddr);
88 
89 	nilfs_palloc_commit_alloc_entry(dat, req);
90 	nilfs_dat_commit_entry(dat, req);
91 }
92 
93 void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req)
94 {
95 	nilfs_dat_abort_entry(dat, req);
96 	nilfs_palloc_abort_alloc_entry(dat, req);
97 }
98 
99 static void nilfs_dat_commit_free(struct inode *dat,
100 				  struct nilfs_palloc_req *req)
101 {
102 	struct nilfs_dat_entry *entry;
103 	void *kaddr;
104 
105 	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
106 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
107 					     req->pr_entry_bh, kaddr);
108 	entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
109 	entry->de_end = cpu_to_le64(NILFS_CNO_MIN);
110 	entry->de_blocknr = cpu_to_le64(0);
111 	kunmap_atomic(kaddr);
112 
113 	nilfs_dat_commit_entry(dat, req);
114 
115 	if (unlikely(req->pr_desc_bh == NULL || req->pr_bitmap_bh == NULL)) {
116 		nilfs_error(dat->i_sb,
117 			    "state inconsistency probably due to duplicate use of vblocknr = %llu",
118 			    (unsigned long long)req->pr_entry_nr);
119 		return;
120 	}
121 	nilfs_palloc_commit_free_entry(dat, req);
122 }
123 
124 int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req)
125 {
126 	int ret;
127 
128 	ret = nilfs_dat_prepare_entry(dat, req, 0);
129 	WARN_ON(ret == -ENOENT);
130 	return ret;
131 }
132 
133 void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
134 			    sector_t blocknr)
135 {
136 	struct nilfs_dat_entry *entry;
137 	void *kaddr;
138 
139 	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
140 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
141 					     req->pr_entry_bh, kaddr);
142 	entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat));
143 	entry->de_blocknr = cpu_to_le64(blocknr);
144 	kunmap_atomic(kaddr);
145 
146 	nilfs_dat_commit_entry(dat, req);
147 }
148 
149 int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
150 {
151 	struct nilfs_dat_entry *entry;
152 	sector_t blocknr;
153 	void *kaddr;
154 	int ret;
155 
156 	ret = nilfs_dat_prepare_entry(dat, req, 0);
157 	if (ret < 0) {
158 		WARN_ON(ret == -ENOENT);
159 		return ret;
160 	}
161 
162 	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
163 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
164 					     req->pr_entry_bh, kaddr);
165 	blocknr = le64_to_cpu(entry->de_blocknr);
166 	kunmap_atomic(kaddr);
167 
168 	if (blocknr == 0) {
169 		ret = nilfs_palloc_prepare_free_entry(dat, req);
170 		if (ret < 0) {
171 			nilfs_dat_abort_entry(dat, req);
172 			return ret;
173 		}
174 	}
175 
176 	return 0;
177 }
178 
179 void nilfs_dat_commit_end(struct inode *dat, struct nilfs_palloc_req *req,
180 			  int dead)
181 {
182 	struct nilfs_dat_entry *entry;
183 	__u64 start, end;
184 	sector_t blocknr;
185 	void *kaddr;
186 
187 	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
188 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
189 					     req->pr_entry_bh, kaddr);
190 	end = start = le64_to_cpu(entry->de_start);
191 	if (!dead) {
192 		end = nilfs_mdt_cno(dat);
193 		WARN_ON(start > end);
194 	}
195 	entry->de_end = cpu_to_le64(end);
196 	blocknr = le64_to_cpu(entry->de_blocknr);
197 	kunmap_atomic(kaddr);
198 
199 	if (blocknr == 0)
200 		nilfs_dat_commit_free(dat, req);
201 	else
202 		nilfs_dat_commit_entry(dat, req);
203 }
204 
205 void nilfs_dat_abort_end(struct inode *dat, struct nilfs_palloc_req *req)
206 {
207 	struct nilfs_dat_entry *entry;
208 	__u64 start;
209 	sector_t blocknr;
210 	void *kaddr;
211 
212 	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
213 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
214 					     req->pr_entry_bh, kaddr);
215 	start = le64_to_cpu(entry->de_start);
216 	blocknr = le64_to_cpu(entry->de_blocknr);
217 	kunmap_atomic(kaddr);
218 
219 	if (start == nilfs_mdt_cno(dat) && blocknr == 0)
220 		nilfs_palloc_abort_free_entry(dat, req);
221 	nilfs_dat_abort_entry(dat, req);
222 }
223 
224 int nilfs_dat_prepare_update(struct inode *dat,
225 			     struct nilfs_palloc_req *oldreq,
226 			     struct nilfs_palloc_req *newreq)
227 {
228 	int ret;
229 
230 	ret = nilfs_dat_prepare_end(dat, oldreq);
231 	if (!ret) {
232 		ret = nilfs_dat_prepare_alloc(dat, newreq);
233 		if (ret < 0)
234 			nilfs_dat_abort_end(dat, oldreq);
235 	}
236 	return ret;
237 }
238 
239 void nilfs_dat_commit_update(struct inode *dat,
240 			     struct nilfs_palloc_req *oldreq,
241 			     struct nilfs_palloc_req *newreq, int dead)
242 {
243 	nilfs_dat_commit_end(dat, oldreq, dead);
244 	nilfs_dat_commit_alloc(dat, newreq);
245 }
246 
247 void nilfs_dat_abort_update(struct inode *dat,
248 			    struct nilfs_palloc_req *oldreq,
249 			    struct nilfs_palloc_req *newreq)
250 {
251 	nilfs_dat_abort_end(dat, oldreq);
252 	nilfs_dat_abort_alloc(dat, newreq);
253 }
254 
255 /**
256  * nilfs_dat_mark_dirty -
257  * @dat: DAT file inode
258  * @vblocknr: virtual block number
259  *
260  * Description:
261  *
262  * Return Value: On success, 0 is returned. On error, one of the following
263  * negative error codes is returned.
264  *
265  * %-EIO - I/O error.
266  *
267  * %-ENOMEM - Insufficient amount of memory available.
268  */
269 int nilfs_dat_mark_dirty(struct inode *dat, __u64 vblocknr)
270 {
271 	struct nilfs_palloc_req req;
272 	int ret;
273 
274 	req.pr_entry_nr = vblocknr;
275 	ret = nilfs_dat_prepare_entry(dat, &req, 0);
276 	if (ret == 0)
277 		nilfs_dat_commit_entry(dat, &req);
278 	return ret;
279 }
280 
281 /**
282  * nilfs_dat_freev - free virtual block numbers
283  * @dat: DAT file inode
284  * @vblocknrs: array of virtual block numbers
285  * @nitems: number of virtual block numbers
286  *
287  * Description: nilfs_dat_freev() frees the virtual block numbers specified by
288  * @vblocknrs and @nitems.
289  *
290  * Return Value: On success, 0 is returned. On error, one of the following
291  * negative error codes is returned.
292  *
293  * %-EIO - I/O error.
294  *
295  * %-ENOMEM - Insufficient amount of memory available.
296  *
297  * %-ENOENT - The virtual block number have not been allocated.
298  */
299 int nilfs_dat_freev(struct inode *dat, __u64 *vblocknrs, size_t nitems)
300 {
301 	return nilfs_palloc_freev(dat, vblocknrs, nitems);
302 }
303 
304 /**
305  * nilfs_dat_move - change a block number
306  * @dat: DAT file inode
307  * @vblocknr: virtual block number
308  * @blocknr: block number
309  *
310  * Description: nilfs_dat_move() changes the block number associated with
311  * @vblocknr to @blocknr.
312  *
313  * Return Value: On success, 0 is returned. On error, one of the following
314  * negative error codes is returned.
315  *
316  * %-EIO - I/O error.
317  *
318  * %-ENOMEM - Insufficient amount of memory available.
319  */
320 int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
321 {
322 	struct buffer_head *entry_bh;
323 	struct nilfs_dat_entry *entry;
324 	void *kaddr;
325 	int ret;
326 
327 	ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
328 	if (ret < 0)
329 		return ret;
330 
331 	/*
332 	 * The given disk block number (blocknr) is not yet written to
333 	 * the device at this point.
334 	 *
335 	 * To prevent nilfs_dat_translate() from returning the
336 	 * uncommitted block number, this makes a copy of the entry
337 	 * buffer and redirects nilfs_dat_translate() to the copy.
338 	 */
339 	if (!buffer_nilfs_redirected(entry_bh)) {
340 		ret = nilfs_mdt_freeze_buffer(dat, entry_bh);
341 		if (ret) {
342 			brelse(entry_bh);
343 			return ret;
344 		}
345 	}
346 
347 	kaddr = kmap_atomic(entry_bh->b_page);
348 	entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
349 	if (unlikely(entry->de_blocknr == cpu_to_le64(0))) {
350 		nilfs_crit(dat->i_sb,
351 			   "%s: invalid vblocknr = %llu, [%llu, %llu)",
352 			   __func__, (unsigned long long)vblocknr,
353 			   (unsigned long long)le64_to_cpu(entry->de_start),
354 			   (unsigned long long)le64_to_cpu(entry->de_end));
355 		kunmap_atomic(kaddr);
356 		brelse(entry_bh);
357 		return -EINVAL;
358 	}
359 	WARN_ON(blocknr == 0);
360 	entry->de_blocknr = cpu_to_le64(blocknr);
361 	kunmap_atomic(kaddr);
362 
363 	mark_buffer_dirty(entry_bh);
364 	nilfs_mdt_mark_dirty(dat);
365 
366 	brelse(entry_bh);
367 
368 	return 0;
369 }
370 
371 /**
372  * nilfs_dat_translate - translate a virtual block number to a block number
373  * @dat: DAT file inode
374  * @vblocknr: virtual block number
375  * @blocknrp: pointer to a block number
376  *
377  * Description: nilfs_dat_translate() maps the virtual block number @vblocknr
378  * to the corresponding block number.
379  *
380  * Return Value: On success, 0 is returned and the block number associated
381  * with @vblocknr is stored in the place pointed by @blocknrp. On error, one
382  * of the following negative error codes is returned.
383  *
384  * %-EIO - I/O error.
385  *
386  * %-ENOMEM - Insufficient amount of memory available.
387  *
388  * %-ENOENT - A block number associated with @vblocknr does not exist.
389  */
390 int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
391 {
392 	struct buffer_head *entry_bh, *bh;
393 	struct nilfs_dat_entry *entry;
394 	sector_t blocknr;
395 	void *kaddr;
396 	int ret;
397 
398 	ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
399 	if (ret < 0)
400 		return ret;
401 
402 	if (!nilfs_doing_gc() && buffer_nilfs_redirected(entry_bh)) {
403 		bh = nilfs_mdt_get_frozen_buffer(dat, entry_bh);
404 		if (bh) {
405 			WARN_ON(!buffer_uptodate(bh));
406 			brelse(entry_bh);
407 			entry_bh = bh;
408 		}
409 	}
410 
411 	kaddr = kmap_atomic(entry_bh->b_page);
412 	entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
413 	blocknr = le64_to_cpu(entry->de_blocknr);
414 	if (blocknr == 0) {
415 		ret = -ENOENT;
416 		goto out;
417 	}
418 	*blocknrp = blocknr;
419 
420  out:
421 	kunmap_atomic(kaddr);
422 	brelse(entry_bh);
423 	return ret;
424 }
425 
426 ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned int visz,
427 			    size_t nvi)
428 {
429 	struct buffer_head *entry_bh;
430 	struct nilfs_dat_entry *entry;
431 	struct nilfs_vinfo *vinfo = buf;
432 	__u64 first, last;
433 	void *kaddr;
434 	unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block;
435 	int i, j, n, ret;
436 
437 	for (i = 0; i < nvi; i += n) {
438 		ret = nilfs_palloc_get_entry_block(dat, vinfo->vi_vblocknr,
439 						   0, &entry_bh);
440 		if (ret < 0)
441 			return ret;
442 		kaddr = kmap_atomic(entry_bh->b_page);
443 		/* last virtual block number in this block */
444 		first = vinfo->vi_vblocknr;
445 		do_div(first, entries_per_block);
446 		first *= entries_per_block;
447 		last = first + entries_per_block - 1;
448 		for (j = i, n = 0;
449 		     j < nvi && vinfo->vi_vblocknr >= first &&
450 			     vinfo->vi_vblocknr <= last;
451 		     j++, n++, vinfo = (void *)vinfo + visz) {
452 			entry = nilfs_palloc_block_get_entry(
453 				dat, vinfo->vi_vblocknr, entry_bh, kaddr);
454 			vinfo->vi_start = le64_to_cpu(entry->de_start);
455 			vinfo->vi_end = le64_to_cpu(entry->de_end);
456 			vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr);
457 		}
458 		kunmap_atomic(kaddr);
459 		brelse(entry_bh);
460 	}
461 
462 	return nvi;
463 }
464 
465 /**
466  * nilfs_dat_read - read or get dat inode
467  * @sb: super block instance
468  * @entry_size: size of a dat entry
469  * @raw_inode: on-disk dat inode
470  * @inodep: buffer to store the inode
471  */
472 int nilfs_dat_read(struct super_block *sb, size_t entry_size,
473 		   struct nilfs_inode *raw_inode, struct inode **inodep)
474 {
475 	static struct lock_class_key dat_lock_key;
476 	struct inode *dat;
477 	struct nilfs_dat_info *di;
478 	int err;
479 
480 	if (entry_size > sb->s_blocksize) {
481 		nilfs_err(sb, "too large DAT entry size: %zu bytes",
482 			  entry_size);
483 		return -EINVAL;
484 	} else if (entry_size < NILFS_MIN_DAT_ENTRY_SIZE) {
485 		nilfs_err(sb, "too small DAT entry size: %zu bytes",
486 			  entry_size);
487 		return -EINVAL;
488 	}
489 
490 	dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO);
491 	if (unlikely(!dat))
492 		return -ENOMEM;
493 	if (!(dat->i_state & I_NEW))
494 		goto out;
495 
496 	err = nilfs_mdt_init(dat, NILFS_MDT_GFP, sizeof(*di));
497 	if (err)
498 		goto failed;
499 
500 	err = nilfs_palloc_init_blockgroup(dat, entry_size);
501 	if (err)
502 		goto failed;
503 
504 	di = NILFS_DAT_I(dat);
505 	lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
506 	nilfs_palloc_setup_cache(dat, &di->palloc_cache);
507 	err = nilfs_mdt_setup_shadow_map(dat, &di->shadow);
508 	if (err)
509 		goto failed;
510 
511 	err = nilfs_read_inode_common(dat, raw_inode);
512 	if (err)
513 		goto failed;
514 
515 	unlock_new_inode(dat);
516  out:
517 	*inodep = dat;
518 	return 0;
519  failed:
520 	iget_failed(dat);
521 	return err;
522 }
523