blob: e132d8a4100887b8b969051b4a7c0b1d89074646 [file] [log] [blame]
David Teiglandb3b94fa2006-01-16 16:50:04 +00001/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
4 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License v.2.
8 */
9
10#include <linux/sched.h>
11#include <linux/slab.h>
12#include <linux/spinlock.h>
13#include <linux/completion.h>
14#include <linux/buffer_head.h>
15#include <asm/semaphore.h>
16
17#include "gfs2.h"
18#include "bmap.h"
19#include "glock.h"
20#include "inode.h"
David Teiglandb3b94fa2006-01-16 16:50:04 +000021#include "meta_io.h"
22#include "page.h"
23#include "quota.h"
24#include "rgrp.h"
25#include "trans.h"
Steven Whitehouse18ec7d52006-02-08 11:50:51 +000026#include "dir.h"
David Teiglandb3b94fa2006-01-16 16:50:04 +000027
28/* This doesn't need to be that large as max 64 bit pointers in a 4k
29 * block is 512, so __u16 is fine for that. It saves stack space to
30 * keep it small.
31 */
32struct metapath {
33 __u16 mp_list[GFS2_MAX_META_HEIGHT];
34};
35
36typedef int (*block_call_t) (struct gfs2_inode *ip, struct buffer_head *dibh,
37 struct buffer_head *bh, uint64_t *top,
38 uint64_t *bottom, unsigned int height,
39 void *data);
40
41struct strip_mine {
42 int sm_first;
43 unsigned int sm_height;
44};
45
46/**
47 * @gfs2_unstuffer_sync - Synchronously unstuff a dinode
48 * @ip:
49 * @dibh:
50 * @block:
51 * @private:
52 *
53 * Cheat and use a metadata buffer instead of a data page.
54 *
55 * Returns: errno
56 */
57
58int gfs2_unstuffer_sync(struct gfs2_inode *ip, struct buffer_head *dibh,
59 uint64_t block, void *private)
60{
61 struct buffer_head *bh;
62 int error;
63
64 bh = gfs2_meta_new(ip->i_gl, block);
65
66 gfs2_buffer_copy_tail(bh, 0, dibh, sizeof(struct gfs2_dinode));
67
68 set_buffer_dirty(bh);
69 error = sync_dirty_buffer(bh);
70
71 brelse(bh);
72
73 return error;
74}
75
76/**
77 * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big
78 * @ip: The GFS2 inode to unstuff
79 * @unstuffer: the routine that handles unstuffing a non-zero length file
80 * @private: private data for the unstuffer
81 *
82 * This routine unstuffs a dinode and returns it to a "normal" state such
83 * that the height can be grown in the traditional way.
84 *
85 * Returns: errno
86 */
87
88int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer,
89 void *private)
90{
91 struct buffer_head *bh, *dibh;
92 uint64_t block = 0;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +000093 int isdir = gfs2_is_dir(ip);
David Teiglandb3b94fa2006-01-16 16:50:04 +000094 int error;
95
96 down_write(&ip->i_rw_mutex);
97
98 error = gfs2_meta_inode_buffer(ip, &dibh);
99 if (error)
100 goto out;
101
102 if (ip->i_di.di_size) {
103 /* Get a free block, fill it with the stuffed data,
104 and write it out to disk */
105
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000106 if (isdir) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000107 block = gfs2_alloc_meta(ip);
108
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000109 error = gfs2_dir_get_buffer(ip, block, 1, &bh);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000110 if (error)
111 goto out_brelse;
112 gfs2_buffer_copy_tail(bh,
113 sizeof(struct gfs2_meta_header),
114 dibh, sizeof(struct gfs2_dinode));
115 brelse(bh);
116 } else {
117 block = gfs2_alloc_data(ip);
118
119 error = unstuffer(ip, dibh, block, private);
120 if (error)
121 goto out_brelse;
122 }
123 }
124
125 /* Set up the pointer to the new block */
126
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000127 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000128
129 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
130
131 if (ip->i_di.di_size) {
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500132 *(uint64_t *)(dibh->b_data + sizeof(struct gfs2_dinode)) =
133 cpu_to_be64(block);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000134 ip->i_di.di_blocks++;
135 }
136
137 ip->i_di.di_height = 1;
138
139 gfs2_dinode_out(&ip->i_di, dibh->b_data);
140
141 out_brelse:
142 brelse(dibh);
143
144 out:
145 up_write(&ip->i_rw_mutex);
146
147 return error;
148}
149
150/**
151 * calc_tree_height - Calculate the height of a metadata tree
152 * @ip: The GFS2 inode
153 * @size: The proposed size of the file
154 *
155 * Work out how tall a metadata tree needs to be in order to accommodate a
156 * file of a particular size. If size is less than the current size of
157 * the inode, then the current size of the inode is used instead of the
158 * supplied one.
159 *
160 * Returns: the height the tree should be
161 */
162
163static unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size)
164{
165 struct gfs2_sbd *sdp = ip->i_sbd;
166 uint64_t *arr;
167 unsigned int max, height;
168
169 if (ip->i_di.di_size > size)
170 size = ip->i_di.di_size;
171
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000172 if (gfs2_is_dir(ip)) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000173 arr = sdp->sd_jheightsize;
174 max = sdp->sd_max_jheight;
175 } else {
176 arr = sdp->sd_heightsize;
177 max = sdp->sd_max_height;
178 }
179
180 for (height = 0; height < max; height++)
181 if (arr[height] >= size)
182 break;
183
184 return height;
185}
186
187/**
188 * build_height - Build a metadata tree of the requested height
189 * @ip: The GFS2 inode
190 * @height: The height to build to
191 *
192 * This routine makes sure that the metadata tree is tall enough to hold
193 * "size" bytes of data.
194 *
195 * Returns: errno
196 */
197
198static int build_height(struct gfs2_inode *ip, int height)
199{
200 struct gfs2_sbd *sdp = ip->i_sbd;
201 struct buffer_head *bh, *dibh;
202 uint64_t block = 0, *bp;
203 unsigned int x;
204 int new_block;
205 int error;
206
207 while (ip->i_di.di_height < height) {
208 error = gfs2_meta_inode_buffer(ip, &dibh);
209 if (error)
210 return error;
211
212 new_block = 0;
213 bp = (uint64_t *)(dibh->b_data + sizeof(struct gfs2_dinode));
214 for (x = 0; x < sdp->sd_diptrs; x++, bp++)
215 if (*bp) {
216 new_block = 1;
217 break;
218 }
219
220 if (new_block) {
221 /* Get a new block, fill it with the old direct
222 pointers, and write it out */
223
224 block = gfs2_alloc_meta(ip);
225
226 bh = gfs2_meta_new(ip->i_gl, block);
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000227 gfs2_trans_add_bh(ip->i_gl, bh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000228 gfs2_metatype_set(bh,
229 GFS2_METATYPE_IN,
230 GFS2_FORMAT_IN);
231 gfs2_buffer_copy_tail(bh,
232 sizeof(struct gfs2_meta_header),
233 dibh, sizeof(struct gfs2_dinode));
234
235 brelse(bh);
236 }
237
238 /* Set up the new direct pointer and write it out to disk */
239
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000240 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000241
242 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
243
244 if (new_block) {
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500245 *(uint64_t *)(dibh->b_data +
246 sizeof(struct gfs2_dinode)) =
247 cpu_to_be64(block);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000248 ip->i_di.di_blocks++;
249 }
250
251 ip->i_di.di_height++;
252
253 gfs2_dinode_out(&ip->i_di, dibh->b_data);
254 brelse(dibh);
255 }
256
257 return 0;
258}
259
260/**
261 * find_metapath - Find path through the metadata tree
262 * @ip: The inode pointer
263 * @mp: The metapath to return the result in
264 * @block: The disk block to look up
265 *
266 * This routine returns a struct metapath structure that defines a path
267 * through the metadata of inode "ip" to get to block "block".
268 *
269 * Example:
270 * Given: "ip" is a height 3 file, "offset" is 101342453, and this is a
271 * filesystem with a blocksize of 4096.
272 *
273 * find_metapath() would return a struct metapath structure set to:
274 * mp_offset = 101342453, mp_height = 3, mp_list[0] = 0, mp_list[1] = 48,
275 * and mp_list[2] = 165.
276 *
277 * That means that in order to get to the block containing the byte at
278 * offset 101342453, we would load the indirect block pointed to by pointer
279 * 0 in the dinode. We would then load the indirect block pointed to by
280 * pointer 48 in that indirect block. We would then load the data block
281 * pointed to by pointer 165 in that indirect block.
282 *
283 * ----------------------------------------
284 * | Dinode | |
285 * | | 4|
286 * | |0 1 2 3 4 5 9|
287 * | | 6|
288 * ----------------------------------------
289 * |
290 * |
291 * V
292 * ----------------------------------------
293 * | Indirect Block |
294 * | 5|
295 * | 4 4 4 4 4 5 5 1|
296 * |0 5 6 7 8 9 0 1 2|
297 * ----------------------------------------
298 * |
299 * |
300 * V
301 * ----------------------------------------
302 * | Indirect Block |
303 * | 1 1 1 1 1 5|
304 * | 6 6 6 6 6 1|
305 * |0 3 4 5 6 7 2|
306 * ----------------------------------------
307 * |
308 * |
309 * V
310 * ----------------------------------------
311 * | Data block containing offset |
312 * | 101342453 |
313 * | |
314 * | |
315 * ----------------------------------------
316 *
317 */
318
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500319static void find_metapath(struct gfs2_inode *ip, uint64_t block,
320 struct metapath *mp)
David Teiglandb3b94fa2006-01-16 16:50:04 +0000321{
322 struct gfs2_sbd *sdp = ip->i_sbd;
323 uint64_t b = block;
324 unsigned int i;
325
326 for (i = ip->i_di.di_height; i--;)
327 mp->mp_list[i] = (__u16)do_div(b, sdp->sd_inptrs);
328
329}
330
331/**
332 * metapointer - Return pointer to start of metadata in a buffer
333 * @bh: The buffer
334 * @height: The metadata height (0 = dinode)
335 * @mp: The metapath
336 *
337 * Return a pointer to the block number of the next height of the metadata
338 * tree given a buffer containing the pointer to the current height of the
339 * metadata tree.
340 */
341
342static inline uint64_t *metapointer(struct buffer_head *bh,
343 unsigned int height, struct metapath *mp)
344{
345 unsigned int head_size = (height > 0) ?
346 sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
347
348 return ((uint64_t *)(bh->b_data + head_size)) + mp->mp_list[height];
349}
350
351/**
352 * lookup_block - Get the next metadata block in metadata tree
353 * @ip: The GFS2 inode
354 * @bh: Buffer containing the pointers to metadata blocks
355 * @height: The height of the tree (0 = dinode)
356 * @mp: The metapath
357 * @create: Non-zero if we may create a new meatdata block
358 * @new: Used to indicate if we did create a new metadata block
359 * @block: the returned disk block number
360 *
361 * Given a metatree, complete to a particular height, checks to see if the next
362 * height of the tree exists. If not the next height of the tree is created.
363 * The block number of the next height of the metadata tree is returned.
364 *
365 */
366
367static void lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
368 unsigned int height, struct metapath *mp, int create,
369 int *new, uint64_t *block)
370{
371 uint64_t *ptr = metapointer(bh, height, mp);
372
373 if (*ptr) {
374 *block = be64_to_cpu(*ptr);
375 return;
376 }
377
378 *block = 0;
379
380 if (!create)
381 return;
382
383 if (height == ip->i_di.di_height - 1 &&
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000384 !gfs2_is_dir(ip))
David Teiglandb3b94fa2006-01-16 16:50:04 +0000385 *block = gfs2_alloc_data(ip);
386 else
387 *block = gfs2_alloc_meta(ip);
388
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000389 gfs2_trans_add_bh(ip->i_gl, bh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000390
391 *ptr = cpu_to_be64(*block);
392 ip->i_di.di_blocks++;
393
394 *new = 1;
395}
396
397/**
398 * gfs2_block_map - Map a block from an inode to a disk block
399 * @ip: The GFS2 inode
400 * @lblock: The logical block number
401 * @new: Value/Result argument (1 = may create/did create new blocks)
402 * @dblock: the disk block number of the start of an extent
403 * @extlen: the size of the extent
404 *
405 * Find the block number on the current device which corresponds to an
406 * inode's block. If the block had to be created, "new" will be set.
407 *
408 * Returns: errno
409 */
410
411int gfs2_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
412 uint64_t *dblock, uint32_t *extlen)
413{
414 struct gfs2_sbd *sdp = ip->i_sbd;
415 struct buffer_head *bh;
416 struct metapath mp;
417 int create = *new;
418 unsigned int bsize;
419 unsigned int height;
420 unsigned int end_of_metadata;
421 unsigned int x;
422 int error = 0;
423
424 *new = 0;
425 *dblock = 0;
426 if (extlen)
427 *extlen = 0;
428
429 if (create)
430 down_write(&ip->i_rw_mutex);
431 else
432 down_read(&ip->i_rw_mutex);
433
434 if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
435 goto out;
436
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000437 bsize = (gfs2_is_dir(ip)) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000438
439 height = calc_tree_height(ip, (lblock + 1) * bsize);
440 if (ip->i_di.di_height < height) {
441 if (!create)
442 goto out;
443
444 error = build_height(ip, height);
445 if (error)
446 goto out;
447 }
448
449 find_metapath(ip, lblock, &mp);
450 end_of_metadata = ip->i_di.di_height - 1;
451
452 error = gfs2_meta_inode_buffer(ip, &bh);
453 if (error)
454 goto out;
455
456 for (x = 0; x < end_of_metadata; x++) {
457 lookup_block(ip, bh, x, &mp, create, new, dblock);
458 brelse(bh);
459 if (!*dblock)
460 goto out;
461
462 error = gfs2_meta_indirect_buffer(ip, x+1, *dblock, *new, &bh);
463 if (error)
464 goto out;
465 }
466
467 lookup_block(ip, bh, end_of_metadata, &mp, create, new, dblock);
468
469 if (extlen && *dblock) {
470 *extlen = 1;
471
472 if (!*new) {
473 uint64_t tmp_dblock;
474 int tmp_new;
475 unsigned int nptrs;
476
477 nptrs = (end_of_metadata) ? sdp->sd_inptrs :
478 sdp->sd_diptrs;
479
480 while (++mp.mp_list[end_of_metadata] < nptrs) {
481 lookup_block(ip, bh, end_of_metadata, &mp,
482 0, &tmp_new, &tmp_dblock);
483
484 if (*dblock + *extlen != tmp_dblock)
485 break;
486
487 (*extlen)++;
488 }
489 }
490 }
491
492 brelse(bh);
493
494 if (*new) {
495 error = gfs2_meta_inode_buffer(ip, &bh);
496 if (!error) {
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000497 gfs2_trans_add_bh(ip->i_gl, bh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000498 gfs2_dinode_out(&ip->i_di, bh->b_data);
499 brelse(bh);
500 }
501 }
502
503 out:
504 if (create)
505 up_write(&ip->i_rw_mutex);
506 else
507 up_read(&ip->i_rw_mutex);
508
509 return error;
510}
511
512/**
513 * recursive_scan - recursively scan through the end of a file
514 * @ip: the inode
515 * @dibh: the dinode buffer
516 * @mp: the path through the metadata to the point to start
517 * @height: the height the recursion is at
518 * @block: the indirect block to look at
519 * @first: 1 if this is the first block
520 * @bc: the call to make for each piece of metadata
521 * @data: data opaque to this function to pass to @bc
522 *
523 * When this is first called @height and @block should be zero and
524 * @first should be 1.
525 *
526 * Returns: errno
527 */
528
529static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
530 struct metapath *mp, unsigned int height,
531 uint64_t block, int first, block_call_t bc,
532 void *data)
533{
534 struct gfs2_sbd *sdp = ip->i_sbd;
535 struct buffer_head *bh = NULL;
536 uint64_t *top, *bottom;
537 uint64_t bn;
538 int error;
539 int mh_size = sizeof(struct gfs2_meta_header);
540
541 if (!height) {
542 error = gfs2_meta_inode_buffer(ip, &bh);
543 if (error)
544 return error;
545 dibh = bh;
546
547 top = (uint64_t *)(bh->b_data + sizeof(struct gfs2_dinode)) +
548 mp->mp_list[0];
549 bottom = (uint64_t *)(bh->b_data + sizeof(struct gfs2_dinode)) +
550 sdp->sd_diptrs;
551 } else {
552 error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
553 if (error)
554 return error;
555
556 top = (uint64_t *)(bh->b_data + mh_size) +
557 ((first) ? mp->mp_list[height] : 0);
558
559 bottom = (uint64_t *)(bh->b_data + mh_size) + sdp->sd_inptrs;
560 }
561
562 error = bc(ip, dibh, bh, top, bottom, height, data);
563 if (error)
564 goto out;
565
566 if (height < ip->i_di.di_height - 1)
567 for (; top < bottom; top++, first = 0) {
568 if (!*top)
569 continue;
570
571 bn = be64_to_cpu(*top);
572
573 error = recursive_scan(ip, dibh, mp, height + 1, bn,
574 first, bc, data);
575 if (error)
576 break;
577 }
578
579 out:
580 brelse(bh);
581
582 return error;
583}
584
585/**
586 * do_strip - Look for a layer a particular layer of the file and strip it off
587 * @ip: the inode
588 * @dibh: the dinode buffer
589 * @bh: A buffer of pointers
590 * @top: The first pointer in the buffer
591 * @bottom: One more than the last pointer
592 * @height: the height this buffer is at
593 * @data: a pointer to a struct strip_mine
594 *
595 * Returns: errno
596 */
597
598static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
599 struct buffer_head *bh, uint64_t *top, uint64_t *bottom,
600 unsigned int height, void *data)
601{
602 struct strip_mine *sm = (struct strip_mine *)data;
603 struct gfs2_sbd *sdp = ip->i_sbd;
604 struct gfs2_rgrp_list rlist;
605 uint64_t bn, bstart;
606 uint32_t blen;
607 uint64_t *p;
608 unsigned int rg_blocks = 0;
609 int metadata;
610 unsigned int revokes = 0;
611 int x;
612 int error;
613
614 if (!*top)
615 sm->sm_first = 0;
616
617 if (height != sm->sm_height)
618 return 0;
619
620 if (sm->sm_first) {
621 top++;
622 sm->sm_first = 0;
623 }
624
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000625 metadata = (height != ip->i_di.di_height - 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000626 if (metadata)
627 revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
628
629 error = gfs2_rindex_hold(sdp, &ip->i_alloc.al_ri_gh);
630 if (error)
631 return error;
632
633 memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
634 bstart = 0;
635 blen = 0;
636
637 for (p = top; p < bottom; p++) {
638 if (!*p)
639 continue;
640
641 bn = be64_to_cpu(*p);
642
643 if (bstart + blen == bn)
644 blen++;
645 else {
646 if (bstart)
647 gfs2_rlist_add(sdp, &rlist, bstart);
648
649 bstart = bn;
650 blen = 1;
651 }
652 }
653
654 if (bstart)
655 gfs2_rlist_add(sdp, &rlist, bstart);
656 else
657 goto out; /* Nothing to do */
658
659 gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
660
661 for (x = 0; x < rlist.rl_rgrps; x++) {
662 struct gfs2_rgrpd *rgd;
663 rgd = get_gl2rgd(rlist.rl_ghs[x].gh_gl);
664 rg_blocks += rgd->rd_ri.ri_length;
665 }
666
667 error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
668 if (error)
669 goto out_rlist;
670
671 error = gfs2_trans_begin(sdp, rg_blocks + RES_DINODE +
672 RES_INDIRECT + RES_STATFS + RES_QUOTA,
673 revokes);
674 if (error)
675 goto out_rg_gunlock;
676
677 down_write(&ip->i_rw_mutex);
678
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000679 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
680 gfs2_trans_add_bh(ip->i_gl, bh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000681
682 bstart = 0;
683 blen = 0;
684
685 for (p = top; p < bottom; p++) {
686 if (!*p)
687 continue;
688
689 bn = be64_to_cpu(*p);
690
691 if (bstart + blen == bn)
692 blen++;
693 else {
694 if (bstart) {
695 if (metadata)
696 gfs2_free_meta(ip, bstart, blen);
697 else
698 gfs2_free_data(ip, bstart, blen);
699 }
700
701 bstart = bn;
702 blen = 1;
703 }
704
705 *p = 0;
706 if (!ip->i_di.di_blocks)
707 gfs2_consist_inode(ip);
708 ip->i_di.di_blocks--;
709 }
710 if (bstart) {
711 if (metadata)
712 gfs2_free_meta(ip, bstart, blen);
713 else
714 gfs2_free_data(ip, bstart, blen);
715 }
716
717 ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
718
719 gfs2_dinode_out(&ip->i_di, dibh->b_data);
720
721 up_write(&ip->i_rw_mutex);
722
723 gfs2_trans_end(sdp);
724
725 out_rg_gunlock:
726 gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
727
728 out_rlist:
729 gfs2_rlist_free(&rlist);
730
731 out:
732 gfs2_glock_dq_uninit(&ip->i_alloc.al_ri_gh);
733
734 return error;
735}
736
737/**
738 * do_grow - Make a file look bigger than it is
739 * @ip: the inode
740 * @size: the size to set the file to
741 *
742 * Called with an exclusive lock on @ip.
743 *
744 * Returns: errno
745 */
746
747static int do_grow(struct gfs2_inode *ip, uint64_t size)
748{
749 struct gfs2_sbd *sdp = ip->i_sbd;
750 struct gfs2_alloc *al;
751 struct buffer_head *dibh;
752 unsigned int h;
753 int error;
754
755 al = gfs2_alloc_get(ip);
756
757 error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
758 if (error)
759 goto out;
760
761 error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
762 if (error)
763 goto out_gunlock_q;
764
765 al->al_requested = sdp->sd_max_height + RES_DATA;
766
767 error = gfs2_inplace_reserve(ip);
768 if (error)
769 goto out_gunlock_q;
770
771 error = gfs2_trans_begin(sdp,
772 sdp->sd_max_height + al->al_rgd->rd_ri.ri_length +
773 RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
774 if (error)
775 goto out_ipres;
776
777 if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
778 if (gfs2_is_stuffed(ip)) {
779 error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page,
780 NULL);
781 if (error)
782 goto out_end_trans;
783 }
784
785 h = calc_tree_height(ip, size);
786 if (ip->i_di.di_height < h) {
787 down_write(&ip->i_rw_mutex);
788 error = build_height(ip, h);
789 up_write(&ip->i_rw_mutex);
790 if (error)
791 goto out_end_trans;
792 }
793 }
794
795 ip->i_di.di_size = size;
796 ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
797
798 error = gfs2_meta_inode_buffer(ip, &dibh);
799 if (error)
800 goto out_end_trans;
801
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000802 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000803 gfs2_dinode_out(&ip->i_di, dibh->b_data);
804 brelse(dibh);
805
806 out_end_trans:
807 gfs2_trans_end(sdp);
808
809 out_ipres:
810 gfs2_inplace_release(ip);
811
812 out_gunlock_q:
813 gfs2_quota_unlock(ip);
814
815 out:
816 gfs2_alloc_put(ip);
817
818 return error;
819}
820
Steven Whitehouseaa6a85a2006-01-24 10:37:06 +0000821static int trunc_start(struct gfs2_inode *ip, uint64_t size)
David Teiglandb3b94fa2006-01-16 16:50:04 +0000822{
823 struct gfs2_sbd *sdp = ip->i_sbd;
824 struct buffer_head *dibh;
825 int journaled = gfs2_is_jdata(ip);
826 int error;
827
828 error = gfs2_trans_begin(sdp,
829 RES_DINODE + ((journaled) ? RES_JDATA : 0), 0);
830 if (error)
831 return error;
832
833 error = gfs2_meta_inode_buffer(ip, &dibh);
834 if (error)
835 goto out;
836
837 if (gfs2_is_stuffed(ip)) {
838 ip->i_di.di_size = size;
839 ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000840 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000841 gfs2_dinode_out(&ip->i_di, dibh->b_data);
842 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
843 error = 1;
844
845 } else {
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000846 if (size & (uint64_t)(sdp->sd_sb.sb_bsize - 1))
Steven Whitehouse257f9b42006-01-31 10:00:25 +0000847 error = gfs2_block_truncate_page(ip->i_vnode->i_mapping);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000848
849 if (!error) {
850 ip->i_di.di_size = size;
851 ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
852 ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000853 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000854 gfs2_dinode_out(&ip->i_di, dibh->b_data);
855 }
856 }
857
858 brelse(dibh);
859
860 out:
861 gfs2_trans_end(sdp);
862
863 return error;
864}
865
866static int trunc_dealloc(struct gfs2_inode *ip, uint64_t size)
867{
868 unsigned int height = ip->i_di.di_height;
869 uint64_t lblock;
870 struct metapath mp;
871 int error;
872
873 if (!size)
874 lblock = 0;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000875 else
David Teiglandb3b94fa2006-01-16 16:50:04 +0000876 lblock = (size - 1) >> ip->i_sbd->sd_sb.sb_bsize_shift;
877
878 find_metapath(ip, lblock, &mp);
879 gfs2_alloc_get(ip);
880
881 error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
882 if (error)
883 goto out;
884
885 while (height--) {
886 struct strip_mine sm;
887 sm.sm_first = !!size;
888 sm.sm_height = height;
889
890 error = recursive_scan(ip, NULL, &mp, 0, 0, 1, do_strip, &sm);
891 if (error)
892 break;
893 }
894
895 gfs2_quota_unhold(ip);
896
897 out:
898 gfs2_alloc_put(ip);
899 return error;
900}
901
902static int trunc_end(struct gfs2_inode *ip)
903{
904 struct gfs2_sbd *sdp = ip->i_sbd;
905 struct buffer_head *dibh;
906 int error;
907
908 error = gfs2_trans_begin(sdp, RES_DINODE, 0);
909 if (error)
910 return error;
911
912 down_write(&ip->i_rw_mutex);
913
914 error = gfs2_meta_inode_buffer(ip, &dibh);
915 if (error)
916 goto out;
917
918 if (!ip->i_di.di_size) {
919 ip->i_di.di_height = 0;
920 ip->i_di.di_goal_meta =
921 ip->i_di.di_goal_data =
922 ip->i_num.no_addr;
923 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
924 }
925 ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
926 ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
927
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +0000928 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000929 gfs2_dinode_out(&ip->i_di, dibh->b_data);
930 brelse(dibh);
931
932 out:
933 up_write(&ip->i_rw_mutex);
934
935 gfs2_trans_end(sdp);
936
937 return error;
938}
939
940/**
941 * do_shrink - make a file smaller
942 * @ip: the inode
943 * @size: the size to make the file
944 * @truncator: function to truncate the last partial block
945 *
946 * Called with an exclusive lock on @ip.
947 *
948 * Returns: errno
949 */
950
Steven Whitehouseaa6a85a2006-01-24 10:37:06 +0000951static int do_shrink(struct gfs2_inode *ip, uint64_t size)
David Teiglandb3b94fa2006-01-16 16:50:04 +0000952{
953 int error;
954
Steven Whitehouseaa6a85a2006-01-24 10:37:06 +0000955 error = trunc_start(ip, size);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000956 if (error < 0)
957 return error;
958 if (error > 0)
959 return 0;
960
961 error = trunc_dealloc(ip, size);
962 if (!error)
963 error = trunc_end(ip);
964
965 return error;
966}
967
968/**
Steven Whitehouse666a2c52006-01-18 10:29:04 +0000969 * gfs2_truncatei - make a file a given size
David Teiglandb3b94fa2006-01-16 16:50:04 +0000970 * @ip: the inode
971 * @size: the size to make the file
972 * @truncator: function to truncate the last partial block
973 *
974 * The file size can grow, shrink, or stay the same size.
975 *
976 * Returns: errno
977 */
978
Steven Whitehouseaa6a85a2006-01-24 10:37:06 +0000979int gfs2_truncatei(struct gfs2_inode *ip, uint64_t size)
David Teiglandb3b94fa2006-01-16 16:50:04 +0000980{
981 int error;
982
983 if (gfs2_assert_warn(ip->i_sbd, S_ISREG(ip->i_di.di_mode)))
984 return -EINVAL;
985
986 if (size > ip->i_di.di_size)
987 error = do_grow(ip, size);
988 else
Steven Whitehouseaa6a85a2006-01-24 10:37:06 +0000989 error = do_shrink(ip, size);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000990
991 return error;
992}
993
994int gfs2_truncatei_resume(struct gfs2_inode *ip)
995{
996 int error;
997 error = trunc_dealloc(ip, ip->i_di.di_size);
998 if (!error)
999 error = trunc_end(ip);
1000 return error;
1001}
1002
1003int gfs2_file_dealloc(struct gfs2_inode *ip)
1004{
1005 return trunc_dealloc(ip, 0);
1006}
1007
1008/**
1009 * gfs2_write_calc_reserv - calculate number of blocks needed to write to a file
1010 * @ip: the file
1011 * @len: the number of bytes to be written to the file
1012 * @data_blocks: returns the number of data blocks required
1013 * @ind_blocks: returns the number of indirect blocks required
1014 *
1015 */
1016
1017void gfs2_write_calc_reserv(struct gfs2_inode *ip, unsigned int len,
1018 unsigned int *data_blocks, unsigned int *ind_blocks)
1019{
1020 struct gfs2_sbd *sdp = ip->i_sbd;
1021 unsigned int tmp;
1022
Steven Whitehouse18ec7d52006-02-08 11:50:51 +00001023 if (gfs2_is_dir(ip)) {
David Teiglandb3b94fa2006-01-16 16:50:04 +00001024 *data_blocks = DIV_RU(len, sdp->sd_jbsize) + 2;
1025 *ind_blocks = 3 * (sdp->sd_max_jheight - 1);
1026 } else {
1027 *data_blocks = (len >> sdp->sd_sb.sb_bsize_shift) + 3;
1028 *ind_blocks = 3 * (sdp->sd_max_height - 1);
1029 }
1030
1031 for (tmp = *data_blocks; tmp > sdp->sd_diptrs;) {
1032 tmp = DIV_RU(tmp, sdp->sd_inptrs);
1033 *ind_blocks += tmp;
1034 }
1035}
1036
1037/**
1038 * gfs2_write_alloc_required - figure out if a write will require an allocation
1039 * @ip: the file being written to
1040 * @offset: the offset to write to
1041 * @len: the number of bytes being written
1042 * @alloc_required: set to 1 if an alloc is required, 0 otherwise
1043 *
1044 * Returns: errno
1045 */
1046
1047int gfs2_write_alloc_required(struct gfs2_inode *ip, uint64_t offset,
1048 unsigned int len, int *alloc_required)
1049{
1050 struct gfs2_sbd *sdp = ip->i_sbd;
1051 uint64_t lblock, lblock_stop, dblock;
1052 uint32_t extlen;
1053 int new = 0;
1054 int error = 0;
1055
1056 *alloc_required = 0;
1057
1058 if (!len)
1059 return 0;
1060
1061 if (gfs2_is_stuffed(ip)) {
1062 if (offset + len >
1063 sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode))
1064 *alloc_required = 1;
1065 return 0;
1066 }
1067
Steven Whitehouse18ec7d52006-02-08 11:50:51 +00001068 if (gfs2_is_dir(ip)) {
David Teiglandb3b94fa2006-01-16 16:50:04 +00001069 unsigned int bsize = sdp->sd_jbsize;
1070 lblock = offset;
1071 do_div(lblock, bsize);
1072 lblock_stop = offset + len + bsize - 1;
1073 do_div(lblock_stop, bsize);
1074 } else {
1075 unsigned int shift = sdp->sd_sb.sb_bsize_shift;
1076 lblock = offset >> shift;
1077 lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
1078 }
1079
1080 for (; lblock < lblock_stop; lblock += extlen) {
1081 error = gfs2_block_map(ip, lblock, &new, &dblock, &extlen);
1082 if (error)
1083 return error;
1084
1085 if (!dblock) {
1086 *alloc_required = 1;
1087 return 0;
1088 }
1089 }
1090
1091 return 0;
1092}
1093