Blame view

fs/gfs2/bmap.c 31.2 KB
b3b94faa5   David Teigland   [GFS2] The core o...
1
2
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3a8a9a103   Steven Whitehouse   [GFS2] Update cop...
3
   * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
b3b94faa5   David Teigland   [GFS2] The core o...
4
5
6
   *
   * This copyrighted material is made available to anyone wishing to use,
   * modify, copy, or redistribute it subject to the terms and conditions
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
7
   * of the GNU General Public License version 2.
b3b94faa5   David Teigland   [GFS2] The core o...
8
   */
b3b94faa5   David Teigland   [GFS2] The core o...
9
10
11
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
12
  #include <linux/gfs2_ondisk.h>
71b86f562   Steven Whitehouse   [GFS2] Further up...
13
  #include <linux/crc32.h>
b3b94faa5   David Teigland   [GFS2] The core o...
14
15
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
16
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
17
18
19
  #include "bmap.h"
  #include "glock.h"
  #include "inode.h"
b3b94faa5   David Teigland   [GFS2] The core o...
20
  #include "meta_io.h"
b3b94faa5   David Teigland   [GFS2] The core o...
21
22
23
  #include "quota.h"
  #include "rgrp.h"
  #include "trans.h"
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
24
  #include "dir.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
25
  #include "util.h"
63997775b   Steven Whitehouse   GFS2: Add tracepo...
26
  #include "trace_gfs2.h"
b3b94faa5   David Teigland   [GFS2] The core o...
27
28
29
30
31
32
  
  /* This doesn't need to be that large as max 64 bit pointers in a 4k
   * block is 512, so __u16 is fine for that. It saves stack space to
   * keep it small.
   */
  struct metapath {
dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
33
  	struct buffer_head *mp_bh[GFS2_MAX_META_HEIGHT];
b3b94faa5   David Teigland   [GFS2] The core o...
34
35
36
37
  	__u16 mp_list[GFS2_MAX_META_HEIGHT];
  };
  
  typedef int (*block_call_t) (struct gfs2_inode *ip, struct buffer_head *dibh,
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
38
39
  			     struct buffer_head *bh, __be64 *top,
  			     __be64 *bottom, unsigned int height,
b3b94faa5   David Teigland   [GFS2] The core o...
40
41
42
43
44
45
46
47
  			     void *data);
  
  struct strip_mine {
  	int sm_first;
  	unsigned int sm_height;
  };
  
  /**
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
48
49
50
51
52
53
54
55
56
57
   * gfs2_unstuffer_page - unstuff a stuffed inode into a block cached by a page
   * @ip: the inode
   * @dibh: the dinode buffer
   * @block: the block number that was allocated
   * @private: any locked page held by the caller process
   *
   * Returns: errno
   */
  
  static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
cd915493f   Steven Whitehouse   [GFS2] Change all...
58
  			       u64 block, struct page *page)
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
59
  {
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
60
61
62
63
64
65
66
67
68
69
70
71
72
  	struct inode *inode = &ip->i_inode;
  	struct buffer_head *bh;
  	int release = 0;
  
  	if (!page || page->index) {
  		page = grab_cache_page(inode->i_mapping, 0);
  		if (!page)
  			return -ENOMEM;
  		release = 1;
  	}
  
  	if (!PageUptodate(page)) {
  		void *kaddr = kmap(page);
602c89d2e   Steven Whitehouse   GFS2: Clean up st...
73
74
75
76
  		u64 dsize = i_size_read(inode);
   
  		if (dsize > (dibh->b_size - sizeof(struct gfs2_dinode)))
  			dsize = dibh->b_size - sizeof(struct gfs2_dinode);
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
77

602c89d2e   Steven Whitehouse   GFS2: Clean up st...
78
79
  		memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
  		memset(kaddr + dsize, 0, PAGE_CACHE_SIZE - dsize);
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  		kunmap(page);
  
  		SetPageUptodate(page);
  	}
  
  	if (!page_has_buffers(page))
  		create_empty_buffers(page, 1 << inode->i_blkbits,
  				     (1 << BH_Uptodate));
  
  	bh = page_buffers(page);
  
  	if (!buffer_mapped(bh))
  		map_bh(bh, inode->i_sb, block);
  
  	set_buffer_uptodate(bh);
eaf965270   Steven Whitehouse   [GFS2] Don't mark...
95
96
  	if (!gfs2_is_jdata(ip))
  		mark_buffer_dirty(bh);
bf36a7131   Steven Whitehouse   [GFS2] Add gfs2_i...
97
  	if (!gfs2_is_writeback(ip))
8475487be   Bob Peterson   [GFS2] Fix orderi...
98
  		gfs2_trans_add_bh(ip->i_gl, bh, 0);
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
99
100
101
102
103
104
105
106
107
108
  
  	if (release) {
  		unlock_page(page);
  		page_cache_release(page);
  	}
  
  	return 0;
  }
  
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
109
110
111
112
113
114
115
116
117
118
   * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big
   * @ip: The GFS2 inode to unstuff
   * @unstuffer: the routine that handles unstuffing a non-zero length file
   * @private: private data for the unstuffer
   *
   * This routine unstuffs a dinode and returns it to a "normal" state such
   * that the height can be grown in the traditional way.
   *
   * Returns: errno
   */
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
119
  int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
b3b94faa5   David Teigland   [GFS2] The core o...
120
121
  {
  	struct buffer_head *bh, *dibh;
48516ced2   Steven Whitehouse   [GFS2] Remove une...
122
  	struct gfs2_dinode *di;
cd915493f   Steven Whitehouse   [GFS2] Change all...
123
  	u64 block = 0;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
124
  	int isdir = gfs2_is_dir(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
125
126
127
128
129
130
131
  	int error;
  
  	down_write(&ip->i_rw_mutex);
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto out;
907b9bceb   Steven Whitehouse   [GFS2/DLM] Fix tr...
132

c9e988867   Steven Whitehouse   GFS2: Move i_size...
133
  	if (ip->i_disksize) {
b3b94faa5   David Teigland   [GFS2] The core o...
134
135
  		/* Get a free block, fill it with the stuffed data,
  		   and write it out to disk */
b45e41d7d   Steven Whitehouse   [GFS2] Add extent...
136
  		unsigned int n = 1;
090109783   Steven Whitehouse   GFS2: Improve res...
137
138
139
  		error = gfs2_alloc_block(ip, &block, &n);
  		if (error)
  			goto out_brelse;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
140
  		if (isdir) {
5731be53e   Steven Whitehouse   [GFS2] Update gfs...
141
  			gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1);
61e085a88   Steven Whitehouse   [GFS2] Tidy up di...
142
  			error = gfs2_dir_get_new_buffer(ip, block, &bh);
b3b94faa5   David Teigland   [GFS2] The core o...
143
144
  			if (error)
  				goto out_brelse;
48516ced2   Steven Whitehouse   [GFS2] Remove une...
145
  			gfs2_buffer_copy_tail(bh, sizeof(struct gfs2_meta_header),
b3b94faa5   David Teigland   [GFS2] The core o...
146
147
148
  					      dibh, sizeof(struct gfs2_dinode));
  			brelse(bh);
  		} else {
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
149
  			error = gfs2_unstuffer_page(ip, dibh, block, page);
b3b94faa5   David Teigland   [GFS2] The core o...
150
151
152
153
154
155
  			if (error)
  				goto out_brelse;
  		}
  	}
  
  	/*  Set up the pointer to the new block  */
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
156
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
48516ced2   Steven Whitehouse   [GFS2] Remove une...
157
  	di = (struct gfs2_dinode *)dibh->b_data;
b3b94faa5   David Teigland   [GFS2] The core o...
158
  	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
c9e988867   Steven Whitehouse   GFS2: Move i_size...
159
  	if (ip->i_disksize) {
48516ced2   Steven Whitehouse   [GFS2] Remove une...
160
  		*(__be64 *)(di + 1) = cpu_to_be64(block);
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
161
162
  		gfs2_add_inode_blocks(&ip->i_inode, 1);
  		di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
b3b94faa5   David Teigland   [GFS2] The core o...
163
  	}
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
164
  	ip->i_height = 1;
48516ced2   Steven Whitehouse   [GFS2] Remove une...
165
  	di->di_height = cpu_to_be16(1);
b3b94faa5   David Teigland   [GFS2] The core o...
166

a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
167
  out_brelse:
b3b94faa5   David Teigland   [GFS2] The core o...
168
  	brelse(dibh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
169
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
170
  	up_write(&ip->i_rw_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
171
172
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
173
174
175
  
  /**
   * find_metapath - Find path through the metadata tree
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
176
   * @sdp: The superblock
b3b94faa5   David Teigland   [GFS2] The core o...
177
178
   * @mp: The metapath to return the result in
   * @block: The disk block to look up
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
179
   * @height: The pre-calculated height of the metadata tree
b3b94faa5   David Teigland   [GFS2] The core o...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
   *
   *   This routine returns a struct metapath structure that defines a path
   *   through the metadata of inode "ip" to get to block "block".
   *
   *   Example:
   *   Given:  "ip" is a height 3 file, "offset" is 101342453, and this is a
   *   filesystem with a blocksize of 4096.
   *
   *   find_metapath() would return a struct metapath structure set to:
   *   mp_offset = 101342453, mp_height = 3, mp_list[0] = 0, mp_list[1] = 48,
   *   and mp_list[2] = 165.
   *
   *   That means that in order to get to the block containing the byte at
   *   offset 101342453, we would load the indirect block pointed to by pointer
   *   0 in the dinode.  We would then load the indirect block pointed to by
   *   pointer 48 in that indirect block.  We would then load the data block
   *   pointed to by pointer 165 in that indirect block.
   *
   *             ----------------------------------------
   *             | Dinode |                             |
   *             |        |                            4|
   *             |        |0 1 2 3 4 5                 9|
   *             |        |                            6|
   *             ----------------------------------------
   *                       |
   *                       |
   *                       V
   *             ----------------------------------------
   *             | Indirect Block                       |
   *             |                                     5|
   *             |            4 4 4 4 4 5 5            1|
   *             |0           5 6 7 8 9 0 1            2|
   *             ----------------------------------------
   *                                |
   *                                |
   *                                V
   *             ----------------------------------------
   *             | Indirect Block                       |
   *             |                         1 1 1 1 1   5|
   *             |                         6 6 6 6 6   1|
   *             |0                        3 4 5 6 7   2|
   *             ----------------------------------------
   *                                           |
   *                                           |
   *                                           V
   *             ----------------------------------------
   *             | Data block containing offset         |
   *             |            101342453                 |
   *             |                                      |
   *             |                                      |
   *             ----------------------------------------
   *
   */
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
233
234
  static void find_metapath(const struct gfs2_sbd *sdp, u64 block,
  			  struct metapath *mp, unsigned int height)
b3b94faa5   David Teigland   [GFS2] The core o...
235
  {
b3b94faa5   David Teigland   [GFS2] The core o...
236
  	unsigned int i;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
237
  	for (i = height; i--;)
7eabb77e6   Bob Peterson   [GFS2] Misc fixups
238
  		mp->mp_list[i] = do_div(block, sdp->sd_inptrs);
b3b94faa5   David Teigland   [GFS2] The core o...
239
240
  
  }
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
241
  static inline unsigned int metapath_branch_start(const struct metapath *mp)
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
242
  {
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
243
244
245
  	if (mp->mp_list[0] == 0)
  		return 2;
  	return 1;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
246
  }
b3b94faa5   David Teigland   [GFS2] The core o...
247
248
  /**
   * metapointer - Return pointer to start of metadata in a buffer
b3b94faa5   David Teigland   [GFS2] The core o...
249
250
251
252
253
254
255
   * @height: The metadata height (0 = dinode)
   * @mp: The metapath
   *
   * Return a pointer to the block number of the next height of the metadata
   * tree given a buffer containing the pointer to the current height of the
   * metadata tree.
   */
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
256
  static inline __be64 *metapointer(unsigned int height, const struct metapath *mp)
b3b94faa5   David Teigland   [GFS2] The core o...
257
  {
dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
258
  	struct buffer_head *bh = mp->mp_bh[height];
b3b94faa5   David Teigland   [GFS2] The core o...
259
260
  	unsigned int head_size = (height > 0) ?
  		sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
261
  	return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
b3b94faa5   David Teigland   [GFS2] The core o...
262
263
264
  }
  
  /**
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
265
266
   * lookup_metapath - Walk the metadata tree to a specific point
   * @ip: The inode
b3b94faa5   David Teigland   [GFS2] The core o...
267
   * @mp: The metapath
b3b94faa5   David Teigland   [GFS2] The core o...
268
   *
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
269
270
271
272
273
274
275
276
   * Assumes that the inode's buffer has already been looked up and
   * hooked onto mp->mp_bh[0] and that the metapath has been initialised
   * by find_metapath().
   *
   * If this function encounters part of the tree which has not been
   * allocated, it returns the current height of the tree at the point
   * at which it found the unallocated block. Blocks which are found are
   * added to the mp->mp_bh[] list.
b3b94faa5   David Teigland   [GFS2] The core o...
277
   *
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
278
   * Returns: error or height of metadata tree
b3b94faa5   David Teigland   [GFS2] The core o...
279
   */
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
280
  static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp)
11707ea05   Steven Whitehouse   [GFS2] Move part ...
281
  {
11707ea05   Steven Whitehouse   [GFS2] Move part ...
282
283
  	unsigned int end_of_metadata = ip->i_height - 1;
  	unsigned int x;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
284
285
  	__be64 *ptr;
  	u64 dblock;
e23159d2a   Steven Whitehouse   [GFS2] Get inode ...
286
  	int ret;
11707ea05   Steven Whitehouse   [GFS2] Move part ...
287
288
  
  	for (x = 0; x < end_of_metadata; x++) {
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
289
290
291
292
  		ptr = metapointer(x, mp);
  		dblock = be64_to_cpu(*ptr);
  		if (!dblock)
  			return x + 1;
11707ea05   Steven Whitehouse   [GFS2] Move part ...
293

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
294
  		ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]);
11707ea05   Steven Whitehouse   [GFS2] Move part ...
295
296
297
  		if (ret)
  			return ret;
  	}
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
298
  	return ip->i_height;
dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
299
  }
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
300
  static inline void release_metapath(struct metapath *mp)
dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
301
302
  {
  	int i;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
303
304
305
306
307
  	for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) {
  		if (mp->mp_bh[i] == NULL)
  			break;
  		brelse(mp->mp_bh[i]);
  	}
11707ea05   Steven Whitehouse   [GFS2] Move part ...
308
  }
30cbf189c   Steven Whitehouse   [GFS2] Add a func...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  /**
   * gfs2_extent_length - Returns length of an extent of blocks
   * @start: Start of the buffer
   * @len: Length of the buffer in bytes
   * @ptr: Current position in the buffer
   * @limit: Max extent length to return (0 = unlimited)
   * @eob: Set to 1 if we hit "end of block"
   *
   * If the first block is zero (unallocated) it will return the number of
   * unallocated blocks in the extent, otherwise it will return the number
   * of contiguous blocks in the extent.
   *
   * Returns: The length of the extent (minimum of one block)
   */
  
  static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __be64 *ptr, unsigned limit, int *eob)
  {
  	const __be64 *end = (start + len);
  	const __be64 *first = ptr;
  	u64 d = be64_to_cpu(*ptr);
  
  	*eob = 0;
  	do {
  		ptr++;
  		if (ptr >= end)
  			break;
  		if (limit && --limit == 0)
  			break;
  		if (d)
  			d++;
  	} while(be64_to_cpu(*ptr) == d);
  	if (ptr >= end)
  		*eob = 1;
  	return (ptr - first);
  }
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
344
  static inline void bmap_lock(struct gfs2_inode *ip, int create)
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
345
  {
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
346
347
348
349
350
  	if (create)
  		down_write(&ip->i_rw_mutex);
  	else
  		down_read(&ip->i_rw_mutex);
  }
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
351
  static inline void bmap_unlock(struct gfs2_inode *ip, int create)
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
352
  {
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
353
354
355
356
357
  	if (create)
  		up_write(&ip->i_rw_mutex);
  	else
  		up_read(&ip->i_rw_mutex);
  }
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
  static inline __be64 *gfs2_indirect_init(struct metapath *mp,
  					 struct gfs2_glock *gl, unsigned int i,
  					 unsigned offset, u64 bn)
  {
  	__be64 *ptr = (__be64 *)(mp->mp_bh[i - 1]->b_data +
  		       ((i > 1) ? sizeof(struct gfs2_meta_header) :
  				 sizeof(struct gfs2_dinode)));
  	BUG_ON(i < 1);
  	BUG_ON(mp->mp_bh[i] != NULL);
  	mp->mp_bh[i] = gfs2_meta_new(gl, bn);
  	gfs2_trans_add_bh(gl, mp->mp_bh[i], 1);
  	gfs2_metatype_set(mp->mp_bh[i], GFS2_METATYPE_IN, GFS2_FORMAT_IN);
  	gfs2_buffer_clear_tail(mp->mp_bh[i], sizeof(struct gfs2_meta_header));
  	ptr += offset;
  	*ptr = cpu_to_be64(bn);
  	return ptr;
  }
  
  enum alloc_state {
  	ALLOC_DATA = 0,
  	ALLOC_GROW_DEPTH = 1,
  	ALLOC_GROW_HEIGHT = 2,
  	/* ALLOC_UNSTUFF = 3,   TBD and rather complicated */
  };
  
  /**
   * gfs2_bmap_alloc - Build a metadata tree of the requested height
   * @inode: The GFS2 inode
   * @lblock: The logical starting block of the extent
   * @bh_map: This is used to return the mapping details
   * @mp: The metapath
   * @sheight: The starting height (i.e. whats already mapped)
   * @height: The height to build to
   * @maxlen: The max number of data blocks to alloc
   *
   * In this routine we may have to alloc:
   *   i) Indirect blocks to grow the metadata tree height
   *  ii) Indirect blocks to fill in lower part of the metadata tree
   * iii) Data blocks
   *
   * The function is in two parts. The first part works out the total
   * number of blocks which we need. The second part does the actual
   * allocation asking for an extent at a time (if enough contiguous free
   * blocks are available, there will only be one request per bmap call)
   * and uses the state machine to initialise the blocks in order.
   *
   * Returns: errno on error
   */
  
  static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
  			   struct buffer_head *bh_map, struct metapath *mp,
  			   const unsigned int sheight,
  			   const unsigned int height,
  			   const unsigned int maxlen)
  {
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
  	struct buffer_head *dibh = mp->mp_bh[0];
  	u64 bn, dblock = 0;
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
417
  	unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
  	unsigned dblks = 0;
  	unsigned ptrs_per_blk;
  	const unsigned end_of_metadata = height - 1;
  	int eob = 0;
  	enum alloc_state state;
  	__be64 *ptr;
  	__be64 zero_bn = 0;
  
  	BUG_ON(sheight < 1);
  	BUG_ON(dibh == NULL);
  
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
  
  	if (height == sheight) {
  		struct buffer_head *bh;
  		/* Bottom indirect block exists, find unalloced extent size */
  		ptr = metapointer(end_of_metadata, mp);
  		bh = mp->mp_bh[end_of_metadata];
  		dblks = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen,
  					   &eob);
  		BUG_ON(dblks < 1);
  		state = ALLOC_DATA;
  	} else {
  		/* Need to allocate indirect blocks */
  		ptrs_per_blk = height > 1 ? sdp->sd_inptrs : sdp->sd_diptrs;
  		dblks = min(maxlen, ptrs_per_blk - mp->mp_list[end_of_metadata]);
  		if (height == ip->i_height) {
  			/* Writing into existing tree, extend tree down */
  			iblks = height - sheight;
  			state = ALLOC_GROW_DEPTH;
  		} else {
  			/* Building up tree height */
  			state = ALLOC_GROW_HEIGHT;
  			iblks = height - ip->i_height;
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
452
453
  			branch_start = metapath_branch_start(mp);
  			iblks += (height - branch_start);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
454
455
456
457
458
459
460
461
  		}
  	}
  
  	/* start of the second part of the function (state machine) */
  
  	blks = dblks + iblks;
  	i = sheight;
  	do {
090109783   Steven Whitehouse   GFS2: Improve res...
462
  		int error;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
463
  		n = blks - alloced;
090109783   Steven Whitehouse   GFS2: Improve res...
464
465
466
  		error = gfs2_alloc_block(ip, &bn, &n);
  		if (error)
  			return error;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  		alloced += n;
  		if (state != ALLOC_DATA || gfs2_is_jdata(ip))
  			gfs2_trans_add_unrevoke(sdp, bn, n);
  		switch (state) {
  		/* Growing height of tree */
  		case ALLOC_GROW_HEIGHT:
  			if (i == 1) {
  				ptr = (__be64 *)(dibh->b_data +
  						 sizeof(struct gfs2_dinode));
  				zero_bn = *ptr;
  			}
  			for (; i - 1 < height - ip->i_height && n > 0; i++, n--)
  				gfs2_indirect_init(mp, ip->i_gl, i, 0, bn++);
  			if (i - 1 == height - ip->i_height) {
  				i--;
  				gfs2_buffer_copy_tail(mp->mp_bh[i],
  						sizeof(struct gfs2_meta_header),
  						dibh, sizeof(struct gfs2_dinode));
  				gfs2_buffer_clear_tail(dibh,
  						sizeof(struct gfs2_dinode) +
  						sizeof(__be64));
  				ptr = (__be64 *)(mp->mp_bh[i]->b_data +
  					sizeof(struct gfs2_meta_header));
  				*ptr = zero_bn;
  				state = ALLOC_GROW_DEPTH;
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
492
  				for(i = branch_start; i < height; i++) {
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
493
494
495
496
497
  					if (mp->mp_bh[i] == NULL)
  						break;
  					brelse(mp->mp_bh[i]);
  					mp->mp_bh[i] = NULL;
  				}
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
498
  				i = branch_start;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
  			}
  			if (n == 0)
  				break;
  		/* Branching from existing tree */
  		case ALLOC_GROW_DEPTH:
  			if (i > 1 && i < height)
  				gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i-1], 1);
  			for (; i < height && n > 0; i++, n--)
  				gfs2_indirect_init(mp, ip->i_gl, i,
  						   mp->mp_list[i-1], bn++);
  			if (i == height)
  				state = ALLOC_DATA;
  			if (n == 0)
  				break;
  		/* Tree complete, adding data blocks */
  		case ALLOC_DATA:
  			BUG_ON(n > dblks);
  			BUG_ON(mp->mp_bh[end_of_metadata] == NULL);
  			gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[end_of_metadata], 1);
  			dblks = n;
  			ptr = metapointer(end_of_metadata, mp);
  			dblock = bn;
  			while (n-- > 0)
  				*ptr++ = cpu_to_be64(bn++);
  			break;
  		}
07ccb7bf2   Steven Whitehouse   GFS2: Fix bmap al...
525
  	} while ((state != ALLOC_DATA) || !dblock);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
526
527
528
529
530
531
532
533
534
  
  	ip->i_height = height;
  	gfs2_add_inode_blocks(&ip->i_inode, alloced);
  	gfs2_dinode_out(ip, mp->mp_bh[0]->b_data);
  	map_bh(bh_map, inode->i_sb, dblock);
  	bh_map->b_size = dblks << inode->i_blkbits;
  	set_buffer_new(bh_map);
  	return 0;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
535
  /**
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
536
   * gfs2_block_map - Map a block from an inode to a disk block
fd88de569   Steven Whitehouse   [GFS2] Readpages ...
537
   * @inode: The inode
b3b94faa5   David Teigland   [GFS2] The core o...
538
   * @lblock: The logical block number
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
539
   * @bh_map: The bh to be mapped
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
540
   * @create: True if its ok to alloc blocks to satify the request
b3b94faa5   David Teigland   [GFS2] The core o...
541
   *
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
542
543
544
   * Sets buffer_mapped() if successful, sets buffer_boundary() if a
   * read of metadata will be required before the next block can be
   * mapped. Sets buffer_new() if new blocks were allocated.
b3b94faa5   David Teigland   [GFS2] The core o...
545
546
547
   *
   * Returns: errno
   */
e9e1ef2b6   Bob Peterson   [GFS2] Remove fun...
548
549
  int gfs2_block_map(struct inode *inode, sector_t lblock,
  		   struct buffer_head *bh_map, int create)
b3b94faa5   David Teigland   [GFS2] The core o...
550
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
551
552
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
553
  	unsigned int bsize = sdp->sd_sb.sb_bsize;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
554
  	const unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
555
  	const u64 *arr = sdp->sd_heightsize;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
556
557
558
559
560
561
562
563
  	__be64 *ptr;
  	u64 size;
  	struct metapath mp;
  	int ret;
  	int eob;
  	unsigned int len;
  	struct buffer_head *bh;
  	u8 height;
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
564

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
565
  	BUG_ON(maxlen == 0);
b3b94faa5   David Teigland   [GFS2] The core o...
566

dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
567
  	memset(mp.mp_bh, 0, sizeof(mp.mp_bh));
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
568
  	bmap_lock(ip, create);
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
569
570
571
  	clear_buffer_mapped(bh_map);
  	clear_buffer_new(bh_map);
  	clear_buffer_boundary(bh_map);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
572
  	trace_gfs2_bmap(ip, bh_map, lblock, create, 1);
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
573
574
575
576
  	if (gfs2_is_dir(ip)) {
  		bsize = sdp->sd_jbsize;
  		arr = sdp->sd_jheightsize;
  	}
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
577

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
578
579
580
  	ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]);
  	if (ret)
  		goto out;
b3b94faa5   David Teigland   [GFS2] The core o...
581

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
  	height = ip->i_height;
  	size = (lblock + 1) * bsize;
  	while (size > arr[height])
  		height++;
  	find_metapath(sdp, lblock, &mp, height);
  	ret = 1;
  	if (height > ip->i_height || gfs2_is_stuffed(ip))
  		goto do_alloc;
  	ret = lookup_metapath(ip, &mp);
  	if (ret < 0)
  		goto out;
  	if (ret != ip->i_height)
  		goto do_alloc;
  	ptr = metapointer(ip->i_height - 1, &mp);
  	if (*ptr == 0)
  		goto do_alloc;
  	map_bh(bh_map, inode->i_sb, be64_to_cpu(*ptr));
  	bh = mp.mp_bh[ip->i_height - 1];
  	len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, &eob);
  	bh_map->b_size = (len << inode->i_blkbits);
  	if (eob)
  		set_buffer_boundary(bh_map);
  	ret = 0;
  out:
  	release_metapath(&mp);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
607
  	trace_gfs2_bmap(ip, bh_map, lblock, create, ret);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
608
609
  	bmap_unlock(ip, create);
  	return ret;
30cbf189c   Steven Whitehouse   [GFS2] Add a func...
610

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
611
612
613
614
615
616
  do_alloc:
  	/* All allocations are done here, firstly check create flag */
  	if (!create) {
  		BUG_ON(gfs2_is_stuffed(ip));
  		ret = 0;
  		goto out;
b3b94faa5   David Teigland   [GFS2] The core o...
617
  	}
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
618
619
620
621
  
  	/* At this point ret is the tree depth of already allocated blocks */
  	ret = gfs2_bmap_alloc(inode, lblock, bh_map, &mp, ret, height, maxlen);
  	goto out;
fd88de569   Steven Whitehouse   [GFS2] Readpages ...
622
  }
941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
623
624
625
  /*
   * Deprecated: do not use in new code
   */
fd88de569   Steven Whitehouse   [GFS2] Readpages ...
626
627
  int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
  {
23591256d   Steven Whitehouse   [GFS2] Fix bmap t...
628
  	struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 };
7a6bbacbb   Steven Whitehouse   [GFS2] Map multip...
629
  	int ret;
fd88de569   Steven Whitehouse   [GFS2] Readpages ...
630
631
632
633
634
  	int create = *new;
  
  	BUG_ON(!extlen);
  	BUG_ON(!dblock);
  	BUG_ON(!new);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
635
  	bh.b_size = 1 << (inode->i_blkbits + (create ? 0 : 5));
e9e1ef2b6   Bob Peterson   [GFS2] Remove fun...
636
  	ret = gfs2_block_map(inode, lblock, &bh, create);
7a6bbacbb   Steven Whitehouse   [GFS2] Map multip...
637
638
639
640
641
642
643
  	*extlen = bh.b_size >> inode->i_blkbits;
  	*dblock = bh.b_blocknr;
  	if (buffer_new(&bh))
  		*new = 1;
  	else
  		*new = 0;
  	return ret;
b3b94faa5   David Teigland   [GFS2] The core o...
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
  }
  
  /**
   * recursive_scan - recursively scan through the end of a file
   * @ip: the inode
   * @dibh: the dinode buffer
   * @mp: the path through the metadata to the point to start
   * @height: the height the recursion is at
   * @block: the indirect block to look at
   * @first: 1 if this is the first block
   * @bc: the call to make for each piece of metadata
   * @data: data opaque to this function to pass to @bc
   *
   * When this is first called @height and @block should be zero and
   * @first should be 1.
   *
   * Returns: errno
   */
  
  static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
  			  struct metapath *mp, unsigned int height,
cd915493f   Steven Whitehouse   [GFS2] Change all...
665
  			  u64 block, int first, block_call_t bc,
b3b94faa5   David Teigland   [GFS2] The core o...
666
667
  			  void *data)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
668
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
669
  	struct buffer_head *bh = NULL;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
670
  	__be64 *top, *bottom;
cd915493f   Steven Whitehouse   [GFS2] Change all...
671
  	u64 bn;
b3b94faa5   David Teigland   [GFS2] The core o...
672
673
674
675
676
677
678
679
  	int error;
  	int mh_size = sizeof(struct gfs2_meta_header);
  
  	if (!height) {
  		error = gfs2_meta_inode_buffer(ip, &bh);
  		if (error)
  			return error;
  		dibh = bh;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
680
681
  		top = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0];
  		bottom = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs;
b3b94faa5   David Teigland   [GFS2] The core o...
682
683
684
685
  	} else {
  		error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
  		if (error)
  			return error;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
686
  		top = (__be64 *)(bh->b_data + mh_size) +
c53921248   Jan Engelhardt   [GFS2] More style...
687
  				  (first ? mp->mp_list[height] : 0);
b3b94faa5   David Teigland   [GFS2] The core o...
688

b44b84d76   Al Viro   [GFS2] gfs2 misc ...
689
  		bottom = (__be64 *)(bh->b_data + mh_size) + sdp->sd_inptrs;
b3b94faa5   David Teigland   [GFS2] The core o...
690
691
692
693
694
  	}
  
  	error = bc(ip, dibh, bh, top, bottom, height, data);
  	if (error)
  		goto out;
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
695
  	if (height < ip->i_height - 1)
b3b94faa5   David Teigland   [GFS2] The core o...
696
697
698
699
700
701
702
703
704
705
706
  		for (; top < bottom; top++, first = 0) {
  			if (!*top)
  				continue;
  
  			bn = be64_to_cpu(*top);
  
  			error = recursive_scan(ip, dibh, mp, height + 1, bn,
  					       first, bc, data);
  			if (error)
  				break;
  		}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
707
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
708
  	brelse(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
  	return error;
  }
  
  /**
   * do_strip - Look for a layer a particular layer of the file and strip it off
   * @ip: the inode
   * @dibh: the dinode buffer
   * @bh: A buffer of pointers
   * @top: The first pointer in the buffer
   * @bottom: One more than the last pointer
   * @height: the height this buffer is at
   * @data: a pointer to a struct strip_mine
   *
   * Returns: errno
   */
  
  static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
726
  		    struct buffer_head *bh, __be64 *top, __be64 *bottom,
b3b94faa5   David Teigland   [GFS2] The core o...
727
728
  		    unsigned int height, void *data)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
729
730
  	struct strip_mine *sm = data;
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
731
  	struct gfs2_rgrp_list rlist;
cd915493f   Steven Whitehouse   [GFS2] Change all...
732
733
  	u64 bn, bstart;
  	u32 blen;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
734
  	__be64 *p;
b3b94faa5   David Teigland   [GFS2] The core o...
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
  	unsigned int rg_blocks = 0;
  	int metadata;
  	unsigned int revokes = 0;
  	int x;
  	int error;
  
  	if (!*top)
  		sm->sm_first = 0;
  
  	if (height != sm->sm_height)
  		return 0;
  
  	if (sm->sm_first) {
  		top++;
  		sm->sm_first = 0;
  	}
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
751
  	metadata = (height != ip->i_height - 1);
b3b94faa5   David Teigland   [GFS2] The core o...
752
753
  	if (metadata)
  		revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
6dbd82248   Steven Whitehouse   [GFS2] Reduce ino...
754
  	error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
  	if (error)
  		return error;
  
  	memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
  	bstart = 0;
  	blen = 0;
  
  	for (p = top; p < bottom; p++) {
  		if (!*p)
  			continue;
  
  		bn = be64_to_cpu(*p);
  
  		if (bstart + blen == bn)
  			blen++;
  		else {
  			if (bstart)
  				gfs2_rlist_add(sdp, &rlist, bstart);
  
  			bstart = bn;
  			blen = 1;
  		}
  	}
  
  	if (bstart)
  		gfs2_rlist_add(sdp, &rlist, bstart);
  	else
  		goto out; /* Nothing to do */
fe6c991c5   Bob Peterson   [GFS2] Get rid of...
783
  	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
b3b94faa5   David Teigland   [GFS2] The core o...
784
785
786
  
  	for (x = 0; x < rlist.rl_rgrps; x++) {
  		struct gfs2_rgrpd *rgd;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
787
  		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
788
  		rg_blocks += rgd->rd_length;
b3b94faa5   David Teigland   [GFS2] The core o...
789
790
791
792
793
794
795
796
797
798
799
800
801
  	}
  
  	error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
  	if (error)
  		goto out_rlist;
  
  	error = gfs2_trans_begin(sdp, rg_blocks + RES_DINODE +
  				 RES_INDIRECT + RES_STATFS + RES_QUOTA,
  				 revokes);
  	if (error)
  		goto out_rg_gunlock;
  
  	down_write(&ip->i_rw_mutex);
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
802
803
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
  	gfs2_trans_add_bh(ip->i_gl, bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
  
  	bstart = 0;
  	blen = 0;
  
  	for (p = top; p < bottom; p++) {
  		if (!*p)
  			continue;
  
  		bn = be64_to_cpu(*p);
  
  		if (bstart + blen == bn)
  			blen++;
  		else {
  			if (bstart) {
  				if (metadata)
  					gfs2_free_meta(ip, bstart, blen);
  				else
  					gfs2_free_data(ip, bstart, blen);
  			}
  
  			bstart = bn;
  			blen = 1;
  		}
  
  		*p = 0;
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
829
  		gfs2_add_inode_blocks(&ip->i_inode, -1);
b3b94faa5   David Teigland   [GFS2] The core o...
830
831
832
833
834
835
836
  	}
  	if (bstart) {
  		if (metadata)
  			gfs2_free_meta(ip, bstart, blen);
  		else
  			gfs2_free_data(ip, bstart, blen);
  	}
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
837
  	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
b3b94faa5   David Teigland   [GFS2] The core o...
838

539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
839
  	gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
840
841
842
843
  
  	up_write(&ip->i_rw_mutex);
  
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
844
  out_rg_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
845
  	gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
846
  out_rlist:
b3b94faa5   David Teigland   [GFS2] The core o...
847
  	gfs2_rlist_free(&rlist);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
848
  out:
6dbd82248   Steven Whitehouse   [GFS2] Reduce ino...
849
  	gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
850
851
852
853
854
855
856
857
858
859
860
861
  	return error;
  }
  
  /**
   * do_grow - Make a file look bigger than it is
   * @ip: the inode
   * @size: the size to set the file to
   *
   * Called with an exclusive lock on @ip.
   *
   * Returns: errno
   */
cd915493f   Steven Whitehouse   [GFS2] Change all...
862
  static int do_grow(struct gfs2_inode *ip, u64 size)
b3b94faa5   David Teigland   [GFS2] The core o...
863
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
864
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
865
866
  	struct gfs2_alloc *al;
  	struct buffer_head *dibh;
b3b94faa5   David Teigland   [GFS2] The core o...
867
868
869
  	int error;
  
  	al = gfs2_alloc_get(ip);
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
870
871
  	if (!al)
  		return -ENOMEM;
b3b94faa5   David Teigland   [GFS2] The core o...
872

d82661d96   Steven Whitehouse   [GFS2] Streamline...
873
  	error = gfs2_quota_lock_check(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
874
875
  	if (error)
  		goto out;
b3b94faa5   David Teigland   [GFS2] The core o...
876
877
878
879
880
881
882
  	al->al_requested = sdp->sd_max_height + RES_DATA;
  
  	error = gfs2_inplace_reserve(ip);
  	if (error)
  		goto out_gunlock_q;
  
  	error = gfs2_trans_begin(sdp,
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
883
  			sdp->sd_max_height + al->al_rgd->rd_length +
b3b94faa5   David Teigland   [GFS2] The core o...
884
885
886
  			RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
  	if (error)
  		goto out_ipres;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
887
888
889
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto out_end_trans;
b3b94faa5   David Teigland   [GFS2] The core o...
890
891
  	if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
  		if (gfs2_is_stuffed(ip)) {
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
892
  			error = gfs2_unstuff_dinode(ip, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
893
  			if (error)
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
894
  				goto out_brelse;
b3b94faa5   David Teigland   [GFS2] The core o...
895
896
  		}
  	}
c9e988867   Steven Whitehouse   GFS2: Move i_size...
897
  	ip->i_disksize = size;
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
898
  	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
899
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
900
  	gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
901

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
902
903
  out_brelse:
  	brelse(dibh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
904
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
905
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
906
  out_ipres:
b3b94faa5   David Teigland   [GFS2] The core o...
907
  	gfs2_inplace_release(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
908
  out_gunlock_q:
b3b94faa5   David Teigland   [GFS2] The core o...
909
  	gfs2_quota_unlock(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
910
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
911
  	gfs2_alloc_put(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
912
913
  	return error;
  }
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
914
915
916
917
918
919
920
921
922
923
  
  /**
   * gfs2_block_truncate_page - Deal with zeroing out data for truncate
   *
   * This is partly borrowed from ext3.
   */
  static int gfs2_block_truncate_page(struct address_space *mapping)
  {
  	struct inode *inode = mapping->host;
  	struct gfs2_inode *ip = GFS2_I(inode);
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
924
925
926
927
928
929
  	loff_t from = inode->i_size;
  	unsigned long index = from >> PAGE_CACHE_SHIFT;
  	unsigned offset = from & (PAGE_CACHE_SIZE-1);
  	unsigned blocksize, iblock, length, pos;
  	struct buffer_head *bh;
  	struct page *page;
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
  	int err;
  
  	page = grab_cache_page(mapping, index);
  	if (!page)
  		return 0;
  
  	blocksize = inode->i_sb->s_blocksize;
  	length = blocksize - (offset & (blocksize - 1));
  	iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
  
  	if (!page_has_buffers(page))
  		create_empty_buffers(page, blocksize, 0);
  
  	/* Find the buffer that contains "offset" */
  	bh = page_buffers(page);
  	pos = blocksize;
  	while (offset >= pos) {
  		bh = bh->b_this_page;
  		iblock++;
  		pos += blocksize;
  	}
  
  	err = 0;
  
  	if (!buffer_mapped(bh)) {
e9e1ef2b6   Bob Peterson   [GFS2] Remove fun...
955
  		gfs2_block_map(inode, iblock, bh, 0);
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
  		/* unmapped? It's a hole - nothing to do */
  		if (!buffer_mapped(bh))
  			goto unlock;
  	}
  
  	/* Ok, it's mapped. Make sure it's up-to-date */
  	if (PageUptodate(page))
  		set_buffer_uptodate(bh);
  
  	if (!buffer_uptodate(bh)) {
  		err = -EIO;
  		ll_rw_block(READ, 1, &bh);
  		wait_on_buffer(bh);
  		/* Uhhuh. Read error. Complain and punt. */
  		if (!buffer_uptodate(bh))
  			goto unlock;
1875f2f31   S. Wendy Cheng   [GFS2] Fix gfs2_b...
972
  		err = 0;
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
973
  	}
bf36a7131   Steven Whitehouse   [GFS2] Add gfs2_i...
974
  	if (!gfs2_is_writeback(ip))
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
975
  		gfs2_trans_add_bh(ip->i_gl, bh, 0);
eebd2aa35   Christoph Lameter   Pagecache zeroing...
976
  	zero_user(page, offset, length);
40bc9a27e   Steven Whitehouse   GFS2: Fix cache c...
977
  	mark_buffer_dirty(bh);
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
978
979
980
981
982
  unlock:
  	unlock_page(page);
  	page_cache_release(page);
  	return err;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
983
  static int trunc_start(struct gfs2_inode *ip, u64 size)
b3b94faa5   David Teigland   [GFS2] The core o...
984
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
985
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
986
987
988
989
990
  	struct buffer_head *dibh;
  	int journaled = gfs2_is_jdata(ip);
  	int error;
  
  	error = gfs2_trans_begin(sdp,
c53921248   Jan Engelhardt   [GFS2] More style...
991
  				 RES_DINODE + (journaled ? RES_JDATA : 0), 0);
b3b94faa5   David Teigland   [GFS2] The core o...
992
993
994
995
996
997
998
999
  	if (error)
  		return error;
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto out;
  
  	if (gfs2_is_stuffed(ip)) {
c639d5d8f   Abhijith Das   GFS2: Fix typo in...
1000
  		u64 dsize = size + sizeof(struct gfs2_dinode);
a8bf2bc21   Bob Peterson   GFS2: O_TRUNC not...
1001
  		ip->i_disksize = size;
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
1002
  		ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1003
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
1004
  		gfs2_dinode_out(ip, dibh->b_data);
602c89d2e   Steven Whitehouse   GFS2: Clean up st...
1005
1006
1007
  		if (dsize > dibh->b_size)
  			dsize = dibh->b_size;
  		gfs2_buffer_clear_tail(dibh, dsize);
b3b94faa5   David Teigland   [GFS2] The core o...
1008
  		error = 1;
b3b94faa5   David Teigland   [GFS2] The core o...
1009
  	} else {
cd915493f   Steven Whitehouse   [GFS2] Change all...
1010
  		if (size & (u64)(sdp->sd_sb.sb_bsize - 1))
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1011
  			error = gfs2_block_truncate_page(ip->i_inode.i_mapping);
b3b94faa5   David Teigland   [GFS2] The core o...
1012
1013
  
  		if (!error) {
c9e988867   Steven Whitehouse   GFS2: Move i_size...
1014
  			ip->i_disksize = size;
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
1015
  			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
1016
  			ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1017
  			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
1018
  			gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
1019
1020
1021
1022
  		}
  	}
  
  	brelse(dibh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1023
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
1024
  	gfs2_trans_end(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
1025
1026
  	return error;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
1027
  static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
b3b94faa5   David Teigland   [GFS2] The core o...
1028
  {
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
1029
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
1030
  	unsigned int height = ip->i_height;
cd915493f   Steven Whitehouse   [GFS2] Change all...
1031
  	u64 lblock;
b3b94faa5   David Teigland   [GFS2] The core o...
1032
1033
1034
1035
1036
  	struct metapath mp;
  	int error;
  
  	if (!size)
  		lblock = 0;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
1037
  	else
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
1038
  		lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift;
b3b94faa5   David Teigland   [GFS2] The core o...
1039

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
1040
  	find_metapath(sdp, lblock, &mp, ip->i_height);
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
1041
1042
  	if (!gfs2_alloc_get(ip))
  		return -ENOMEM;
b3b94faa5   David Teigland   [GFS2] The core o...
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
  
  	error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
  	if (error)
  		goto out;
  
  	while (height--) {
  		struct strip_mine sm;
  		sm.sm_first = !!size;
  		sm.sm_height = height;
  
  		error = recursive_scan(ip, NULL, &mp, 0, 0, 1, do_strip, &sm);
  		if (error)
  			break;
  	}
  
  	gfs2_quota_unhold(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1059
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
1060
1061
1062
1063
1064
1065
  	gfs2_alloc_put(ip);
  	return error;
  }
  
  static int trunc_end(struct gfs2_inode *ip)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1066
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
  	struct buffer_head *dibh;
  	int error;
  
  	error = gfs2_trans_begin(sdp, RES_DINODE, 0);
  	if (error)
  		return error;
  
  	down_write(&ip->i_rw_mutex);
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto out;
c9e988867   Steven Whitehouse   GFS2: Move i_size...
1079
  	if (!ip->i_disksize) {
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
1080
  		ip->i_height = 0;
ce276b06e   Steven Whitehouse   [GFS2] Reduce ino...
1081
  		ip->i_goal = ip->i_no_addr;
b3b94faa5   David Teigland   [GFS2] The core o...
1082
1083
  		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
  	}
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
1084
  	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
1085
  	ip->i_diskflags &= ~GFS2_DIF_TRUNC_IN_PROG;
b3b94faa5   David Teigland   [GFS2] The core o...
1086

d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1087
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
1088
  	gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
1089
  	brelse(dibh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1090
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
1091
  	up_write(&ip->i_rw_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
1092
  	gfs2_trans_end(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
  	return error;
  }
  
  /**
   * do_shrink - make a file smaller
   * @ip: the inode
   * @size: the size to make the file
   * @truncator: function to truncate the last partial block
   *
   * Called with an exclusive lock on @ip.
   *
   * Returns: errno
   */
cd915493f   Steven Whitehouse   [GFS2] Change all...
1106
  static int do_shrink(struct gfs2_inode *ip, u64 size)
b3b94faa5   David Teigland   [GFS2] The core o...
1107
1108
  {
  	int error;
aa6a85a97   Steven Whitehouse   [GFS2] Remove poi...
1109
  	error = trunc_start(ip, size);
b3b94faa5   David Teigland   [GFS2] The core o...
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
  	if (error < 0)
  		return error;
  	if (error > 0)
  		return 0;
  
  	error = trunc_dealloc(ip, size);
  	if (!error)
  		error = trunc_end(ip);
  
  	return error;
  }
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  static int do_touch(struct gfs2_inode *ip, u64 size)
  {
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
  	struct buffer_head *dibh;
  	int error;
  
  	error = gfs2_trans_begin(sdp, RES_DINODE, 0);
  	if (error)
  		return error;
  
  	down_write(&ip->i_rw_mutex);
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto do_touch_out;
  
  	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
  	gfs2_dinode_out(ip, dibh->b_data);
  	brelse(dibh);
  
  do_touch_out:
  	up_write(&ip->i_rw_mutex);
  	gfs2_trans_end(sdp);
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1147
  /**
666a2c534   Steven Whitehouse   [GFS2] Remove unu...
1148
   * gfs2_truncatei - make a file a given size
b3b94faa5   David Teigland   [GFS2] The core o...
1149
1150
1151
1152
1153
1154
1155
1156
   * @ip: the inode
   * @size: the size to make the file
   * @truncator: function to truncate the last partial block
   *
   * The file size can grow, shrink, or stay the same size.
   *
   * Returns: errno
   */
cd915493f   Steven Whitehouse   [GFS2] Change all...
1157
  int gfs2_truncatei(struct gfs2_inode *ip, u64 size)
b3b94faa5   David Teigland   [GFS2] The core o...
1158
1159
  {
  	int error;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
1160
  	if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode)))
b3b94faa5   David Teigland   [GFS2] The core o...
1161
  		return -EINVAL;
c9e988867   Steven Whitehouse   GFS2: Move i_size...
1162
  	if (size > ip->i_disksize)
b3b94faa5   David Teigland   [GFS2] The core o...
1163
  		error = do_grow(ip, size);
c9e988867   Steven Whitehouse   GFS2: Move i_size...
1164
  	else if (size < ip->i_disksize)
aa6a85a97   Steven Whitehouse   [GFS2] Remove poi...
1165
  		error = do_shrink(ip, size);
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1166
1167
1168
  	else
  		/* update time stamps */
  		error = do_touch(ip, size);
b3b94faa5   David Teigland   [GFS2] The core o...
1169
1170
1171
1172
1173
1174
1175
  
  	return error;
  }
  
  int gfs2_truncatei_resume(struct gfs2_inode *ip)
  {
  	int error;
c9e988867   Steven Whitehouse   GFS2: Move i_size...
1176
  	error = trunc_dealloc(ip, ip->i_disksize);
b3b94faa5   David Teigland   [GFS2] The core o...
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
  	if (!error)
  		error = trunc_end(ip);
  	return error;
  }
  
  int gfs2_file_dealloc(struct gfs2_inode *ip)
  {
  	return trunc_dealloc(ip, 0);
  }
  
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
1188
1189
1190
1191
   * gfs2_write_alloc_required - figure out if a write will require an allocation
   * @ip: the file being written to
   * @offset: the offset to write to
   * @len: the number of bytes being written
b3b94faa5   David Teigland   [GFS2] The core o...
1192
   *
461cb419f   Bob Peterson   GFS2: Simplify gf...
1193
   * Returns: 1 if an alloc is required, 0 otherwise
b3b94faa5   David Teigland   [GFS2] The core o...
1194
   */
cd915493f   Steven Whitehouse   [GFS2] Change all...
1195
  int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
461cb419f   Bob Peterson   GFS2: Simplify gf...
1196
  			      unsigned int len)
b3b94faa5   David Teigland   [GFS2] The core o...
1197
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1198
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
1199
1200
1201
  	struct buffer_head bh;
  	unsigned int shift;
  	u64 lblock, lblock_stop, size;
7ed122e42   Steven Whitehouse   GFS2: Streamline ...
1202
  	u64 end_of_file;
b3b94faa5   David Teigland   [GFS2] The core o...
1203

b3b94faa5   David Teigland   [GFS2] The core o...
1204
1205
1206
1207
1208
1209
  	if (!len)
  		return 0;
  
  	if (gfs2_is_stuffed(ip)) {
  		if (offset + len >
  		    sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode))
461cb419f   Bob Peterson   GFS2: Simplify gf...
1210
  			return 1;
b3b94faa5   David Teigland   [GFS2] The core o...
1211
1212
  		return 0;
  	}
941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
1213
  	shift = sdp->sd_sb.sb_bsize_shift;
7ed122e42   Steven Whitehouse   GFS2: Streamline ...
1214
1215
1216
1217
1218
  	BUG_ON(gfs2_is_dir(ip));
  	end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift;
  	lblock = offset >> shift;
  	lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
  	if (lblock_stop > end_of_file)
461cb419f   Bob Peterson   GFS2: Simplify gf...
1219
  		return 1;
b3b94faa5   David Teigland   [GFS2] The core o...
1220

941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
1221
1222
1223
1224
1225
1226
  	size = (lblock_stop - lblock) << shift;
  	do {
  		bh.b_state = 0;
  		bh.b_size = size;
  		gfs2_block_map(&ip->i_inode, lblock, &bh, 0);
  		if (!buffer_mapped(&bh))
461cb419f   Bob Peterson   GFS2: Simplify gf...
1227
  			return 1;
941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
1228
1229
1230
  		size -= bh.b_size;
  		lblock += (bh.b_size >> ip->i_inode.i_blkbits);
  	} while(size > 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1231
1232
1233
  
  	return 0;
  }