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