Blame view

fs/gfs2/bmap.c 32 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>
64dd153c8   Benjamin Marzinski   GFS2: rewrite fal...
12
  #include <linux/blkdev.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
13
  #include <linux/gfs2_ondisk.h>
71b86f562   Steven Whitehouse   [GFS2] Further up...
14
  #include <linux/crc32.h>
b3b94faa5   David Teigland   [GFS2] The core o...
15
16
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
17
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
18
19
20
  #include "bmap.h"
  #include "glock.h"
  #include "inode.h"
b3b94faa5   David Teigland   [GFS2] The core o...
21
  #include "meta_io.h"
b3b94faa5   David Teigland   [GFS2] The core o...
22
23
  #include "quota.h"
  #include "rgrp.h"
4c16c36ad   Bob Peterson   GFS2: deallocatio...
24
  #include "super.h"
b3b94faa5   David Teigland   [GFS2] The core o...
25
  #include "trans.h"
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
26
  #include "dir.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
27
  #include "util.h"
63997775b   Steven Whitehouse   GFS2: Add tracepo...
28
  #include "trace_gfs2.h"
b3b94faa5   David Teigland   [GFS2] The core o...
29
30
31
32
33
34
  
  /* 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 ...
35
  	struct buffer_head *mp_bh[GFS2_MAX_META_HEIGHT];
b3b94faa5   David Teigland   [GFS2] The core o...
36
37
  	__u16 mp_list[GFS2_MAX_META_HEIGHT];
  };
b3b94faa5   David Teigland   [GFS2] The core o...
38
39
40
41
42
43
  struct strip_mine {
  	int sm_first;
  	unsigned int sm_height;
  };
  
  /**
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
44
45
46
47
   * 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
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
48
   * @page: The (optional) page. This is looked up if @page is NULL
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
49
50
51
52
53
   *
   * Returns: errno
   */
  
  static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
cd915493f   Steven Whitehouse   [GFS2] Change all...
54
  			       u64 block, struct page *page)
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
55
  {
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
56
57
58
59
60
61
62
63
64
65
66
67
68
  	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...
69
70
71
72
  		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_...
73

602c89d2e   Steven Whitehouse   GFS2: Clean up st...
74
75
  		memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
  		memset(kaddr + dsize, 0, PAGE_CACHE_SIZE - dsize);
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  		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...
91
92
  	if (!gfs2_is_jdata(ip))
  		mark_buffer_dirty(bh);
bf36a7131   Steven Whitehouse   [GFS2] Add gfs2_i...
93
  	if (!gfs2_is_writeback(ip))
8475487be   Bob Peterson   [GFS2] Fix orderi...
94
  		gfs2_trans_add_bh(ip->i_gl, bh, 0);
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
95
96
97
98
99
100
101
102
103
104
  
  	if (release) {
  		unlock_page(page);
  		page_cache_release(page);
  	}
  
  	return 0;
  }
  
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
105
106
   * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big
   * @ip: The GFS2 inode to unstuff
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
107
   * @page: The (optional) page. This is looked up if the @page is NULL
b3b94faa5   David Teigland   [GFS2] The core o...
108
109
110
111
112
113
   *
   * 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_...
114
  int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
b3b94faa5   David Teigland   [GFS2] The core o...
115
116
  {
  	struct buffer_head *bh, *dibh;
48516ced2   Steven Whitehouse   [GFS2] Remove une...
117
  	struct gfs2_dinode *di;
cd915493f   Steven Whitehouse   [GFS2] Change all...
118
  	u64 block = 0;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
119
  	int isdir = gfs2_is_dir(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
120
121
122
123
124
125
126
  	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...
127

a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
128
  	if (i_size_read(&ip->i_inode)) {
b3b94faa5   David Teigland   [GFS2] The core o...
129
130
  		/* Get a free block, fill it with the stuffed data,
  		   and write it out to disk */
b45e41d7d   Steven Whitehouse   [GFS2] Add extent...
131
  		unsigned int n = 1;
6e87ed0fc   Bob Peterson   GFS2: move toward...
132
  		error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL);
090109783   Steven Whitehouse   GFS2: Improve res...
133
134
  		if (error)
  			goto out_brelse;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
135
  		if (isdir) {
5731be53e   Steven Whitehouse   [GFS2] Update gfs...
136
  			gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1);
61e085a88   Steven Whitehouse   [GFS2] Tidy up di...
137
  			error = gfs2_dir_get_new_buffer(ip, block, &bh);
b3b94faa5   David Teigland   [GFS2] The core o...
138
139
  			if (error)
  				goto out_brelse;
48516ced2   Steven Whitehouse   [GFS2] Remove une...
140
  			gfs2_buffer_copy_tail(bh, sizeof(struct gfs2_meta_header),
b3b94faa5   David Teigland   [GFS2] The core o...
141
142
143
  					      dibh, sizeof(struct gfs2_dinode));
  			brelse(bh);
  		} else {
f25ef0c1b   Steven Whitehouse   [GFS2] Tidy gfs2_...
144
  			error = gfs2_unstuffer_page(ip, dibh, block, page);
b3b94faa5   David Teigland   [GFS2] The core o...
145
146
147
148
149
150
  			if (error)
  				goto out_brelse;
  		}
  	}
  
  	/*  Set up the pointer to the new block  */
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
151
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
48516ced2   Steven Whitehouse   [GFS2] Remove une...
152
  	di = (struct gfs2_dinode *)dibh->b_data;
b3b94faa5   David Teigland   [GFS2] The core o...
153
  	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
154
  	if (i_size_read(&ip->i_inode)) {
48516ced2   Steven Whitehouse   [GFS2] Remove une...
155
  		*(__be64 *)(di + 1) = cpu_to_be64(block);
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
156
157
  		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...
158
  	}
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
159
  	ip->i_height = 1;
48516ced2   Steven Whitehouse   [GFS2] Remove une...
160
  	di->di_height = cpu_to_be16(1);
b3b94faa5   David Teigland   [GFS2] The core o...
161

a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
162
  out_brelse:
b3b94faa5   David Teigland   [GFS2] The core o...
163
  	brelse(dibh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
164
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
165
  	up_write(&ip->i_rw_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
166
167
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
168
169
170
  
  /**
   * find_metapath - Find path through the metadata tree
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
171
   * @sdp: The superblock
b3b94faa5   David Teigland   [GFS2] The core o...
172
173
   * @mp: The metapath to return the result in
   * @block: The disk block to look up
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
174
   * @height: The pre-calculated height of the metadata tree
b3b94faa5   David Teigland   [GFS2] The core o...
175
176
177
178
179
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
   *
   *   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...
228
229
  static void find_metapath(const struct gfs2_sbd *sdp, u64 block,
  			  struct metapath *mp, unsigned int height)
b3b94faa5   David Teigland   [GFS2] The core o...
230
  {
b3b94faa5   David Teigland   [GFS2] The core o...
231
  	unsigned int i;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
232
  	for (i = height; i--;)
7eabb77e6   Bob Peterson   [GFS2] Misc fixups
233
  		mp->mp_list[i] = do_div(block, sdp->sd_inptrs);
b3b94faa5   David Teigland   [GFS2] The core o...
234
235
  
  }
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
236
  static inline unsigned int metapath_branch_start(const struct metapath *mp)
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
237
  {
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
238
239
240
  	if (mp->mp_list[0] == 0)
  		return 2;
  	return 1;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
241
  }
b3b94faa5   David Teigland   [GFS2] The core o...
242
243
  /**
   * metapointer - Return pointer to start of metadata in a buffer
b3b94faa5   David Teigland   [GFS2] The core o...
244
245
246
247
248
249
250
   * @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...
251
  static inline __be64 *metapointer(unsigned int height, const struct metapath *mp)
b3b94faa5   David Teigland   [GFS2] The core o...
252
  {
dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
253
  	struct buffer_head *bh = mp->mp_bh[height];
b3b94faa5   David Teigland   [GFS2] The core o...
254
255
  	unsigned int head_size = (height > 0) ?
  		sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
256
  	return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
b3b94faa5   David Teigland   [GFS2] The core o...
257
  }
b99b98dc2   Steven Whitehouse   GFS2: Move readah...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  static void gfs2_metapath_ra(struct gfs2_glock *gl,
  			     const struct buffer_head *bh, const __be64 *pos)
  {
  	struct buffer_head *rabh;
  	const __be64 *endp = (const __be64 *)(bh->b_data + bh->b_size);
  	const __be64 *t;
  
  	for (t = pos; t < endp; t++) {
  		if (!*t)
  			continue;
  
  		rabh = gfs2_getbuf(gl, be64_to_cpu(*t), CREATE);
  		if (trylock_buffer(rabh)) {
  			if (!buffer_uptodate(rabh)) {
  				rabh->b_end_io = end_buffer_read_sync;
  				submit_bh(READA | REQ_META, rabh);
  				continue;
  			}
  			unlock_buffer(rabh);
  		}
  		brelse(rabh);
  	}
  }
b3b94faa5   David Teigland   [GFS2] The core o...
281
  /**
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
282
283
   * lookup_metapath - Walk the metadata tree to a specific point
   * @ip: The inode
b3b94faa5   David Teigland   [GFS2] The core o...
284
   * @mp: The metapath
b3b94faa5   David Teigland   [GFS2] The core o...
285
   *
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
286
287
288
289
290
291
292
293
   * 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...
294
   *
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
295
   * Returns: error or height of metadata tree
b3b94faa5   David Teigland   [GFS2] The core o...
296
   */
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
297
  static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp)
11707ea05   Steven Whitehouse   [GFS2] Move part ...
298
  {
11707ea05   Steven Whitehouse   [GFS2] Move part ...
299
300
  	unsigned int end_of_metadata = ip->i_height - 1;
  	unsigned int x;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
301
302
  	__be64 *ptr;
  	u64 dblock;
e23159d2a   Steven Whitehouse   [GFS2] Get inode ...
303
  	int ret;
11707ea05   Steven Whitehouse   [GFS2] Move part ...
304
305
  
  	for (x = 0; x < end_of_metadata; x++) {
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
306
307
308
309
  		ptr = metapointer(x, mp);
  		dblock = be64_to_cpu(*ptr);
  		if (!dblock)
  			return x + 1;
11707ea05   Steven Whitehouse   [GFS2] Move part ...
310

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
311
  		ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]);
11707ea05   Steven Whitehouse   [GFS2] Move part ...
312
313
314
  		if (ret)
  			return ret;
  	}
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
315
  	return ip->i_height;
dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
316
  }
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
317
  static inline void release_metapath(struct metapath *mp)
dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
318
319
  {
  	int i;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
320
321
322
323
324
  	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 ...
325
  }
30cbf189c   Steven Whitehouse   [GFS2] Add a func...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  /**
   * 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...
361
  static inline void bmap_lock(struct gfs2_inode *ip, int create)
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
362
  {
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
363
364
365
366
367
  	if (create)
  		down_write(&ip->i_rw_mutex);
  	else
  		down_read(&ip->i_rw_mutex);
  }
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
368
  static inline void bmap_unlock(struct gfs2_inode *ip, int create)
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
369
  {
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
370
371
372
373
374
  	if (create)
  		up_write(&ip->i_rw_mutex);
  	else
  		up_read(&ip->i_rw_mutex);
  }
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
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
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
  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);
64dd153c8   Benjamin Marzinski   GFS2: rewrite fal...
432
  	struct super_block *sb = sdp->sd_vfs;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
433
434
  	struct buffer_head *dibh = mp->mp_bh[0];
  	u64 bn, dblock = 0;
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
435
  	unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
436
437
438
  	unsigned dblks = 0;
  	unsigned ptrs_per_blk;
  	const unsigned end_of_metadata = height - 1;
64dd153c8   Benjamin Marzinski   GFS2: rewrite fal...
439
  	int ret;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
  	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...
471
472
  			branch_start = metapath_branch_start(mp);
  			iblks += (height - branch_start);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
473
474
475
476
477
478
479
480
  		}
  	}
  
  	/* start of the second part of the function (state machine) */
  
  	blks = dblks + iblks;
  	i = sheight;
  	do {
090109783   Steven Whitehouse   GFS2: Improve res...
481
  		int error;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
482
  		n = blks - alloced;
6e87ed0fc   Bob Peterson   GFS2: move toward...
483
  		error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
090109783   Steven Whitehouse   GFS2: Improve res...
484
485
  		if (error)
  			return error;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  		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...
511
  				for(i = branch_start; i < height; i++) {
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
512
513
514
515
516
  					if (mp->mp_bh[i] == NULL)
  						break;
  					brelse(mp->mp_bh[i]);
  					mp->mp_bh[i] = NULL;
  				}
5af4e7a0b   Benjamin Marzinski   [GFS2] fix gfs2 b...
517
  				i = branch_start;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
  			}
  			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++);
64dd153c8   Benjamin Marzinski   GFS2: rewrite fal...
542
543
544
545
546
547
548
549
550
551
  			if (buffer_zeronew(bh_map)) {
  				ret = sb_issue_zeroout(sb, dblock, dblks,
  						       GFP_NOFS);
  				if (ret) {
  					fs_err(sdp,
  					       "Failed to zero data buffers
  ");
  					clear_buffer_zeronew(bh_map);
  				}
  			}
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
552
553
  			break;
  		}
07ccb7bf2   Steven Whitehouse   GFS2: Fix bmap al...
554
  	} while ((state != ALLOC_DATA) || !dblock);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
555
556
557
558
559
560
561
562
563
  
  	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...
564
  /**
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
565
   * gfs2_block_map - Map a block from an inode to a disk block
fd88de569   Steven Whitehouse   [GFS2] Readpages ...
566
   * @inode: The inode
b3b94faa5   David Teigland   [GFS2] The core o...
567
   * @lblock: The logical block number
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
568
   * @bh_map: The bh to be mapped
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
569
   * @create: True if its ok to alloc blocks to satify the request
b3b94faa5   David Teigland   [GFS2] The core o...
570
   *
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
571
572
573
   * 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...
574
575
576
   *
   * Returns: errno
   */
e9e1ef2b6   Bob Peterson   [GFS2] Remove fun...
577
578
  int gfs2_block_map(struct inode *inode, sector_t lblock,
  		   struct buffer_head *bh_map, int create)
b3b94faa5   David Teigland   [GFS2] The core o...
579
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
580
581
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
582
  	unsigned int bsize = sdp->sd_sb.sb_bsize;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
583
  	const unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
584
  	const u64 *arr = sdp->sd_heightsize;
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
585
586
587
588
589
590
591
592
  	__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...
593

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

dbac6710a   Steven Whitehouse   [GFS2] Introduce ...
596
  	memset(mp.mp_bh, 0, sizeof(mp.mp_bh));
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
597
  	bmap_lock(ip, create);
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
598
599
600
  	clear_buffer_mapped(bh_map);
  	clear_buffer_new(bh_map);
  	clear_buffer_boundary(bh_map);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
601
  	trace_gfs2_bmap(ip, bh_map, lblock, create, 1);
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
602
603
604
605
  	if (gfs2_is_dir(ip)) {
  		bsize = sdp->sd_jbsize;
  		arr = sdp->sd_jheightsize;
  	}
4cf1ed814   Steven Whitehouse   [GFS2] Tidy up bm...
606

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
607
608
609
  	ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]);
  	if (ret)
  		goto out;
b3b94faa5   David Teigland   [GFS2] The core o...
610

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
  	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...
636
  	trace_gfs2_bmap(ip, bh_map, lblock, create, ret);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
637
638
  	bmap_unlock(ip, create);
  	return ret;
30cbf189c   Steven Whitehouse   [GFS2] Add a func...
639

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
640
641
642
643
644
645
  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...
646
  	}
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
647
648
649
650
  
  	/* 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 ...
651
  }
941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
652
653
654
  /*
   * Deprecated: do not use in new code
   */
fd88de569   Steven Whitehouse   [GFS2] Readpages ...
655
656
  int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
  {
23591256d   Steven Whitehouse   [GFS2] Fix bmap t...
657
  	struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 };
7a6bbacbb   Steven Whitehouse   [GFS2] Map multip...
658
  	int ret;
fd88de569   Steven Whitehouse   [GFS2] Readpages ...
659
660
661
662
663
  	int create = *new;
  
  	BUG_ON(!extlen);
  	BUG_ON(!dblock);
  	BUG_ON(!new);
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
664
  	bh.b_size = 1 << (inode->i_blkbits + (create ? 0 : 5));
e9e1ef2b6   Bob Peterson   [GFS2] Remove fun...
665
  	ret = gfs2_block_map(inode, lblock, &bh, create);
7a6bbacbb   Steven Whitehouse   [GFS2] Map multip...
666
667
668
669
670
671
672
  	*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...
673
674
675
  }
  
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
676
677
678
679
680
681
682
683
684
685
686
687
688
   * 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 ...
689
  		    struct buffer_head *bh, __be64 *top, __be64 *bottom,
d56fa8a1c   Steven Whitehouse   GFS2: Call do_str...
690
  		    unsigned int height, struct strip_mine *sm)
b3b94faa5   David Teigland   [GFS2] The core o...
691
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
692
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
693
  	struct gfs2_rgrp_list rlist;
cd915493f   Steven Whitehouse   [GFS2] Change all...
694
  	u64 bn, bstart;
4c16c36ad   Bob Peterson   GFS2: deallocatio...
695
  	u32 blen, btotal;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
696
  	__be64 *p;
b3b94faa5   David Teigland   [GFS2] The core o...
697
698
699
700
  	unsigned int rg_blocks = 0;
  	int metadata;
  	unsigned int revokes = 0;
  	int x;
e06dfc492   Steven Whitehouse   GFS2: Fix uniniti...
701
  	int error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
702
703
704
705
706
707
708
709
710
711
712
  
  	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...
713
  	metadata = (height != ip->i_height - 1);
b3b94faa5   David Teigland   [GFS2] The core o...
714
715
  	if (metadata)
  		revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
6d3117b41   Steven Whitehouse   GFS2: Wipe direct...
716
717
  	else if (ip->i_depth)
  		revokes = sdp->sd_inptrs;
b3b94faa5   David Teigland   [GFS2] The core o...
718

b3b94faa5   David Teigland   [GFS2] The core o...
719
720
721
722
723
724
725
726
727
728
729
730
731
732
  	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)
70b0c3656   Steven Whitehouse   GFS2: Use cached ...
733
  				gfs2_rlist_add(ip, &rlist, bstart);
b3b94faa5   David Teigland   [GFS2] The core o...
734
735
736
737
738
739
740
  
  			bstart = bn;
  			blen = 1;
  		}
  	}
  
  	if (bstart)
70b0c3656   Steven Whitehouse   GFS2: Use cached ...
741
  		gfs2_rlist_add(ip, &rlist, bstart);
b3b94faa5   David Teigland   [GFS2] The core o...
742
743
  	else
  		goto out; /* Nothing to do */
fe6c991c5   Bob Peterson   [GFS2] Get rid of...
744
  	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
b3b94faa5   David Teigland   [GFS2] The core o...
745
746
747
  
  	for (x = 0; x < rlist.rl_rgrps; x++) {
  		struct gfs2_rgrpd *rgd;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
748
  		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
749
  		rg_blocks += rgd->rd_length;
b3b94faa5   David Teigland   [GFS2] The core o...
750
751
752
753
754
755
756
757
758
759
760
761
762
  	}
  
  	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...
763
764
  	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...
765
766
767
  
  	bstart = 0;
  	blen = 0;
4c16c36ad   Bob Peterson   GFS2: deallocatio...
768
  	btotal = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
769
770
771
772
773
774
775
776
777
778
779
  
  	for (p = top; p < bottom; p++) {
  		if (!*p)
  			continue;
  
  		bn = be64_to_cpu(*p);
  
  		if (bstart + blen == bn)
  			blen++;
  		else {
  			if (bstart) {
46fcb2ed2   Eric Sandeen   GFS2: combine dup...
780
  				__gfs2_free_blocks(ip, bstart, blen, metadata);
4c16c36ad   Bob Peterson   GFS2: deallocatio...
781
  				btotal += blen;
b3b94faa5   David Teigland   [GFS2] The core o...
782
783
784
785
786
787
788
  			}
  
  			bstart = bn;
  			blen = 1;
  		}
  
  		*p = 0;
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
789
  		gfs2_add_inode_blocks(&ip->i_inode, -1);
b3b94faa5   David Teigland   [GFS2] The core o...
790
791
  	}
  	if (bstart) {
46fcb2ed2   Eric Sandeen   GFS2: combine dup...
792
  		__gfs2_free_blocks(ip, bstart, blen, metadata);
4c16c36ad   Bob Peterson   GFS2: deallocatio...
793
  		btotal += blen;
b3b94faa5   David Teigland   [GFS2] The core o...
794
  	}
4c16c36ad   Bob Peterson   GFS2: deallocatio...
795
796
797
  	gfs2_statfs_change(sdp, 0, +btotal, 0);
  	gfs2_quota_change(ip, -(s64)btotal, ip->i_inode.i_uid,
  			  ip->i_inode.i_gid);
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
798
  	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
b3b94faa5   David Teigland   [GFS2] The core o...
799

539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
800
  	gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
801
802
803
804
  
  	up_write(&ip->i_rw_mutex);
  
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
805
  out_rg_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
806
  	gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
807
  out_rlist:
b3b94faa5   David Teigland   [GFS2] The core o...
808
  	gfs2_rlist_free(&rlist);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
809
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
810
811
812
813
  	return error;
  }
  
  /**
d56fa8a1c   Steven Whitehouse   GFS2: Call do_str...
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
   * 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
   * @sm: 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,
  			  u64 block, int first, struct strip_mine *sm)
  {
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
  	struct buffer_head *bh = NULL;
b99b98dc2   Steven Whitehouse   GFS2: Move readah...
835
  	__be64 *top, *bottom;
d56fa8a1c   Steven Whitehouse   GFS2: Call do_str...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
  	u64 bn;
  	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;
  
  		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;
  	} else {
  		error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
  		if (error)
  			return error;
  
  		top = (__be64 *)(bh->b_data + mh_size) +
  				  (first ? mp->mp_list[height] : 0);
  
  		bottom = (__be64 *)(bh->b_data + mh_size) + sdp->sd_inptrs;
  	}
  
  	error = do_strip(ip, dibh, bh, top, bottom, height, sm);
  	if (error)
  		goto out;
bd5437a7d   Bob Peterson   GFS2: speed up de...
862
  	if (height < ip->i_height - 1) {
bd5437a7d   Bob Peterson   GFS2: speed up de...
863

b99b98dc2   Steven Whitehouse   GFS2: Move readah...
864
  		gfs2_metapath_ra(ip->i_gl, bh, top);
bd5437a7d   Bob Peterson   GFS2: speed up de...
865

d56fa8a1c   Steven Whitehouse   GFS2: Call do_str...
866
867
868
869
870
871
872
873
874
875
876
  		for (; top < bottom; top++, first = 0) {
  			if (!*top)
  				continue;
  
  			bn = be64_to_cpu(*top);
  
  			error = recursive_scan(ip, dibh, mp, height + 1, bn,
  					       first, sm);
  			if (error)
  				break;
  		}
bd5437a7d   Bob Peterson   GFS2: speed up de...
877
  	}
d56fa8a1c   Steven Whitehouse   GFS2: Call do_str...
878
879
880
881
882
883
884
  out:
  	brelse(bh);
  	return error;
  }
  
  
  /**
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
885
886
887
888
   * gfs2_block_truncate_page - Deal with zeroing out data for truncate
   *
   * This is partly borrowed from ext3.
   */
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
889
  static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from)
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
890
891
892
  {
  	struct inode *inode = mapping->host;
  	struct gfs2_inode *ip = GFS2_I(inode);
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
893
894
895
896
897
  	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...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
  	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...
923
  		gfs2_block_map(inode, iblock, bh, 0);
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  		/* 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...
940
  		err = 0;
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
941
  	}
bf36a7131   Steven Whitehouse   [GFS2] Add gfs2_i...
942
  	if (!gfs2_is_writeback(ip))
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
943
  		gfs2_trans_add_bh(ip->i_gl, bh, 0);
eebd2aa35   Christoph Lameter   Pagecache zeroing...
944
  	zero_user(page, offset, length);
40bc9a27e   Steven Whitehouse   GFS2: Fix cache c...
945
  	mark_buffer_dirty(bh);
ba7f72901   Steven Whitehouse   [GFS2] Remove pag...
946
947
948
949
950
  unlock:
  	unlock_page(page);
  	page_cache_release(page);
  	return err;
  }
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
951
  static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
b3b94faa5   David Teigland   [GFS2] The core o...
952
  {
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
953
954
955
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
  	struct address_space *mapping = inode->i_mapping;
b3b94faa5   David Teigland   [GFS2] The core o...
956
957
958
959
960
  	struct buffer_head *dibh;
  	int journaled = gfs2_is_jdata(ip);
  	int error;
  
  	error = gfs2_trans_begin(sdp,
c53921248   Jan Engelhardt   [GFS2] More style...
961
  				 RES_DINODE + (journaled ? RES_JDATA : 0), 0);
b3b94faa5   David Teigland   [GFS2] The core o...
962
963
964
965
966
967
  	if (error)
  		return error;
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto out;
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
968
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
969
  	if (gfs2_is_stuffed(ip)) {
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
970
  		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize);
b3b94faa5   David Teigland   [GFS2] The core o...
971
  	} else {
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
972
973
974
975
  		if (newsize & (u64)(sdp->sd_sb.sb_bsize - 1)) {
  			error = gfs2_block_truncate_page(mapping, newsize);
  			if (error)
  				goto out_brelse;
b3b94faa5   David Teigland   [GFS2] The core o...
976
  		}
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
977
  		ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
b3b94faa5   David Teigland   [GFS2] The core o...
978
  	}
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
979
  	i_size_write(inode, newsize);
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
980
981
  	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
  	gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
982

ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
983
984
985
  	truncate_pagecache(inode, oldsize, newsize);
  out_brelse:
  	brelse(dibh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
986
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
987
  	gfs2_trans_end(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
988
989
  	return error;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
990
  static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
b3b94faa5   David Teigland   [GFS2] The core o...
991
  {
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
992
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
993
  	unsigned int height = ip->i_height;
cd915493f   Steven Whitehouse   [GFS2] Change all...
994
  	u64 lblock;
b3b94faa5   David Teigland   [GFS2] The core o...
995
996
997
998
999
  	struct metapath mp;
  	int error;
  
  	if (!size)
  		lblock = 0;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
1000
  	else
9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
1001
  		lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift;
b3b94faa5   David Teigland   [GFS2] The core o...
1002

9b8c81d1d   Steven Whitehouse   [GFS2] Allow bmap...
1003
  	find_metapath(sdp, lblock, &mp, ip->i_height);
564e12b11   Bob Peterson   GFS2: decouple qu...
1004
  	if (!gfs2_qadata_get(ip))
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
1005
  		return -ENOMEM;
b3b94faa5   David Teigland   [GFS2] The core o...
1006
1007
1008
1009
1010
1011
1012
1013
1014
  
  	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;
d56fa8a1c   Steven Whitehouse   GFS2: Call do_str...
1015
  		error = recursive_scan(ip, NULL, &mp, 0, 0, 1, &sm);
b3b94faa5   David Teigland   [GFS2] The core o...
1016
1017
1018
1019
1020
  		if (error)
  			break;
  	}
  
  	gfs2_quota_unhold(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1021
  out:
564e12b11   Bob Peterson   GFS2: decouple qu...
1022
  	gfs2_qadata_put(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
1023
1024
1025
1026
1027
  	return error;
  }
  
  static int trunc_end(struct gfs2_inode *ip)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1028
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
  	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;
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1041
  	if (!i_size_read(&ip->i_inode)) {
ecc30c791   Steven Whitehouse   [GFS2] Streamline...
1042
  		ip->i_height = 0;
ce276b06e   Steven Whitehouse   [GFS2] Reduce ino...
1043
  		ip->i_goal = ip->i_no_addr;
b3b94faa5   David Teigland   [GFS2] The core o...
1044
1045
  		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
  	}
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
1046
  	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
1047
  	ip->i_diskflags &= ~GFS2_DIF_TRUNC_IN_PROG;
b3b94faa5   David Teigland   [GFS2] The core o...
1048

d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1049
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
1050
  	gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
1051
  	brelse(dibh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1052
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
1053
  	up_write(&ip->i_rw_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
1054
  	gfs2_trans_end(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
1055
1056
1057
1058
1059
  	return error;
  }
  
  /**
   * do_shrink - make a file smaller
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1060
1061
1062
   * @inode: the inode
   * @oldsize: the current inode size
   * @newsize: the size to make the file
b3b94faa5   David Teigland   [GFS2] The core o...
1063
   *
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1064
1065
   * Called with an exclusive lock on @inode. The @size must
   * be equal to or smaller than the current inode size.
b3b94faa5   David Teigland   [GFS2] The core o...
1066
1067
1068
   *
   * Returns: errno
   */
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1069
  static int do_shrink(struct inode *inode, u64 oldsize, u64 newsize)
b3b94faa5   David Teigland   [GFS2] The core o...
1070
  {
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1071
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1072
  	int error;
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1073
  	error = trunc_start(inode, oldsize, newsize);
b3b94faa5   David Teigland   [GFS2] The core o...
1074
1075
  	if (error < 0)
  		return error;
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1076
  	if (gfs2_is_stuffed(ip))
b3b94faa5   David Teigland   [GFS2] The core o...
1077
  		return 0;
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1078
1079
  	error = trunc_dealloc(ip, newsize);
  	if (error == 0)
b3b94faa5   David Teigland   [GFS2] The core o...
1080
1081
1082
1083
  		error = trunc_end(ip);
  
  	return error;
  }
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1084
  void gfs2_trim_blocks(struct inode *inode)
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1085
  {
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  	u64 size = inode->i_size;
  	int ret;
  
  	ret = do_shrink(inode, size, size);
  	WARN_ON(ret != 0);
  }
  
  /**
   * do_grow - Touch and update inode size
   * @inode: The inode
   * @size: The new size
   *
   * This function updates the timestamps on the inode and
   * may also increase the size of the inode. This function
   * must not be called with @size any smaller than the current
   * inode size.
   *
   * Although it is not strictly required to unstuff files here,
   * earlier versions of GFS2 have a bug in the stuffed file reading
   * code which will result in a buffer overrun if the size is larger
   * than the max stuffed file size. In order to prevent this from
25985edce   Lucas De Marchi   Fix common misspe...
1107
   * occurring, such files are unstuffed, but in other cases we can
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1108
1109
1110
1111
1112
1113
1114
1115
1116
   * just update the inode size directly.
   *
   * Returns: 0 on success, or -ve on error
   */
  
  static int do_grow(struct inode *inode, u64 size)
  {
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1117
  	struct buffer_head *dibh;
564e12b11   Bob Peterson   GFS2: decouple qu...
1118
  	struct gfs2_qadata *qa = NULL;
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1119
  	int error;
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1120
1121
  	if (gfs2_is_stuffed(ip) &&
  	    (size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) {
564e12b11   Bob Peterson   GFS2: decouple qu...
1122
1123
  		qa = gfs2_qadata_get(ip);
  		if (qa == NULL)
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1124
1125
1126
1127
1128
  			return -ENOMEM;
  
  		error = gfs2_quota_lock_check(ip);
  		if (error)
  			goto do_grow_alloc_put;
564e12b11   Bob Peterson   GFS2: decouple qu...
1129
  		error = gfs2_inplace_reserve(ip, 1);
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1130
1131
1132
  		if (error)
  			goto do_grow_qunlock;
  	}
bf97b6734   Benjamin Marzinski   GFS2: reserve mor...
1133
  	error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0);
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1134
  	if (error)
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1135
  		goto do_grow_release;
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1136

564e12b11   Bob Peterson   GFS2: decouple qu...
1137
  	if (qa) {
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1138
1139
1140
1141
  		error = gfs2_unstuff_dinode(ip, NULL);
  		if (error)
  			goto do_end_trans;
  	}
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1142
1143
1144
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1145
  		goto do_end_trans;
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1146

ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1147
  	i_size_write(inode, size);
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1148
1149
1150
1151
  	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);
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1152
  do_end_trans:
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1153
  	gfs2_trans_end(sdp);
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1154
  do_grow_release:
564e12b11   Bob Peterson   GFS2: decouple qu...
1155
  	if (qa) {
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1156
1157
1158
1159
  		gfs2_inplace_release(ip);
  do_grow_qunlock:
  		gfs2_quota_unlock(ip);
  do_grow_alloc_put:
564e12b11   Bob Peterson   GFS2: decouple qu...
1160
  		gfs2_qadata_put(ip);
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1161
  	}
a13b8c5f2   Wendy Cheng   [GFS2] Reduce tru...
1162
1163
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1164
  /**
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1165
1166
1167
   * gfs2_setattr_size - make a file a given size
   * @inode: the inode
   * @newsize: the size to make the file
b3b94faa5   David Teigland   [GFS2] The core o...
1168
   *
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1169
1170
1171
   * The file size can grow, shrink, or stay the same size. This
   * is called holding i_mutex and an exclusive glock on the inode
   * in question.
b3b94faa5   David Teigland   [GFS2] The core o...
1172
1173
1174
   *
   * Returns: errno
   */
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1175
  int gfs2_setattr_size(struct inode *inode, u64 newsize)
b3b94faa5   David Teigland   [GFS2] The core o...
1176
  {
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1177
1178
  	int ret;
  	u64 oldsize;
b3b94faa5   David Teigland   [GFS2] The core o...
1179

ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1180
  	BUG_ON(!S_ISREG(inode->i_mode));
b3b94faa5   David Teigland   [GFS2] The core o...
1181

ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1182
1183
1184
  	ret = inode_newsize_ok(inode, newsize);
  	if (ret)
  		return ret;
b3b94faa5   David Teigland   [GFS2] The core o...
1185

562c72aa5   Christoph Hellwig   fs: move inode_di...
1186
  	inode_dio_wait(inode);
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1187
1188
1189
1190
1191
  	oldsize = inode->i_size;
  	if (newsize >= oldsize)
  		return do_grow(inode, newsize);
  
  	return do_shrink(inode, oldsize, newsize);
b3b94faa5   David Teigland   [GFS2] The core o...
1192
1193
1194
1195
1196
  }
  
  int gfs2_truncatei_resume(struct gfs2_inode *ip)
  {
  	int error;
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1197
  	error = trunc_dealloc(ip, i_size_read(&ip->i_inode));
b3b94faa5   David Teigland   [GFS2] The core o...
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
  	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...
1209
1210
1211
1212
   * 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...
1213
   *
461cb419f   Bob Peterson   GFS2: Simplify gf...
1214
   * Returns: 1 if an alloc is required, 0 otherwise
b3b94faa5   David Teigland   [GFS2] The core o...
1215
   */
cd915493f   Steven Whitehouse   [GFS2] Change all...
1216
  int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
461cb419f   Bob Peterson   GFS2: Simplify gf...
1217
  			      unsigned int len)
b3b94faa5   David Teigland   [GFS2] The core o...
1218
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1219
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
1220
1221
1222
  	struct buffer_head bh;
  	unsigned int shift;
  	u64 lblock, lblock_stop, size;
7ed122e42   Steven Whitehouse   GFS2: Streamline ...
1223
  	u64 end_of_file;
b3b94faa5   David Teigland   [GFS2] The core o...
1224

b3b94faa5   David Teigland   [GFS2] The core o...
1225
1226
1227
1228
1229
1230
  	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...
1231
  			return 1;
b3b94faa5   David Teigland   [GFS2] The core o...
1232
1233
  		return 0;
  	}
941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
1234
  	shift = sdp->sd_sb.sb_bsize_shift;
7ed122e42   Steven Whitehouse   GFS2: Streamline ...
1235
  	BUG_ON(gfs2_is_dir(ip));
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1236
  	end_of_file = (i_size_read(&ip->i_inode) + sdp->sd_sb.sb_bsize - 1) >> shift;
7ed122e42   Steven Whitehouse   GFS2: Streamline ...
1237
1238
1239
  	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...
1240
  		return 1;
b3b94faa5   David Teigland   [GFS2] The core o...
1241

941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
1242
1243
1244
1245
1246
1247
  	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...
1248
  			return 1;
941e6d7d0   Steven Whitehouse   [GFS2] Speed up g...
1249
1250
1251
  		size -= bh.b_size;
  		lblock += (bh.b_size >> ip->i_inode.i_blkbits);
  	} while(size > 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1252
1253
1254
  
  	return 0;
  }