Blame view

fs/nilfs2/direct.c 8.95 KB
36a580eb4   Koji Sato   nilfs2: direct bl...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /*
   * direct.c - NILFS direct block pointer.
   *
   * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
   * Written by Koji Sato <koji@osrg.net>.
   */
  
  #include <linux/errno.h>
  #include "nilfs.h"
  #include "page.h"
  #include "direct.h"
  #include "alloc.h"
c3a7abf06   Ryusuke Konishi   nilfs2: support c...
28
  #include "dat.h"
36a580eb4   Koji Sato   nilfs2: direct bl...
29

10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
30
  static inline __le64 *nilfs_direct_dptrs(const struct nilfs_bmap *direct)
36a580eb4   Koji Sato   nilfs2: direct bl...
31
32
  {
  	return (__le64 *)
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
33
  		((struct nilfs_direct_node *)direct->b_u.u_data + 1);
36a580eb4   Koji Sato   nilfs2: direct bl...
34
35
36
  }
  
  static inline __u64
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
37
  nilfs_direct_get_ptr(const struct nilfs_bmap *direct, __u64 key)
36a580eb4   Koji Sato   nilfs2: direct bl...
38
  {
25b8d7ded   Ryusuke Konishi   nilfs2: get rid o...
39
  	return le64_to_cpu(*(nilfs_direct_dptrs(direct) + key));
36a580eb4   Koji Sato   nilfs2: direct bl...
40
  }
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
41
  static inline void nilfs_direct_set_ptr(struct nilfs_bmap *direct,
36a580eb4   Koji Sato   nilfs2: direct bl...
42
43
  					__u64 key, __u64 ptr)
  {
25b8d7ded   Ryusuke Konishi   nilfs2: get rid o...
44
  	*(nilfs_direct_dptrs(direct) + key) = cpu_to_le64(ptr);
36a580eb4   Koji Sato   nilfs2: direct bl...
45
  }
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
46
  static int nilfs_direct_lookup(const struct nilfs_bmap *direct,
36a580eb4   Koji Sato   nilfs2: direct bl...
47
48
  			       __u64 key, int level, __u64 *ptrp)
  {
36a580eb4   Koji Sato   nilfs2: direct bl...
49
  	__u64 ptr;
5ee581483   Jiro SEKIBA   nilfs2: trivial c...
50
51
52
53
  	if (key > NILFS_DIRECT_KEY_MAX || level != 1)
  		return -ENOENT;
  	ptr = nilfs_direct_get_ptr(direct, key);
  	if (ptr == NILFS_BMAP_INVALID_PTR)
36a580eb4   Koji Sato   nilfs2: direct bl...
54
  		return -ENOENT;
364ec2d70   Ryusuke Konishi   nilfs2: remove re...
55
  	*ptrp = ptr;
36a580eb4   Koji Sato   nilfs2: direct bl...
56
57
  	return 0;
  }
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
58
  static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
c3a7abf06   Ryusuke Konishi   nilfs2: support c...
59
60
61
  				      __u64 key, __u64 *ptrp,
  				      unsigned maxblocks)
  {
c3a7abf06   Ryusuke Konishi   nilfs2: support c...
62
63
64
65
  	struct inode *dat = NULL;
  	__u64 ptr, ptr2;
  	sector_t blocknr;
  	int ret, cnt;
5ee581483   Jiro SEKIBA   nilfs2: trivial c...
66
67
68
69
  	if (key > NILFS_DIRECT_KEY_MAX)
  		return -ENOENT;
  	ptr = nilfs_direct_get_ptr(direct, key);
  	if (ptr == NILFS_BMAP_INVALID_PTR)
c3a7abf06   Ryusuke Konishi   nilfs2: support c...
70
  		return -ENOENT;
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
71
72
  	if (NILFS_BMAP_USE_VBN(direct)) {
  		dat = nilfs_bmap_get_dat(direct);
c3a7abf06   Ryusuke Konishi   nilfs2: support c...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  		ret = nilfs_dat_translate(dat, ptr, &blocknr);
  		if (ret < 0)
  			return ret;
  		ptr = blocknr;
  	}
  
  	maxblocks = min_t(unsigned, maxblocks, NILFS_DIRECT_KEY_MAX - key + 1);
  	for (cnt = 1; cnt < maxblocks &&
  		     (ptr2 = nilfs_direct_get_ptr(direct, key + cnt)) !=
  		     NILFS_BMAP_INVALID_PTR;
  	     cnt++) {
  		if (dat) {
  			ret = nilfs_dat_translate(dat, ptr2, &blocknr);
  			if (ret < 0)
  				return ret;
  			ptr2 = blocknr;
  		}
  		if (ptr2 != ptr + cnt)
  			break;
  	}
  	*ptrp = ptr;
  	return cnt;
  }
36a580eb4   Koji Sato   nilfs2: direct bl...
96
  static __u64
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
97
  nilfs_direct_find_target_v(const struct nilfs_bmap *direct, __u64 key)
36a580eb4   Koji Sato   nilfs2: direct bl...
98
99
  {
  	__u64 ptr;
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
100
  	ptr = nilfs_bmap_find_target_seq(direct, key);
36a580eb4   Koji Sato   nilfs2: direct bl...
101
102
103
104
105
  	if (ptr != NILFS_BMAP_INVALID_PTR)
  		/* sequential access */
  		return ptr;
  	else
  		/* block group */
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
106
  		return nilfs_bmap_find_target_in_group(direct);
36a580eb4   Koji Sato   nilfs2: direct bl...
107
  }
36a580eb4   Koji Sato   nilfs2: direct bl...
108
109
  static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
  {
36a580eb4   Koji Sato   nilfs2: direct bl...
110
  	union nilfs_bmap_ptr_req req;
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
111
112
  	struct inode *dat = NULL;
  	struct buffer_head *bh;
36a580eb4   Koji Sato   nilfs2: direct bl...
113
  	int ret;
36a580eb4   Koji Sato   nilfs2: direct bl...
114
115
  	if (key > NILFS_DIRECT_KEY_MAX)
  		return -ENOENT;
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
116
  	if (nilfs_direct_get_ptr(bmap, key) != NILFS_BMAP_INVALID_PTR)
36a580eb4   Koji Sato   nilfs2: direct bl...
117
  		return -EEXIST;
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
118
  	if (NILFS_BMAP_USE_VBN(bmap)) {
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
119
  		req.bpr_ptr = nilfs_direct_find_target_v(bmap, key);
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
120
121
122
123
124
125
126
  		dat = nilfs_bmap_get_dat(bmap);
  	}
  	ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat);
  	if (!ret) {
  		/* ptr must be a pointer to a buffer head. */
  		bh = (struct buffer_head *)((unsigned long)ptr);
  		set_buffer_nilfs_volatile(bh);
36a580eb4   Koji Sato   nilfs2: direct bl...
127

2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
128
  		nilfs_bmap_commit_alloc_ptr(bmap, &req, dat);
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
129
  		nilfs_direct_set_ptr(bmap, key, req.bpr_ptr);
36a580eb4   Koji Sato   nilfs2: direct bl...
130

2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
131
132
  		if (!nilfs_bmap_dirty(bmap))
  			nilfs_bmap_set_dirty(bmap);
36a580eb4   Koji Sato   nilfs2: direct bl...
133

2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
134
  		if (NILFS_BMAP_USE_VBN(bmap))
dc935be2a   Ryusuke Konishi   nilfs2: unify bma...
135
  			nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr);
36a580eb4   Koji Sato   nilfs2: direct bl...
136

be667377a   Ryusuke Konishi   nilfs2: record us...
137
  		nilfs_inode_add_blocks(bmap->b_inode, 1);
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
138
139
  	}
  	return ret;
36a580eb4   Koji Sato   nilfs2: direct bl...
140
141
142
143
  }
  
  static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
  {
36a580eb4   Koji Sato   nilfs2: direct bl...
144
  	union nilfs_bmap_ptr_req req;
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
145
  	struct inode *dat;
36a580eb4   Koji Sato   nilfs2: direct bl...
146
  	int ret;
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
147
  	if (key > NILFS_DIRECT_KEY_MAX ||
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
148
  	    nilfs_direct_get_ptr(bmap, key) == NILFS_BMAP_INVALID_PTR)
36a580eb4   Koji Sato   nilfs2: direct bl...
149
  		return -ENOENT;
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
150
  	dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
151
  	req.bpr_ptr = nilfs_direct_get_ptr(bmap, key);
36a580eb4   Koji Sato   nilfs2: direct bl...
152

2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
153
154
155
  	ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat);
  	if (!ret) {
  		nilfs_bmap_commit_end_ptr(bmap, &req, dat);
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
156
  		nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR);
be667377a   Ryusuke Konishi   nilfs2: record us...
157
  		nilfs_inode_sub_blocks(bmap->b_inode, 1);
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
158
159
  	}
  	return ret;
36a580eb4   Koji Sato   nilfs2: direct bl...
160
  }
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
161
  static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp)
36a580eb4   Koji Sato   nilfs2: direct bl...
162
  {
36a580eb4   Koji Sato   nilfs2: direct bl...
163
  	__u64 key, lastkey;
36a580eb4   Koji Sato   nilfs2: direct bl...
164
165
166
167
168
169
170
171
  	lastkey = NILFS_DIRECT_KEY_MAX + 1;
  	for (key = NILFS_DIRECT_KEY_MIN; key <= NILFS_DIRECT_KEY_MAX; key++)
  		if (nilfs_direct_get_ptr(direct, key) !=
  		    NILFS_BMAP_INVALID_PTR)
  			lastkey = key;
  
  	if (lastkey == NILFS_DIRECT_KEY_MAX + 1)
  		return -ENOENT;
36a580eb4   Koji Sato   nilfs2: direct bl...
172
173
174
175
176
177
178
179
180
  	*keyp = lastkey;
  
  	return 0;
  }
  
  static int nilfs_direct_check_insert(const struct nilfs_bmap *bmap, __u64 key)
  {
  	return key > NILFS_DIRECT_KEY_MAX;
  }
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
181
  static int nilfs_direct_gather_data(struct nilfs_bmap *direct,
36a580eb4   Koji Sato   nilfs2: direct bl...
182
183
  				    __u64 *keys, __u64 *ptrs, int nitems)
  {
36a580eb4   Koji Sato   nilfs2: direct bl...
184
185
186
  	__u64 key;
  	__u64 ptr;
  	int n;
36a580eb4   Koji Sato   nilfs2: direct bl...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  	if (nitems > NILFS_DIRECT_NBLOCKS)
  		nitems = NILFS_DIRECT_NBLOCKS;
  	n = 0;
  	for (key = 0; key < nitems; key++) {
  		ptr = nilfs_direct_get_ptr(direct, key);
  		if (ptr != NILFS_BMAP_INVALID_PTR) {
  			keys[n] = key;
  			ptrs[n] = ptr;
  			n++;
  		}
  	}
  	return n;
  }
  
  int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
3033342a0   Ryusuke Konishi   nilfs2: remove us...
202
  				    __u64 key, __u64 *keys, __u64 *ptrs, int n)
36a580eb4   Koji Sato   nilfs2: direct bl...
203
  {
36a580eb4   Koji Sato   nilfs2: direct bl...
204
205
206
207
208
209
  	__le64 *dptrs;
  	int ret, i, j;
  
  	/* no need to allocate any resource for conversion */
  
  	/* delete */
8acfbf093   Pekka Enberg   nilfs2: clean up ...
210
  	ret = bmap->b_ops->bop_delete(bmap, key);
36a580eb4   Koji Sato   nilfs2: direct bl...
211
212
213
214
215
  	if (ret < 0)
  		return ret;
  
  	/* free resources */
  	if (bmap->b_ops->bop_clear != NULL)
8acfbf093   Pekka Enberg   nilfs2: clean up ...
216
  		bmap->b_ops->bop_clear(bmap);
36a580eb4   Koji Sato   nilfs2: direct bl...
217
218
  
  	/* convert */
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
219
  	dptrs = nilfs_direct_dptrs(bmap);
36a580eb4   Koji Sato   nilfs2: direct bl...
220
221
222
  	for (i = 0, j = 0; i < NILFS_DIRECT_NBLOCKS; i++) {
  		if ((j < n) && (i == keys[j])) {
  			dptrs[i] = (i != key) ?
25b8d7ded   Ryusuke Konishi   nilfs2: get rid o...
223
  				cpu_to_le64(ptrs[j]) :
36a580eb4   Koji Sato   nilfs2: direct bl...
224
225
226
227
228
  				NILFS_BMAP_INVALID_PTR;
  			j++;
  		} else
  			dptrs[i] = NILFS_BMAP_INVALID_PTR;
  	}
3033342a0   Ryusuke Konishi   nilfs2: remove us...
229
  	nilfs_direct_init(bmap);
36a580eb4   Koji Sato   nilfs2: direct bl...
230
231
  	return 0;
  }
583ada476   Ryusuke Konishi   nilfs2: remove co...
232
  static int nilfs_direct_propagate(struct nilfs_bmap *bmap,
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
233
  				  struct buffer_head *bh)
36a580eb4   Koji Sato   nilfs2: direct bl...
234
  {
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
235
236
  	struct nilfs_palloc_req oldreq, newreq;
  	struct inode *dat;
36a580eb4   Koji Sato   nilfs2: direct bl...
237
238
239
  	__u64 key;
  	__u64 ptr;
  	int ret;
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
240
241
242
243
244
  	if (!NILFS_BMAP_USE_VBN(bmap))
  		return 0;
  
  	dat = nilfs_bmap_get_dat(bmap);
  	key = nilfs_bmap_data_get_key(bmap, bh);
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
245
  	ptr = nilfs_direct_get_ptr(bmap, key);
36a580eb4   Koji Sato   nilfs2: direct bl...
246
  	if (!buffer_nilfs_volatile(bh)) {
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
247
248
249
  		oldreq.pr_entry_nr = ptr;
  		newreq.pr_entry_nr = ptr;
  		ret = nilfs_dat_prepare_update(dat, &oldreq, &newreq);
36a580eb4   Koji Sato   nilfs2: direct bl...
250
251
  		if (ret < 0)
  			return ret;
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
252
253
  		nilfs_dat_commit_update(dat, &oldreq, &newreq,
  					bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
36a580eb4   Koji Sato   nilfs2: direct bl...
254
  		set_buffer_nilfs_volatile(bh);
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
255
  		nilfs_direct_set_ptr(bmap, key, newreq.pr_entry_nr);
36a580eb4   Koji Sato   nilfs2: direct bl...
256
  	} else
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
257
  		ret = nilfs_dat_mark_dirty(dat, ptr);
36a580eb4   Koji Sato   nilfs2: direct bl...
258
259
260
  
  	return ret;
  }
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
261
  static int nilfs_direct_assign_v(struct nilfs_bmap *direct,
36a580eb4   Koji Sato   nilfs2: direct bl...
262
263
264
265
266
  				 __u64 key, __u64 ptr,
  				 struct buffer_head **bh,
  				 sector_t blocknr,
  				 union nilfs_binfo *binfo)
  {
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
267
  	struct inode *dat = nilfs_bmap_get_dat(direct);
36a580eb4   Koji Sato   nilfs2: direct bl...
268
269
270
271
  	union nilfs_bmap_ptr_req req;
  	int ret;
  
  	req.bpr_ptr = ptr;
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
272
273
274
  	ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
  	if (!ret) {
  		nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
25b8d7ded   Ryusuke Konishi   nilfs2: get rid o...
275
276
  		binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
  		binfo->bi_v.bi_blkoff = cpu_to_le64(key);
2e0c2c739   Ryusuke Konishi   nilfs2: allow btr...
277
278
  	}
  	return ret;
36a580eb4   Koji Sato   nilfs2: direct bl...
279
  }
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
280
  static int nilfs_direct_assign_p(struct nilfs_bmap *direct,
36a580eb4   Koji Sato   nilfs2: direct bl...
281
282
283
284
285
286
  				 __u64 key, __u64 ptr,
  				 struct buffer_head **bh,
  				 sector_t blocknr,
  				 union nilfs_binfo *binfo)
  {
  	nilfs_direct_set_ptr(direct, key, blocknr);
25b8d7ded   Ryusuke Konishi   nilfs2: get rid o...
287
  	binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
36a580eb4   Koji Sato   nilfs2: direct bl...
288
289
290
291
292
293
294
295
296
297
  	binfo->bi_dat.bi_level = 0;
  
  	return 0;
  }
  
  static int nilfs_direct_assign(struct nilfs_bmap *bmap,
  			       struct buffer_head **bh,
  			       sector_t blocknr,
  			       union nilfs_binfo *binfo)
  {
36a580eb4   Koji Sato   nilfs2: direct bl...
298
299
  	__u64 key;
  	__u64 ptr;
36a580eb4   Koji Sato   nilfs2: direct bl...
300
  	key = nilfs_bmap_data_get_key(bmap, *bh);
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
301
302
303
304
305
306
  	if (unlikely(key > NILFS_DIRECT_KEY_MAX)) {
  		printk(KERN_CRIT "%s: invalid key: %llu
  ", __func__,
  		       (unsigned long long)key);
  		return -EINVAL;
  	}
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
307
  	ptr = nilfs_direct_get_ptr(bmap, key);
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
308
309
310
311
312
313
  	if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) {
  		printk(KERN_CRIT "%s: invalid pointer: %llu
  ", __func__,
  		       (unsigned long long)ptr);
  		return -EINVAL;
  	}
36a580eb4   Koji Sato   nilfs2: direct bl...
314

355c6b610   Ryusuke Konishi   nilfs2: remove ni...
315
  	return NILFS_BMAP_USE_VBN(bmap) ?
10ff885ba   Ryusuke Konishi   nilfs2: get rid o...
316
317
  		nilfs_direct_assign_v(bmap, key, ptr, bh, blocknr, binfo) :
  		nilfs_direct_assign_p(bmap, key, ptr, bh, blocknr, binfo);
36a580eb4   Koji Sato   nilfs2: direct bl...
318
319
320
321
  }
  
  static const struct nilfs_bmap_operations nilfs_direct_ops = {
  	.bop_lookup		=	nilfs_direct_lookup,
c3a7abf06   Ryusuke Konishi   nilfs2: support c...
322
  	.bop_lookup_contig	=	nilfs_direct_lookup_contig,
36a580eb4   Koji Sato   nilfs2: direct bl...
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  	.bop_insert		=	nilfs_direct_insert,
  	.bop_delete		=	nilfs_direct_delete,
  	.bop_clear		=	NULL,
  
  	.bop_propagate		=	nilfs_direct_propagate,
  
  	.bop_lookup_dirty_buffers	=	NULL,
  
  	.bop_assign		=	nilfs_direct_assign,
  	.bop_mark		=	NULL,
  
  	.bop_last_key		=	nilfs_direct_last_key,
  	.bop_check_insert	=	nilfs_direct_check_insert,
  	.bop_check_delete	=	NULL,
  	.bop_gather_data	=	nilfs_direct_gather_data,
  };
3033342a0   Ryusuke Konishi   nilfs2: remove us...
339
  int nilfs_direct_init(struct nilfs_bmap *bmap)
36a580eb4   Koji Sato   nilfs2: direct bl...
340
  {
36a580eb4   Koji Sato   nilfs2: direct bl...
341
  	bmap->b_ops = &nilfs_direct_ops;
36a580eb4   Koji Sato   nilfs2: direct bl...
342
343
  	return 0;
  }