1ae98043fSRyusuke Konishi // SPDX-License-Identifier: GPL-2.0+
2a17564f5SKoji Sato /*
394ee1d91SRyusuke Konishi * NILFS disk address translation.
4a17564f5SKoji Sato *
5a17564f5SKoji Sato * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
6a17564f5SKoji Sato *
74b420ab4SRyusuke Konishi * Written by Koji Sato.
8a17564f5SKoji Sato */
9a17564f5SKoji Sato
10a17564f5SKoji Sato #include <linux/types.h>
11a17564f5SKoji Sato #include <linux/buffer_head.h>
12a17564f5SKoji Sato #include <linux/string.h>
13a17564f5SKoji Sato #include <linux/errno.h>
14a17564f5SKoji Sato #include "nilfs.h"
15a17564f5SKoji Sato #include "mdt.h"
16a17564f5SKoji Sato #include "alloc.h"
17a17564f5SKoji Sato #include "dat.h"
18a17564f5SKoji Sato
19a17564f5SKoji Sato
20a17564f5SKoji Sato #define NILFS_CNO_MIN ((__u64)1)
21a17564f5SKoji Sato #define NILFS_CNO_MAX (~(__u64)0)
22a17564f5SKoji Sato
23f5974c8fSVyacheslav Dubeyko /**
24f5974c8fSVyacheslav Dubeyko * struct nilfs_dat_info - on-memory private data of DAT file
25f5974c8fSVyacheslav Dubeyko * @mi: on-memory private data of metadata file
26f5974c8fSVyacheslav Dubeyko * @palloc_cache: persistent object allocator cache of DAT file
27f5974c8fSVyacheslav Dubeyko * @shadow: shadow map of DAT file
28f5974c8fSVyacheslav Dubeyko */
298908b2f7SRyusuke Konishi struct nilfs_dat_info {
308908b2f7SRyusuke Konishi struct nilfs_mdt_info mi;
318908b2f7SRyusuke Konishi struct nilfs_palloc_cache palloc_cache;
32c1c1d709SRyusuke Konishi struct nilfs_shadow_map shadow;
338908b2f7SRyusuke Konishi };
348908b2f7SRyusuke Konishi
NILFS_DAT_I(struct inode * dat)358908b2f7SRyusuke Konishi static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat)
368908b2f7SRyusuke Konishi {
378908b2f7SRyusuke Konishi return (struct nilfs_dat_info *)NILFS_MDT(dat);
388908b2f7SRyusuke Konishi }
398908b2f7SRyusuke Konishi
nilfs_dat_prepare_entry(struct inode * dat,struct nilfs_palloc_req * req,int create)40a17564f5SKoji Sato static int nilfs_dat_prepare_entry(struct inode *dat,
41a17564f5SKoji Sato struct nilfs_palloc_req *req, int create)
42a17564f5SKoji Sato {
435124a0a5SRyusuke Konishi int ret;
445124a0a5SRyusuke Konishi
455124a0a5SRyusuke Konishi ret = nilfs_palloc_get_entry_block(dat, req->pr_entry_nr,
46a17564f5SKoji Sato create, &req->pr_entry_bh);
475124a0a5SRyusuke Konishi if (unlikely(ret == -ENOENT)) {
485124a0a5SRyusuke Konishi nilfs_err(dat->i_sb,
495124a0a5SRyusuke Konishi "DAT doesn't have a block to manage vblocknr = %llu",
505124a0a5SRyusuke Konishi (unsigned long long)req->pr_entry_nr);
515124a0a5SRyusuke Konishi /*
525124a0a5SRyusuke Konishi * Return internal code -EINVAL to notify bmap layer of
535124a0a5SRyusuke Konishi * metadata corruption.
545124a0a5SRyusuke Konishi */
555124a0a5SRyusuke Konishi ret = -EINVAL;
565124a0a5SRyusuke Konishi }
575124a0a5SRyusuke Konishi return ret;
58a17564f5SKoji Sato }
59a17564f5SKoji Sato
nilfs_dat_commit_entry(struct inode * dat,struct nilfs_palloc_req * req)60a17564f5SKoji Sato static void nilfs_dat_commit_entry(struct inode *dat,
61a17564f5SKoji Sato struct nilfs_palloc_req *req)
62a17564f5SKoji Sato {
635fc7b141SRyusuke Konishi mark_buffer_dirty(req->pr_entry_bh);
64a17564f5SKoji Sato nilfs_mdt_mark_dirty(dat);
65a17564f5SKoji Sato brelse(req->pr_entry_bh);
66a17564f5SKoji Sato }
67a17564f5SKoji Sato
nilfs_dat_abort_entry(struct inode * dat,struct nilfs_palloc_req * req)68a17564f5SKoji Sato static void nilfs_dat_abort_entry(struct inode *dat,
69a17564f5SKoji Sato struct nilfs_palloc_req *req)
70a17564f5SKoji Sato {
71a17564f5SKoji Sato brelse(req->pr_entry_bh);
72a17564f5SKoji Sato }
73a17564f5SKoji Sato
nilfs_dat_prepare_alloc(struct inode * dat,struct nilfs_palloc_req * req)74a17564f5SKoji Sato int nilfs_dat_prepare_alloc(struct inode *dat, struct nilfs_palloc_req *req)
75a17564f5SKoji Sato {
76a17564f5SKoji Sato int ret;
77a17564f5SKoji Sato
78*95b13625SRyusuke Konishi ret = nilfs_palloc_prepare_alloc_entry(dat, req, true);
79a17564f5SKoji Sato if (ret < 0)
80a17564f5SKoji Sato return ret;
81a17564f5SKoji Sato
82a17564f5SKoji Sato ret = nilfs_dat_prepare_entry(dat, req, 1);
83a17564f5SKoji Sato if (ret < 0)
84a17564f5SKoji Sato nilfs_palloc_abort_alloc_entry(dat, req);
85a17564f5SKoji Sato
86a17564f5SKoji Sato return ret;
87a17564f5SKoji Sato }
88a17564f5SKoji Sato
nilfs_dat_commit_alloc(struct inode * dat,struct nilfs_palloc_req * req)89a17564f5SKoji Sato void nilfs_dat_commit_alloc(struct inode *dat, struct nilfs_palloc_req *req)
90a17564f5SKoji Sato {
91a17564f5SKoji Sato struct nilfs_dat_entry *entry;
92a17564f5SKoji Sato void *kaddr;
93a17564f5SKoji Sato
947b9c0976SCong Wang kaddr = kmap_atomic(req->pr_entry_bh->b_page);
95a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
96a17564f5SKoji Sato req->pr_entry_bh, kaddr);
97a17564f5SKoji Sato entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
98a17564f5SKoji Sato entry->de_end = cpu_to_le64(NILFS_CNO_MAX);
99a17564f5SKoji Sato entry->de_blocknr = cpu_to_le64(0);
1007b9c0976SCong Wang kunmap_atomic(kaddr);
101a17564f5SKoji Sato
102a17564f5SKoji Sato nilfs_palloc_commit_alloc_entry(dat, req);
103a17564f5SKoji Sato nilfs_dat_commit_entry(dat, req);
104a17564f5SKoji Sato }
105a17564f5SKoji Sato
nilfs_dat_abort_alloc(struct inode * dat,struct nilfs_palloc_req * req)106a17564f5SKoji Sato void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req)
107a17564f5SKoji Sato {
108a17564f5SKoji Sato nilfs_dat_abort_entry(dat, req);
109a17564f5SKoji Sato nilfs_palloc_abort_alloc_entry(dat, req);
110a17564f5SKoji Sato }
111a17564f5SKoji Sato
nilfs_dat_commit_free(struct inode * dat,struct nilfs_palloc_req * req)112abc0b50bSJiro SEKIBA static void nilfs_dat_commit_free(struct inode *dat,
113abc0b50bSJiro SEKIBA struct nilfs_palloc_req *req)
114a17564f5SKoji Sato {
115a17564f5SKoji Sato struct nilfs_dat_entry *entry;
116a17564f5SKoji Sato void *kaddr;
117a17564f5SKoji Sato
1187b9c0976SCong Wang kaddr = kmap_atomic(req->pr_entry_bh->b_page);
119a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
120a17564f5SKoji Sato req->pr_entry_bh, kaddr);
121a17564f5SKoji Sato entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
122a17564f5SKoji Sato entry->de_end = cpu_to_le64(NILFS_CNO_MIN);
123a17564f5SKoji Sato entry->de_blocknr = cpu_to_le64(0);
1247b9c0976SCong Wang kunmap_atomic(kaddr);
125a17564f5SKoji Sato
126a17564f5SKoji Sato nilfs_dat_commit_entry(dat, req);
127f0a0ccdaSZhangPeng
128f0a0ccdaSZhangPeng if (unlikely(req->pr_desc_bh == NULL || req->pr_bitmap_bh == NULL)) {
129f0a0ccdaSZhangPeng nilfs_error(dat->i_sb,
130f0a0ccdaSZhangPeng "state inconsistency probably due to duplicate use of vblocknr = %llu",
131f0a0ccdaSZhangPeng (unsigned long long)req->pr_entry_nr);
132f0a0ccdaSZhangPeng return;
133f0a0ccdaSZhangPeng }
134a17564f5SKoji Sato nilfs_palloc_commit_free_entry(dat, req);
135a17564f5SKoji Sato }
136a17564f5SKoji Sato
nilfs_dat_prepare_start(struct inode * dat,struct nilfs_palloc_req * req)137a17564f5SKoji Sato int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req)
138a17564f5SKoji Sato {
1395124a0a5SRyusuke Konishi return nilfs_dat_prepare_entry(dat, req, 0);
140a17564f5SKoji Sato }
141a17564f5SKoji Sato
nilfs_dat_commit_start(struct inode * dat,struct nilfs_palloc_req * req,sector_t blocknr)142a17564f5SKoji Sato void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
143a17564f5SKoji Sato sector_t blocknr)
144a17564f5SKoji Sato {
145a17564f5SKoji Sato struct nilfs_dat_entry *entry;
146a17564f5SKoji Sato void *kaddr;
147a17564f5SKoji Sato
1487b9c0976SCong Wang kaddr = kmap_atomic(req->pr_entry_bh->b_page);
149a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
150a17564f5SKoji Sato req->pr_entry_bh, kaddr);
151a17564f5SKoji Sato entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat));
152a17564f5SKoji Sato entry->de_blocknr = cpu_to_le64(blocknr);
1537b9c0976SCong Wang kunmap_atomic(kaddr);
154a17564f5SKoji Sato
155a17564f5SKoji Sato nilfs_dat_commit_entry(dat, req);
156a17564f5SKoji Sato }
157a17564f5SKoji Sato
nilfs_dat_prepare_end(struct inode * dat,struct nilfs_palloc_req * req)158a17564f5SKoji Sato int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
159a17564f5SKoji Sato {
160a17564f5SKoji Sato struct nilfs_dat_entry *entry;
161602ce7b8SRyusuke Konishi __u64 start;
162a17564f5SKoji Sato sector_t blocknr;
163a17564f5SKoji Sato void *kaddr;
164a17564f5SKoji Sato int ret;
165a17564f5SKoji Sato
166a17564f5SKoji Sato ret = nilfs_dat_prepare_entry(dat, req, 0);
1675124a0a5SRyusuke Konishi if (ret < 0)
168a17564f5SKoji Sato return ret;
169a17564f5SKoji Sato
1707b9c0976SCong Wang kaddr = kmap_atomic(req->pr_entry_bh->b_page);
171a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
172a17564f5SKoji Sato req->pr_entry_bh, kaddr);
173602ce7b8SRyusuke Konishi start = le64_to_cpu(entry->de_start);
174a17564f5SKoji Sato blocknr = le64_to_cpu(entry->de_blocknr);
1757b9c0976SCong Wang kunmap_atomic(kaddr);
176a17564f5SKoji Sato
177a17564f5SKoji Sato if (blocknr == 0) {
178a17564f5SKoji Sato ret = nilfs_palloc_prepare_free_entry(dat, req);
179a17564f5SKoji Sato if (ret < 0) {
180a17564f5SKoji Sato nilfs_dat_abort_entry(dat, req);
181a17564f5SKoji Sato return ret;
182a17564f5SKoji Sato }
183a17564f5SKoji Sato }
184602ce7b8SRyusuke Konishi if (unlikely(start > nilfs_mdt_cno(dat))) {
185602ce7b8SRyusuke Konishi nilfs_err(dat->i_sb,
186602ce7b8SRyusuke Konishi "vblocknr = %llu has abnormal lifetime: start cno (= %llu) > current cno (= %llu)",
187602ce7b8SRyusuke Konishi (unsigned long long)req->pr_entry_nr,
188602ce7b8SRyusuke Konishi (unsigned long long)start,
189602ce7b8SRyusuke Konishi (unsigned long long)nilfs_mdt_cno(dat));
190602ce7b8SRyusuke Konishi nilfs_dat_abort_entry(dat, req);
191602ce7b8SRyusuke Konishi return -EINVAL;
192602ce7b8SRyusuke Konishi }
193a17564f5SKoji Sato
194a17564f5SKoji Sato return 0;
195a17564f5SKoji Sato }
196a17564f5SKoji Sato
nilfs_dat_commit_end(struct inode * dat,struct nilfs_palloc_req * req,int dead)197a17564f5SKoji Sato void nilfs_dat_commit_end(struct inode *dat, struct nilfs_palloc_req *req,
198a17564f5SKoji Sato int dead)
199a17564f5SKoji Sato {
200a17564f5SKoji Sato struct nilfs_dat_entry *entry;
201a17564f5SKoji Sato __u64 start, end;
202a17564f5SKoji Sato sector_t blocknr;
203a17564f5SKoji Sato void *kaddr;
204a17564f5SKoji Sato
2057b9c0976SCong Wang kaddr = kmap_atomic(req->pr_entry_bh->b_page);
206a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
207a17564f5SKoji Sato req->pr_entry_bh, kaddr);
208a17564f5SKoji Sato end = start = le64_to_cpu(entry->de_start);
209a17564f5SKoji Sato if (!dead) {
210a17564f5SKoji Sato end = nilfs_mdt_cno(dat);
2111f5abe7eSRyusuke Konishi WARN_ON(start > end);
212a17564f5SKoji Sato }
213a17564f5SKoji Sato entry->de_end = cpu_to_le64(end);
214a17564f5SKoji Sato blocknr = le64_to_cpu(entry->de_blocknr);
2157b9c0976SCong Wang kunmap_atomic(kaddr);
216a17564f5SKoji Sato
217a17564f5SKoji Sato if (blocknr == 0)
218a17564f5SKoji Sato nilfs_dat_commit_free(dat, req);
219a17564f5SKoji Sato else
220a17564f5SKoji Sato nilfs_dat_commit_entry(dat, req);
221a17564f5SKoji Sato }
222a17564f5SKoji Sato
nilfs_dat_abort_end(struct inode * dat,struct nilfs_palloc_req * req)223a17564f5SKoji Sato void nilfs_dat_abort_end(struct inode *dat, struct nilfs_palloc_req *req)
224a17564f5SKoji Sato {
225a17564f5SKoji Sato struct nilfs_dat_entry *entry;
226a17564f5SKoji Sato __u64 start;
227a17564f5SKoji Sato sector_t blocknr;
228a17564f5SKoji Sato void *kaddr;
229a17564f5SKoji Sato
2307b9c0976SCong Wang kaddr = kmap_atomic(req->pr_entry_bh->b_page);
231a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
232a17564f5SKoji Sato req->pr_entry_bh, kaddr);
233a17564f5SKoji Sato start = le64_to_cpu(entry->de_start);
234a17564f5SKoji Sato blocknr = le64_to_cpu(entry->de_blocknr);
2357b9c0976SCong Wang kunmap_atomic(kaddr);
236a17564f5SKoji Sato
237a17564f5SKoji Sato if (start == nilfs_mdt_cno(dat) && blocknr == 0)
238a17564f5SKoji Sato nilfs_palloc_abort_free_entry(dat, req);
239a17564f5SKoji Sato nilfs_dat_abort_entry(dat, req);
240a17564f5SKoji Sato }
241a17564f5SKoji Sato
nilfs_dat_prepare_update(struct inode * dat,struct nilfs_palloc_req * oldreq,struct nilfs_palloc_req * newreq)242bd8169efSRyusuke Konishi int nilfs_dat_prepare_update(struct inode *dat,
243bd8169efSRyusuke Konishi struct nilfs_palloc_req *oldreq,
244bd8169efSRyusuke Konishi struct nilfs_palloc_req *newreq)
245bd8169efSRyusuke Konishi {
246bd8169efSRyusuke Konishi int ret;
247bd8169efSRyusuke Konishi
248bd8169efSRyusuke Konishi ret = nilfs_dat_prepare_end(dat, oldreq);
249bd8169efSRyusuke Konishi if (!ret) {
250bd8169efSRyusuke Konishi ret = nilfs_dat_prepare_alloc(dat, newreq);
251bd8169efSRyusuke Konishi if (ret < 0)
252bd8169efSRyusuke Konishi nilfs_dat_abort_end(dat, oldreq);
253bd8169efSRyusuke Konishi }
254bd8169efSRyusuke Konishi return ret;
255bd8169efSRyusuke Konishi }
256bd8169efSRyusuke Konishi
nilfs_dat_commit_update(struct inode * dat,struct nilfs_palloc_req * oldreq,struct nilfs_palloc_req * newreq,int dead)257bd8169efSRyusuke Konishi void nilfs_dat_commit_update(struct inode *dat,
258bd8169efSRyusuke Konishi struct nilfs_palloc_req *oldreq,
259bd8169efSRyusuke Konishi struct nilfs_palloc_req *newreq, int dead)
260bd8169efSRyusuke Konishi {
261bd8169efSRyusuke Konishi nilfs_dat_commit_end(dat, oldreq, dead);
262bd8169efSRyusuke Konishi nilfs_dat_commit_alloc(dat, newreq);
263bd8169efSRyusuke Konishi }
264bd8169efSRyusuke Konishi
nilfs_dat_abort_update(struct inode * dat,struct nilfs_palloc_req * oldreq,struct nilfs_palloc_req * newreq)265bd8169efSRyusuke Konishi void nilfs_dat_abort_update(struct inode *dat,
266bd8169efSRyusuke Konishi struct nilfs_palloc_req *oldreq,
267bd8169efSRyusuke Konishi struct nilfs_palloc_req *newreq)
268bd8169efSRyusuke Konishi {
269bd8169efSRyusuke Konishi nilfs_dat_abort_end(dat, oldreq);
270bd8169efSRyusuke Konishi nilfs_dat_abort_alloc(dat, newreq);
271bd8169efSRyusuke Konishi }
272bd8169efSRyusuke Konishi
273a17564f5SKoji Sato /**
274a17564f5SKoji Sato * nilfs_dat_mark_dirty -
275a17564f5SKoji Sato * @dat: DAT file inode
276a17564f5SKoji Sato * @vblocknr: virtual block number
277a17564f5SKoji Sato *
278a17564f5SKoji Sato * Description:
279a17564f5SKoji Sato *
280a17564f5SKoji Sato * Return Value: On success, 0 is returned. On error, one of the following
281a17564f5SKoji Sato * negative error codes is returned.
282a17564f5SKoji Sato *
283a17564f5SKoji Sato * %-EIO - I/O error.
284a17564f5SKoji Sato *
285a17564f5SKoji Sato * %-ENOMEM - Insufficient amount of memory available.
286a17564f5SKoji Sato */
nilfs_dat_mark_dirty(struct inode * dat,__u64 vblocknr)287a17564f5SKoji Sato int nilfs_dat_mark_dirty(struct inode *dat, __u64 vblocknr)
288a17564f5SKoji Sato {
289a17564f5SKoji Sato struct nilfs_palloc_req req;
290a17564f5SKoji Sato int ret;
291a17564f5SKoji Sato
292a17564f5SKoji Sato req.pr_entry_nr = vblocknr;
293a17564f5SKoji Sato ret = nilfs_dat_prepare_entry(dat, &req, 0);
294a17564f5SKoji Sato if (ret == 0)
295a17564f5SKoji Sato nilfs_dat_commit_entry(dat, &req);
296a17564f5SKoji Sato return ret;
297a17564f5SKoji Sato }
298a17564f5SKoji Sato
299a17564f5SKoji Sato /**
300a17564f5SKoji Sato * nilfs_dat_freev - free virtual block numbers
301a17564f5SKoji Sato * @dat: DAT file inode
302a17564f5SKoji Sato * @vblocknrs: array of virtual block numbers
303a17564f5SKoji Sato * @nitems: number of virtual block numbers
304a17564f5SKoji Sato *
305a17564f5SKoji Sato * Description: nilfs_dat_freev() frees the virtual block numbers specified by
306a17564f5SKoji Sato * @vblocknrs and @nitems.
307a17564f5SKoji Sato *
308a17564f5SKoji Sato * Return Value: On success, 0 is returned. On error, one of the following
3097a65004bSRyusuke Konishi * negative error codes is returned.
310a17564f5SKoji Sato *
311a17564f5SKoji Sato * %-EIO - I/O error.
312a17564f5SKoji Sato *
313a17564f5SKoji Sato * %-ENOMEM - Insufficient amount of memory available.
314a17564f5SKoji Sato *
315a17564f5SKoji Sato * %-ENOENT - The virtual block number have not been allocated.
316a17564f5SKoji Sato */
nilfs_dat_freev(struct inode * dat,__u64 * vblocknrs,size_t nitems)317a17564f5SKoji Sato int nilfs_dat_freev(struct inode *dat, __u64 *vblocknrs, size_t nitems)
318a17564f5SKoji Sato {
319a17564f5SKoji Sato return nilfs_palloc_freev(dat, vblocknrs, nitems);
320a17564f5SKoji Sato }
321a17564f5SKoji Sato
322a17564f5SKoji Sato /**
323a17564f5SKoji Sato * nilfs_dat_move - change a block number
324a17564f5SKoji Sato * @dat: DAT file inode
325a17564f5SKoji Sato * @vblocknr: virtual block number
326a17564f5SKoji Sato * @blocknr: block number
327a17564f5SKoji Sato *
328a17564f5SKoji Sato * Description: nilfs_dat_move() changes the block number associated with
329a17564f5SKoji Sato * @vblocknr to @blocknr.
330a17564f5SKoji Sato *
331a17564f5SKoji Sato * Return Value: On success, 0 is returned. On error, one of the following
332a17564f5SKoji Sato * negative error codes is returned.
333a17564f5SKoji Sato *
334a17564f5SKoji Sato * %-EIO - I/O error.
335a17564f5SKoji Sato *
336a17564f5SKoji Sato * %-ENOMEM - Insufficient amount of memory available.
337a17564f5SKoji Sato */
nilfs_dat_move(struct inode * dat,__u64 vblocknr,sector_t blocknr)338a17564f5SKoji Sato int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
339a17564f5SKoji Sato {
340a17564f5SKoji Sato struct buffer_head *entry_bh;
341a17564f5SKoji Sato struct nilfs_dat_entry *entry;
342a17564f5SKoji Sato void *kaddr;
343a17564f5SKoji Sato int ret;
344a17564f5SKoji Sato
345a17564f5SKoji Sato ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
346a17564f5SKoji Sato if (ret < 0)
347a17564f5SKoji Sato return ret;
348c1c1d709SRyusuke Konishi
349c1c1d709SRyusuke Konishi /*
350c1c1d709SRyusuke Konishi * The given disk block number (blocknr) is not yet written to
351c1c1d709SRyusuke Konishi * the device at this point.
352c1c1d709SRyusuke Konishi *
353c1c1d709SRyusuke Konishi * To prevent nilfs_dat_translate() from returning the
354f6c26ec5SRyusuke Konishi * uncommitted block number, this makes a copy of the entry
355c1c1d709SRyusuke Konishi * buffer and redirects nilfs_dat_translate() to the copy.
356c1c1d709SRyusuke Konishi */
357c1c1d709SRyusuke Konishi if (!buffer_nilfs_redirected(entry_bh)) {
358c1c1d709SRyusuke Konishi ret = nilfs_mdt_freeze_buffer(dat, entry_bh);
359c1c1d709SRyusuke Konishi if (ret) {
360c1c1d709SRyusuke Konishi brelse(entry_bh);
361c1c1d709SRyusuke Konishi return ret;
362c1c1d709SRyusuke Konishi }
363c1c1d709SRyusuke Konishi }
364c1c1d709SRyusuke Konishi
3657b9c0976SCong Wang kaddr = kmap_atomic(entry_bh->b_page);
366a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
3671f5abe7eSRyusuke Konishi if (unlikely(entry->de_blocknr == cpu_to_le64(0))) {
368a1d0747aSJoe Perches nilfs_crit(dat->i_sb,
369feee880fSRyusuke Konishi "%s: invalid vblocknr = %llu, [%llu, %llu)",
370feee880fSRyusuke Konishi __func__, (unsigned long long)vblocknr,
371a17564f5SKoji Sato (unsigned long long)le64_to_cpu(entry->de_start),
372a17564f5SKoji Sato (unsigned long long)le64_to_cpu(entry->de_end));
3737b9c0976SCong Wang kunmap_atomic(kaddr);
3741f5abe7eSRyusuke Konishi brelse(entry_bh);
3751f5abe7eSRyusuke Konishi return -EINVAL;
376a17564f5SKoji Sato }
3771f5abe7eSRyusuke Konishi WARN_ON(blocknr == 0);
378a17564f5SKoji Sato entry->de_blocknr = cpu_to_le64(blocknr);
3797b9c0976SCong Wang kunmap_atomic(kaddr);
380a17564f5SKoji Sato
3815fc7b141SRyusuke Konishi mark_buffer_dirty(entry_bh);
382a17564f5SKoji Sato nilfs_mdt_mark_dirty(dat);
383a17564f5SKoji Sato
384a17564f5SKoji Sato brelse(entry_bh);
385a17564f5SKoji Sato
386a17564f5SKoji Sato return 0;
387a17564f5SKoji Sato }
388a17564f5SKoji Sato
389a17564f5SKoji Sato /**
390a17564f5SKoji Sato * nilfs_dat_translate - translate a virtual block number to a block number
391a17564f5SKoji Sato * @dat: DAT file inode
392a17564f5SKoji Sato * @vblocknr: virtual block number
393a17564f5SKoji Sato * @blocknrp: pointer to a block number
394a17564f5SKoji Sato *
395a17564f5SKoji Sato * Description: nilfs_dat_translate() maps the virtual block number @vblocknr
396a17564f5SKoji Sato * to the corresponding block number.
397a17564f5SKoji Sato *
398a17564f5SKoji Sato * Return Value: On success, 0 is returned and the block number associated
399a17564f5SKoji Sato * with @vblocknr is stored in the place pointed by @blocknrp. On error, one
400a17564f5SKoji Sato * of the following negative error codes is returned.
401a17564f5SKoji Sato *
402a17564f5SKoji Sato * %-EIO - I/O error.
403a17564f5SKoji Sato *
404a17564f5SKoji Sato * %-ENOMEM - Insufficient amount of memory available.
405a17564f5SKoji Sato *
406a17564f5SKoji Sato * %-ENOENT - A block number associated with @vblocknr does not exist.
407a17564f5SKoji Sato */
nilfs_dat_translate(struct inode * dat,__u64 vblocknr,sector_t * blocknrp)408a17564f5SKoji Sato int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
409a17564f5SKoji Sato {
410c1c1d709SRyusuke Konishi struct buffer_head *entry_bh, *bh;
411a17564f5SKoji Sato struct nilfs_dat_entry *entry;
412a17564f5SKoji Sato sector_t blocknr;
413a17564f5SKoji Sato void *kaddr;
414a17564f5SKoji Sato int ret;
415a17564f5SKoji Sato
416a17564f5SKoji Sato ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
417a17564f5SKoji Sato if (ret < 0)
418a17564f5SKoji Sato return ret;
419a17564f5SKoji Sato
420c1c1d709SRyusuke Konishi if (!nilfs_doing_gc() && buffer_nilfs_redirected(entry_bh)) {
421c1c1d709SRyusuke Konishi bh = nilfs_mdt_get_frozen_buffer(dat, entry_bh);
422c1c1d709SRyusuke Konishi if (bh) {
423c1c1d709SRyusuke Konishi WARN_ON(!buffer_uptodate(bh));
424c1c1d709SRyusuke Konishi brelse(entry_bh);
425c1c1d709SRyusuke Konishi entry_bh = bh;
426c1c1d709SRyusuke Konishi }
427c1c1d709SRyusuke Konishi }
428c1c1d709SRyusuke Konishi
4297b9c0976SCong Wang kaddr = kmap_atomic(entry_bh->b_page);
430a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
431a17564f5SKoji Sato blocknr = le64_to_cpu(entry->de_blocknr);
432a17564f5SKoji Sato if (blocknr == 0) {
433a17564f5SKoji Sato ret = -ENOENT;
434a17564f5SKoji Sato goto out;
435a17564f5SKoji Sato }
436a17564f5SKoji Sato *blocknrp = blocknr;
437a17564f5SKoji Sato
438a17564f5SKoji Sato out:
4397b9c0976SCong Wang kunmap_atomic(kaddr);
440a17564f5SKoji Sato brelse(entry_bh);
441a17564f5SKoji Sato return ret;
442a17564f5SKoji Sato }
443a17564f5SKoji Sato
nilfs_dat_get_vinfo(struct inode * dat,void * buf,unsigned int visz,size_t nvi)4440c6c44cbSRyusuke Konishi ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned int visz,
445a17564f5SKoji Sato size_t nvi)
446a17564f5SKoji Sato {
447a17564f5SKoji Sato struct buffer_head *entry_bh;
448a17564f5SKoji Sato struct nilfs_dat_entry *entry;
449003ff182SRyusuke Konishi struct nilfs_vinfo *vinfo = buf;
450a17564f5SKoji Sato __u64 first, last;
451a17564f5SKoji Sato void *kaddr;
452a17564f5SKoji Sato unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block;
453a17564f5SKoji Sato int i, j, n, ret;
454a17564f5SKoji Sato
455a17564f5SKoji Sato for (i = 0; i < nvi; i += n) {
456003ff182SRyusuke Konishi ret = nilfs_palloc_get_entry_block(dat, vinfo->vi_vblocknr,
457a17564f5SKoji Sato 0, &entry_bh);
458a17564f5SKoji Sato if (ret < 0)
459a17564f5SKoji Sato return ret;
4607b9c0976SCong Wang kaddr = kmap_atomic(entry_bh->b_page);
461a17564f5SKoji Sato /* last virtual block number in this block */
462003ff182SRyusuke Konishi first = vinfo->vi_vblocknr;
463a17564f5SKoji Sato do_div(first, entries_per_block);
464a17564f5SKoji Sato first *= entries_per_block;
465a17564f5SKoji Sato last = first + entries_per_block - 1;
466a17564f5SKoji Sato for (j = i, n = 0;
467003ff182SRyusuke Konishi j < nvi && vinfo->vi_vblocknr >= first &&
468003ff182SRyusuke Konishi vinfo->vi_vblocknr <= last;
469003ff182SRyusuke Konishi j++, n++, vinfo = (void *)vinfo + visz) {
470a17564f5SKoji Sato entry = nilfs_palloc_block_get_entry(
471003ff182SRyusuke Konishi dat, vinfo->vi_vblocknr, entry_bh, kaddr);
472003ff182SRyusuke Konishi vinfo->vi_start = le64_to_cpu(entry->de_start);
473003ff182SRyusuke Konishi vinfo->vi_end = le64_to_cpu(entry->de_end);
474003ff182SRyusuke Konishi vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr);
475a17564f5SKoji Sato }
4767b9c0976SCong Wang kunmap_atomic(kaddr);
477a17564f5SKoji Sato brelse(entry_bh);
478a17564f5SKoji Sato }
479a17564f5SKoji Sato
480a17564f5SKoji Sato return nvi;
481a17564f5SKoji Sato }
48279739565SRyusuke Konishi
48379739565SRyusuke Konishi /**
484f1e89c86SRyusuke Konishi * nilfs_dat_read - read or get dat inode
485f1e89c86SRyusuke Konishi * @sb: super block instance
48679739565SRyusuke Konishi * @entry_size: size of a dat entry
487f1e89c86SRyusuke Konishi * @raw_inode: on-disk dat inode
488f1e89c86SRyusuke Konishi * @inodep: buffer to store the inode
48979739565SRyusuke Konishi */
nilfs_dat_read(struct super_block * sb,size_t entry_size,struct nilfs_inode * raw_inode,struct inode ** inodep)490f1e89c86SRyusuke Konishi int nilfs_dat_read(struct super_block *sb, size_t entry_size,
491f1e89c86SRyusuke Konishi struct nilfs_inode *raw_inode, struct inode **inodep)
49279739565SRyusuke Konishi {
49379739565SRyusuke Konishi static struct lock_class_key dat_lock_key;
49479739565SRyusuke Konishi struct inode *dat;
4958908b2f7SRyusuke Konishi struct nilfs_dat_info *di;
49679739565SRyusuke Konishi int err;
49779739565SRyusuke Konishi
4980ec060d1SRyusuke Konishi if (entry_size > sb->s_blocksize) {
499a1d0747aSJoe Perches nilfs_err(sb, "too large DAT entry size: %zu bytes",
5000ec060d1SRyusuke Konishi entry_size);
5010ec060d1SRyusuke Konishi return -EINVAL;
5020ec060d1SRyusuke Konishi } else if (entry_size < NILFS_MIN_DAT_ENTRY_SIZE) {
503a1d0747aSJoe Perches nilfs_err(sb, "too small DAT entry size: %zu bytes",
5040ec060d1SRyusuke Konishi entry_size);
5050ec060d1SRyusuke Konishi return -EINVAL;
5060ec060d1SRyusuke Konishi }
5070ec060d1SRyusuke Konishi
508f1e89c86SRyusuke Konishi dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO);
509f1e89c86SRyusuke Konishi if (unlikely(!dat))
510f1e89c86SRyusuke Konishi return -ENOMEM;
511f1e89c86SRyusuke Konishi if (!(dat->i_state & I_NEW))
512f1e89c86SRyusuke Konishi goto out;
513f1e89c86SRyusuke Konishi
514f1e89c86SRyusuke Konishi err = nilfs_mdt_init(dat, NILFS_MDT_GFP, sizeof(*di));
515f1e89c86SRyusuke Konishi if (err)
516f1e89c86SRyusuke Konishi goto failed;
517f1e89c86SRyusuke Konishi
51879739565SRyusuke Konishi err = nilfs_palloc_init_blockgroup(dat, entry_size);
519f1e89c86SRyusuke Konishi if (err)
520f1e89c86SRyusuke Konishi goto failed;
5218908b2f7SRyusuke Konishi
5228908b2f7SRyusuke Konishi di = NILFS_DAT_I(dat);
5238908b2f7SRyusuke Konishi lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
5248908b2f7SRyusuke Konishi nilfs_palloc_setup_cache(dat, &di->palloc_cache);
5256e211930SRyusuke Konishi err = nilfs_mdt_setup_shadow_map(dat, &di->shadow);
5266e211930SRyusuke Konishi if (err)
5276e211930SRyusuke Konishi goto failed;
528f1e89c86SRyusuke Konishi
529f1e89c86SRyusuke Konishi err = nilfs_read_inode_common(dat, raw_inode);
530f1e89c86SRyusuke Konishi if (err)
531f1e89c86SRyusuke Konishi goto failed;
532f1e89c86SRyusuke Konishi
533f1e89c86SRyusuke Konishi unlock_new_inode(dat);
534f1e89c86SRyusuke Konishi out:
535f1e89c86SRyusuke Konishi *inodep = dat;
536f1e89c86SRyusuke Konishi return 0;
537f1e89c86SRyusuke Konishi failed:
538f1e89c86SRyusuke Konishi iget_failed(dat);
539f1e89c86SRyusuke Konishi return err;
54079739565SRyusuke Konishi }
541