Linux Audio

Check our new training course

Yocto distribution development and maintenance

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