xref: /OK3568_Linux_fs/kernel/fs/reiserfs/resize.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
3*4882a593Smuzhiyun  */
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun /*
6*4882a593Smuzhiyun  * Written by Alexander Zarochentcev.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * The kernel part of the (on-line) reiserfs resizer.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/mm.h>
13*4882a593Smuzhiyun #include <linux/vmalloc.h>
14*4882a593Smuzhiyun #include <linux/string.h>
15*4882a593Smuzhiyun #include <linux/errno.h>
16*4882a593Smuzhiyun #include "reiserfs.h"
17*4882a593Smuzhiyun #include <linux/buffer_head.h>
18*4882a593Smuzhiyun 
reiserfs_resize(struct super_block * s,unsigned long block_count_new)19*4882a593Smuzhiyun int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	int err = 0;
22*4882a593Smuzhiyun 	struct reiserfs_super_block *sb;
23*4882a593Smuzhiyun 	struct reiserfs_bitmap_info *bitmap;
24*4882a593Smuzhiyun 	struct reiserfs_bitmap_info *info;
25*4882a593Smuzhiyun 	struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s);
26*4882a593Smuzhiyun 	struct buffer_head *bh;
27*4882a593Smuzhiyun 	struct reiserfs_transaction_handle th;
28*4882a593Smuzhiyun 	unsigned int bmap_nr_new, bmap_nr;
29*4882a593Smuzhiyun 	unsigned int block_r_new, block_r;
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	struct reiserfs_list_bitmap *jb;
32*4882a593Smuzhiyun 	struct reiserfs_list_bitmap jbitmap[JOURNAL_NUM_BITMAPS];
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	unsigned long int block_count, free_blocks;
35*4882a593Smuzhiyun 	int i;
36*4882a593Smuzhiyun 	int copy_size;
37*4882a593Smuzhiyun 	int depth;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	sb = SB_DISK_SUPER_BLOCK(s);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	if (SB_BLOCK_COUNT(s) >= block_count_new) {
42*4882a593Smuzhiyun 		printk("can\'t shrink filesystem on-line\n");
43*4882a593Smuzhiyun 		return -EINVAL;
44*4882a593Smuzhiyun 	}
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	/* check the device size */
47*4882a593Smuzhiyun 	depth = reiserfs_write_unlock_nested(s);
48*4882a593Smuzhiyun 	bh = sb_bread(s, block_count_new - 1);
49*4882a593Smuzhiyun 	reiserfs_write_lock_nested(s, depth);
50*4882a593Smuzhiyun 	if (!bh) {
51*4882a593Smuzhiyun 		printk("reiserfs_resize: can\'t read last block\n");
52*4882a593Smuzhiyun 		return -EINVAL;
53*4882a593Smuzhiyun 	}
54*4882a593Smuzhiyun 	bforget(bh);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	/*
57*4882a593Smuzhiyun 	 * old disk layout detection; those partitions can be mounted, but
58*4882a593Smuzhiyun 	 * cannot be resized
59*4882a593Smuzhiyun 	 */
60*4882a593Smuzhiyun 	if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size
61*4882a593Smuzhiyun 	    != REISERFS_DISK_OFFSET_IN_BYTES) {
62*4882a593Smuzhiyun 		printk
63*4882a593Smuzhiyun 		    ("reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12)\n");
64*4882a593Smuzhiyun 		return -ENOTSUPP;
65*4882a593Smuzhiyun 	}
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	/* count used bits in last bitmap block */
68*4882a593Smuzhiyun 	block_r = SB_BLOCK_COUNT(s) -
69*4882a593Smuzhiyun 			(reiserfs_bmap_count(s) - 1) * s->s_blocksize * 8;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	/* count bitmap blocks in new fs */
72*4882a593Smuzhiyun 	bmap_nr_new = block_count_new / (s->s_blocksize * 8);
73*4882a593Smuzhiyun 	block_r_new = block_count_new - bmap_nr_new * s->s_blocksize * 8;
74*4882a593Smuzhiyun 	if (block_r_new)
75*4882a593Smuzhiyun 		bmap_nr_new++;
76*4882a593Smuzhiyun 	else
77*4882a593Smuzhiyun 		block_r_new = s->s_blocksize * 8;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	/* save old values */
80*4882a593Smuzhiyun 	block_count = SB_BLOCK_COUNT(s);
81*4882a593Smuzhiyun 	bmap_nr = reiserfs_bmap_count(s);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	/* resizing of reiserfs bitmaps (journal and real), if needed */
84*4882a593Smuzhiyun 	if (bmap_nr_new > bmap_nr) {
85*4882a593Smuzhiyun 		/* reallocate journal bitmaps */
86*4882a593Smuzhiyun 		if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) {
87*4882a593Smuzhiyun 			printk
88*4882a593Smuzhiyun 			    ("reiserfs_resize: unable to allocate memory for journal bitmaps\n");
89*4882a593Smuzhiyun 			return -ENOMEM;
90*4882a593Smuzhiyun 		}
91*4882a593Smuzhiyun 		/*
92*4882a593Smuzhiyun 		 * the new journal bitmaps are zero filled, now we copy i
93*4882a593Smuzhiyun 		 * the bitmap node pointers from the old journal bitmap
94*4882a593Smuzhiyun 		 * structs, and then transfer the new data structures
95*4882a593Smuzhiyun 		 * into the journal struct.
96*4882a593Smuzhiyun 		 *
97*4882a593Smuzhiyun 		 * using the copy_size var below allows this code to work for
98*4882a593Smuzhiyun 		 * both shrinking and expanding the FS.
99*4882a593Smuzhiyun 		 */
100*4882a593Smuzhiyun 		copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr;
101*4882a593Smuzhiyun 		copy_size =
102*4882a593Smuzhiyun 		    copy_size * sizeof(struct reiserfs_list_bitmap_node *);
103*4882a593Smuzhiyun 		for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {
104*4882a593Smuzhiyun 			struct reiserfs_bitmap_node **node_tmp;
105*4882a593Smuzhiyun 			jb = SB_JOURNAL(s)->j_list_bitmap + i;
106*4882a593Smuzhiyun 			memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 			/*
109*4882a593Smuzhiyun 			 * just in case vfree schedules on us, copy the new
110*4882a593Smuzhiyun 			 * pointer into the journal struct before freeing the
111*4882a593Smuzhiyun 			 * old one
112*4882a593Smuzhiyun 			 */
113*4882a593Smuzhiyun 			node_tmp = jb->bitmaps;
114*4882a593Smuzhiyun 			jb->bitmaps = jbitmap[i].bitmaps;
115*4882a593Smuzhiyun 			vfree(node_tmp);
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 		/*
119*4882a593Smuzhiyun 		 * allocate additional bitmap blocks, reallocate
120*4882a593Smuzhiyun 		 * array of bitmap block pointers
121*4882a593Smuzhiyun 		 */
122*4882a593Smuzhiyun 		bitmap =
123*4882a593Smuzhiyun 		    vzalloc(array_size(bmap_nr_new,
124*4882a593Smuzhiyun 				       sizeof(struct reiserfs_bitmap_info)));
125*4882a593Smuzhiyun 		if (!bitmap) {
126*4882a593Smuzhiyun 			/*
127*4882a593Smuzhiyun 			 * Journal bitmaps are still supersized, but the
128*4882a593Smuzhiyun 			 * memory isn't leaked, so I guess it's ok
129*4882a593Smuzhiyun 			 */
130*4882a593Smuzhiyun 			printk("reiserfs_resize: unable to allocate memory.\n");
131*4882a593Smuzhiyun 			return -ENOMEM;
132*4882a593Smuzhiyun 		}
133*4882a593Smuzhiyun 		for (i = 0; i < bmap_nr; i++)
134*4882a593Smuzhiyun 			bitmap[i] = old_bitmap[i];
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 		/*
137*4882a593Smuzhiyun 		 * This doesn't go through the journal, but it doesn't have to.
138*4882a593Smuzhiyun 		 * The changes are still atomic: We're synced up when the
139*4882a593Smuzhiyun 		 * journal transaction begins, and the new bitmaps don't
140*4882a593Smuzhiyun 		 * matter if the transaction fails.
141*4882a593Smuzhiyun 		 */
142*4882a593Smuzhiyun 		for (i = bmap_nr; i < bmap_nr_new; i++) {
143*4882a593Smuzhiyun 			int depth;
144*4882a593Smuzhiyun 			/*
145*4882a593Smuzhiyun 			 * don't use read_bitmap_block since it will cache
146*4882a593Smuzhiyun 			 * the uninitialized bitmap
147*4882a593Smuzhiyun 			 */
148*4882a593Smuzhiyun 			depth = reiserfs_write_unlock_nested(s);
149*4882a593Smuzhiyun 			bh = sb_bread(s, i * s->s_blocksize * 8);
150*4882a593Smuzhiyun 			reiserfs_write_lock_nested(s, depth);
151*4882a593Smuzhiyun 			if (!bh) {
152*4882a593Smuzhiyun 				vfree(bitmap);
153*4882a593Smuzhiyun 				return -EIO;
154*4882a593Smuzhiyun 			}
155*4882a593Smuzhiyun 			memset(bh->b_data, 0, sb_blocksize(sb));
156*4882a593Smuzhiyun 			reiserfs_set_le_bit(0, bh->b_data);
157*4882a593Smuzhiyun 			reiserfs_cache_bitmap_metadata(s, bh, bitmap + i);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 			set_buffer_uptodate(bh);
160*4882a593Smuzhiyun 			mark_buffer_dirty(bh);
161*4882a593Smuzhiyun 			depth = reiserfs_write_unlock_nested(s);
162*4882a593Smuzhiyun 			sync_dirty_buffer(bh);
163*4882a593Smuzhiyun 			reiserfs_write_lock_nested(s, depth);
164*4882a593Smuzhiyun 			/* update bitmap_info stuff */
165*4882a593Smuzhiyun 			bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
166*4882a593Smuzhiyun 			brelse(bh);
167*4882a593Smuzhiyun 		}
168*4882a593Smuzhiyun 		/* free old bitmap blocks array */
169*4882a593Smuzhiyun 		SB_AP_BITMAP(s) = bitmap;
170*4882a593Smuzhiyun 		vfree(old_bitmap);
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	/*
174*4882a593Smuzhiyun 	 * begin transaction, if there was an error, it's fine. Yes, we have
175*4882a593Smuzhiyun 	 * incorrect bitmaps now, but none of it is ever going to touch the
176*4882a593Smuzhiyun 	 * disk anyway.
177*4882a593Smuzhiyun 	 */
178*4882a593Smuzhiyun 	err = journal_begin(&th, s, 10);
179*4882a593Smuzhiyun 	if (err)
180*4882a593Smuzhiyun 		return err;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	/* Extend old last bitmap block - new blocks have been made available */
183*4882a593Smuzhiyun 	info = SB_AP_BITMAP(s) + bmap_nr - 1;
184*4882a593Smuzhiyun 	bh = reiserfs_read_bitmap_block(s, bmap_nr - 1);
185*4882a593Smuzhiyun 	if (!bh) {
186*4882a593Smuzhiyun 		int jerr = journal_end(&th);
187*4882a593Smuzhiyun 		if (jerr)
188*4882a593Smuzhiyun 			return jerr;
189*4882a593Smuzhiyun 		return -EIO;
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	reiserfs_prepare_for_journal(s, bh, 1);
193*4882a593Smuzhiyun 	for (i = block_r; i < s->s_blocksize * 8; i++)
194*4882a593Smuzhiyun 		reiserfs_clear_le_bit(i, bh->b_data);
195*4882a593Smuzhiyun 	info->free_count += s->s_blocksize * 8 - block_r;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	journal_mark_dirty(&th, bh);
198*4882a593Smuzhiyun 	brelse(bh);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/* Correct new last bitmap block - It may not be full */
201*4882a593Smuzhiyun 	info = SB_AP_BITMAP(s) + bmap_nr_new - 1;
202*4882a593Smuzhiyun 	bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1);
203*4882a593Smuzhiyun 	if (!bh) {
204*4882a593Smuzhiyun 		int jerr = journal_end(&th);
205*4882a593Smuzhiyun 		if (jerr)
206*4882a593Smuzhiyun 			return jerr;
207*4882a593Smuzhiyun 		return -EIO;
208*4882a593Smuzhiyun 	}
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	reiserfs_prepare_for_journal(s, bh, 1);
211*4882a593Smuzhiyun 	for (i = block_r_new; i < s->s_blocksize * 8; i++)
212*4882a593Smuzhiyun 		reiserfs_set_le_bit(i, bh->b_data);
213*4882a593Smuzhiyun 	journal_mark_dirty(&th, bh);
214*4882a593Smuzhiyun 	brelse(bh);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	info->free_count -= s->s_blocksize * 8 - block_r_new;
217*4882a593Smuzhiyun 	/* update super */
218*4882a593Smuzhiyun 	reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
219*4882a593Smuzhiyun 	free_blocks = SB_FREE_BLOCKS(s);
220*4882a593Smuzhiyun 	PUT_SB_FREE_BLOCKS(s,
221*4882a593Smuzhiyun 			   free_blocks + (block_count_new - block_count -
222*4882a593Smuzhiyun 					  (bmap_nr_new - bmap_nr)));
223*4882a593Smuzhiyun 	PUT_SB_BLOCK_COUNT(s, block_count_new);
224*4882a593Smuzhiyun 	PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s));
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	SB_JOURNAL(s)->j_must_wait = 1;
229*4882a593Smuzhiyun 	return journal_end(&th);
230*4882a593Smuzhiyun }
231