Blame view

fs/reiserfs/resize.c 6.13 KB
0222e6571   Jeff Mahoney   reiserfs: strip t...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
   * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4

0222e6571   Jeff Mahoney   reiserfs: strip t...
5
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
18
   * Written by Alexander Zarochentcev.
   *
   * The kernel part of the (on-line) reiserfs resizer.
   */
  
  #include <linux/kernel.h>
  #include <linux/mm.h>
  #include <linux/vmalloc.h>
  #include <linux/string.h>
  #include <linux/errno.h>
  #include <linux/reiserfs_fs.h>
  #include <linux/reiserfs_fs_sb.h>
  #include <linux/buffer_head.h>
bd4c625c0   Linus Torvalds   reiserfs: run scr...
19
  int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
21
22
23
  	int err = 0;
  	struct reiserfs_super_block *sb;
  	struct reiserfs_bitmap_info *bitmap;
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
24
  	struct reiserfs_bitmap_info *info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  	struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
26
  	struct buffer_head *bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
  	struct reiserfs_transaction_handle th;
  	unsigned int bmap_nr_new, bmap_nr;
  	unsigned int block_r_new, block_r;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
30
31
  
  	struct reiserfs_list_bitmap *jb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  	struct reiserfs_list_bitmap jbitmap[JOURNAL_NUM_BITMAPS];
bd4c625c0   Linus Torvalds   reiserfs: run scr...
33

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  	unsigned long int block_count, free_blocks;
  	int i;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
36
  	int copy_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  
  	sb = SB_DISK_SUPER_BLOCK(s);
  
  	if (SB_BLOCK_COUNT(s) >= block_count_new) {
  		printk("can\'t shrink filesystem on-line
  ");
  		return -EINVAL;
  	}
  
  	/* check the device size */
  	bh = sb_bread(s, block_count_new - 1);
  	if (!bh) {
  		printk("reiserfs_resize: can\'t read last block
  ");
  		return -EINVAL;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
52
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
56
  	bforget(bh);
  
  	/* old disk layout detection; those partitions can be mounted, but
  	 * cannot be resized */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
57
58
59
60
61
  	if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size
  	    != REISERFS_DISK_OFFSET_IN_BYTES) {
  		printk
  		    ("reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
  		return -ENOTSUPP;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
64

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  	/* count used bits in last bitmap block */
cb680c1be   Jeff Mahoney   reiserfs: ignore ...
66
67
  	block_r = SB_BLOCK_COUNT(s) -
  			(reiserfs_bmap_count(s) - 1) * s->s_blocksize * 8;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
68

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  	/* count bitmap blocks in new fs */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
70
  	bmap_nr_new = block_count_new / (s->s_blocksize * 8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  	block_r_new = block_count_new - bmap_nr_new * s->s_blocksize * 8;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
72
  	if (block_r_new)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
78
  		bmap_nr_new++;
  	else
  		block_r_new = s->s_blocksize * 8;
  
  	/* save old values */
  	block_count = SB_BLOCK_COUNT(s);
cb680c1be   Jeff Mahoney   reiserfs: ignore ...
79
  	bmap_nr = reiserfs_bmap_count(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
  
  	/* resizing of reiserfs bitmaps (journal and real), if needed */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
82
83
84
85
86
87
  	if (bmap_nr_new > bmap_nr) {
  		/* reallocate journal bitmaps */
  		if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) {
  			printk
  			    ("reiserfs_resize: unable to allocate memory for journal bitmaps
  ");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  			return -ENOMEM;
  		}
  		/* the new journal bitmaps are zero filled, now we copy in the bitmap
  		 ** node pointers from the old journal bitmap structs, and then
  		 ** transfer the new data structures into the journal struct.
  		 **
  		 ** using the copy_size var below allows this code to work for
  		 ** both shrinking and expanding the FS.
  		 */
  		copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr;
  		copy_size =
  		    copy_size * sizeof(struct reiserfs_list_bitmap_node *);
  		for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {
  			struct reiserfs_bitmap_node **node_tmp;
  			jb = SB_JOURNAL(s)->j_list_bitmap + i;
  			memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size);
  
  			/* just in case vfree schedules on us, copy the new
0222e6571   Jeff Mahoney   reiserfs: strip t...
106
  			 ** pointer into the journal struct before freeing the
bd4c625c0   Linus Torvalds   reiserfs: run scr...
107
108
109
110
111
112
113
114
115
116
  			 ** old one
  			 */
  			node_tmp = jb->bitmaps;
  			jb->bitmaps = jbitmap[i].bitmaps;
  			vfree(node_tmp);
  		}
  
  		/* allocate additional bitmap blocks, reallocate array of bitmap
  		 * block pointers */
  		bitmap =
558feb081   Joe Perches   fs: Convert vmall...
117
  		    vzalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
118
119
120
121
122
123
124
  		if (!bitmap) {
  			/* Journal bitmaps are still supersized, but the memory isn't
  			 * leaked, so I guess it's ok */
  			printk("reiserfs_resize: unable to allocate memory.
  ");
  			return -ENOMEM;
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
125
126
127
128
129
130
131
132
  		for (i = 0; i < bmap_nr; i++)
  			bitmap[i] = old_bitmap[i];
  
  		/* This doesn't go through the journal, but it doesn't have to.
  		 * The changes are still atomic: We're synced up when the journal
  		 * transaction begins, and the new bitmaps don't matter if the
  		 * transaction fails. */
  		for (i = bmap_nr; i < bmap_nr_new; i++) {
5065227b4   Jeff Mahoney   [PATCH] reiserfs:...
133
134
135
  			/* don't use read_bitmap_block since it will cache
  			 * the uninitialized bitmap */
  			bh = sb_bread(s, i * s->s_blocksize * 8);
2d3466a34   Dmitriy Monakhov   reiserfs: possibl...
136
137
138
139
  			if (!bh) {
  				vfree(bitmap);
  				return -EIO;
  			}
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
140
  			memset(bh->b_data, 0, sb_blocksize(sb));
0c2fd1bfb   Akinobu Mita   reiserfs: use pro...
141
  			reiserfs_set_le_bit(0, bh->b_data);
6f01046b3   Jeff Mahoney   [PATCH] reiserfs:...
142
  			reiserfs_cache_bitmap_metadata(s, bh, bitmap + i);
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
143
144
145
  
  			set_buffer_uptodate(bh);
  			mark_buffer_dirty(bh);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
146
  			reiserfs_write_unlock(s);
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
147
  			sync_dirty_buffer(bh);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
148
  			reiserfs_write_lock(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
149
  			// update bitmap_info stuff
bd4c625c0   Linus Torvalds   reiserfs: run scr...
150
  			bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
151
  			brelse(bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
152
153
154
155
  		}
  		/* free old bitmap blocks array */
  		SB_AP_BITMAP(s) = bitmap;
  		vfree(old_bitmap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
157

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
162
  	/* begin transaction, if there was an error, it's fine. Yes, we have
  	 * incorrect bitmaps now, but none of it is ever going to touch the
  	 * disk anyway. */
  	err = journal_begin(&th, s, 10);
  	if (err)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
163
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164

0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
165
166
  	/* Extend old last bitmap block - new blocks have been made available */
  	info = SB_AP_BITMAP(s) + bmap_nr - 1;
5065227b4   Jeff Mahoney   [PATCH] reiserfs:...
167
168
169
170
171
172
173
  	bh = reiserfs_read_bitmap_block(s, bmap_nr - 1);
  	if (!bh) {
  		int jerr = journal_end(&th, s, 10);
  		if (jerr)
  			return jerr;
  		return -EIO;
  	}
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
174
175
  
  	reiserfs_prepare_for_journal(s, bh, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	for (i = block_r; i < s->s_blocksize * 8; i++)
0c2fd1bfb   Akinobu Mita   reiserfs: use pro...
177
  		reiserfs_clear_le_bit(i, bh->b_data);
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
178
  	info->free_count += s->s_blocksize * 8 - block_r;
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
179
180
181
  
  	journal_mark_dirty(&th, s, bh);
  	brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182

0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
183
184
  	/* Correct new last bitmap block - It may not be full */
  	info = SB_AP_BITMAP(s) + bmap_nr_new - 1;
5065227b4   Jeff Mahoney   [PATCH] reiserfs:...
185
186
187
188
189
190
191
  	bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1);
  	if (!bh) {
  		int jerr = journal_end(&th, s, 10);
  		if (jerr)
  			return jerr;
  		return -EIO;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192

0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
193
  	reiserfs_prepare_for_journal(s, bh, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  	for (i = block_r_new; i < s->s_blocksize * 8; i++)
0c2fd1bfb   Akinobu Mita   reiserfs: use pro...
195
  		reiserfs_set_le_bit(i, bh->b_data);
0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
196
197
  	journal_mark_dirty(&th, s, bh);
  	brelse(bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
198

0b3dc17bc   Jeff Mahoney   [PATCH] reiserfs:...
199
  	info->free_count -= s->s_blocksize * 8 - block_r_new;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
200
201
  	/* update super */
  	reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  	free_blocks = SB_FREE_BLOCKS(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
203
204
205
  	PUT_SB_FREE_BLOCKS(s,
  			   free_blocks + (block_count_new - block_count -
  					  (bmap_nr_new - bmap_nr)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  	PUT_SB_BLOCK_COUNT(s, block_count_new);
cb680c1be   Jeff Mahoney   reiserfs: ignore ...
207
  	PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
  	s->s_dirt = 1;
  
  	journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
211

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
214
  	SB_JOURNAL(s)->j_must_wait = 1;
  	return journal_end(&th, s, 10);
  }