root/trunk/client/revimage/image_lvmreiserfs.c

Revision 197, 9.6 kB (checked in by ludo, 2 years ago)

new client/server protocol for the UI (from r3948)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
Line 
1 /*
2  * $Id$
3  */
4 /*
5  *  Linbox Rescue Server
6  *  Copyright (C) 2002-2005 Linbox FAS, Free & Alter Soft
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29
30 #include <sys/mount.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <asm/types.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <mntent.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <stdlib.h>
41 #include <stdint.h>
42 #include <sys/vfs.h>
43
44 #include "./reiserfsprogs/include/io.h"
45 #include "./reiserfsprogs/include/misc.h"
46 #include "./reiserfsprogs/include/reiserfs_lib.h"
47 #include "./reiserfsprogs/version.h"
48
49 //#include <linux/lvm.h>
50
51 #include "compress.h"
52 #include "client.h"
53 #include "lvm.h"
54
55 typedef struct p {
56     reiserfs_bitmap_t bm;
57     unsigned long blocks;
58     unsigned long offset;       /* offset to real FS in bytes (LVM overhead) */
59 } CPARAMS;
60
61 char info1[32], info2[32];
62 unsigned long lvm_sect = 0;
63
64 /* BEGIN CODE TAKE FROM reiserfsprogs 3.x */
65
66 /* fixme: this assumes that journal start and journal size are set
67    correctly */
68 static void check_first_bitmap(reiserfs_filsys_t fs, char *bitmap)
69 {
70     int i;
71     int bad;
72
73     bad = 0;
74     for (i = 0; i < rs_journal_start(fs->s_rs) +
75          rs_journal_size(fs->s_rs) + 1; i++) {
76         if (!test_bit(i, bitmap)) {
77             bad = 1;
78             /*reiserfs_warning ("block %d is marked free in the first bitmap, fixed\n", i); */
79             /*set_bit (i, bitmap); */
80         }
81     }
82     if (bad)
83         reiserfs_warning(stderr,
84                          "reiserfs_open: first bitmap looks corrupted\n");
85 }
86
87
88 /* read bitmap blocks */
89 void myreiserfs_read_bitmap_blocks(reiserfs_filsys_t fs, long offset)
90 {
91     struct reiserfs_super_block *rs = fs->s_rs;
92     struct buffer_head *bh = SB_BUFFER_WITH_SB(fs);
93     int fd = fs->s_dev;
94     unsigned long block;
95     int i;
96     /* LUDO: the 1st block has already the offset */
97     bh->b_blocknr -= offset / 4096;
98     /* read bitmaps, and correct a bit if necessary */
99     SB_AP_BITMAP(fs) = getmem(sizeof(void *) * rs_bmap_nr(rs));
100     for (i = 0, block = bh->b_blocknr + 1; i < rs_bmap_nr(rs); i++) {
101         SB_AP_BITMAP(fs)[i] =
102             bread(fd, block + (offset / 4096), fs->s_blocksize);
103         if (!SB_AP_BITMAP(fs)[i]) {
104             reiserfs_warning(stderr,
105                              "reiserfs_open: bread failed reading bitmap #%d (%lu)\n",
106                              i, block);
107             SB_AP_BITMAP(fs)[i] = getblk(fd, block, fs->s_blocksize);
108             memset(SB_AP_BITMAP(fs)[i]->b_data, 0xff, fs->s_blocksize);
109             set_bit(BH_Uptodate, &SB_AP_BITMAP(fs)[i]->b_state);
110         }
111
112         /* all bitmaps have to have itself marked used on it */
113         if (bh->b_blocknr == 16) {
114             if (!test_bit
115                 (block % (fs->s_blocksize * 8),
116                  SB_AP_BITMAP(fs)[i]->b_data)) {
117                 reiserfs_warning(stderr,
118                                  "reiserfs_open: bitmap %d was marked free\n",
119                                  i);
120                 /*set_bit (block % (fs->s_blocksize * 8), SB_AP_BITMAP (fs)[i]->b_data); */
121             }
122         } else {
123             /* bitmap not spread over partition: fixme: does not
124                work when number of bitmaps => 32768 */
125             if (!test_bit(block, SB_AP_BITMAP(fs)[0]->b_data)) {
126                 reiserfs_warning(stderr,
127                                  "reiserfs_open: bitmap %d was marked free\n",
128                                  i);
129                 /*set_bit (block, SB_AP_BITMAP (fs)[0]->b_data); */
130             }
131         }
132
133         if (i == 0) {
134             /* first bitmap has to have marked used super block
135                and journal areas */
136             check_first_bitmap(fs, SB_AP_BITMAP(fs)[i]->b_data);
137         }
138         /* LUDO: remove the offset */
139         block =
140             ((bh->b_blocknr) ==
141              16 ? ((i + 1) * fs->s_blocksize * 8) : (block + 1));
142
143     }
144 }
145
146 /* read super block and bitmaps. fixme: only 4k blocks, pre-journaled format
147    is refused */
148 reiserfs_filsys_t myreiserfs_open(char *filename, int flags, int *error,
149                                   void *vp, long offset)
150 {
151     reiserfs_filsys_t fs;
152     struct buffer_head *bh;
153     struct reiserfs_super_block *rs;
154     int fd, i;
155
156     fd = open(filename, flags | O_LARGEFILE);
157     if (fd == -1) {
158         if (error)
159             *error = errno;
160         return 0;
161     }
162
163     fs = getmem(sizeof(*fs));
164     fs->s_dev = fd;
165     fs->s_vp = vp;
166     asprintf(&fs->file_name, "%s", filename);
167
168     /* reiserfs super block is either in 16-th or in 2-nd 4k block of the
169        device */
170     for (i = 16; i > 0; i -= 14) {
171         bh = bread(fd, i + (offset / 4096), 4096);
172         if (!bh) {
173             reiserfs_warning(stderr,
174                              "reiserfs_open: bread failed reading block %d\n",
175                              i);
176         } else {
177             rs = (struct reiserfs_super_block *) bh->b_data;
178
179             if (is_reiser2fs_magic_string(rs)
180                 || is_reiserfs_magic_string(rs))
181                 goto found;
182
183             /* reiserfs signature is not found at the i-th 4k block */
184             brelse(bh);
185         }
186     }
187
188     reiserfs_warning(stderr,
189                      "reiserfs_open: neither new nor old reiserfs format "
190                      "found on %s\n", filename);
191     if (error)
192         *error = 666;
193     return fs;
194
195   found:
196
197     /* fixme: we could make some check to make sure that super block looks
198        correctly */
199     fs->s_version = is_reiser2fs_magic_string(rs) ? REISERFS_VERSION_2 :
200         REISERFS_VERSION_1;
201     fs->s_blocksize = rs_blocksize(rs);
202     fs->s_hash_function = code2func(rs_hash(rs));
203     SB_BUFFER_WITH_SB(fs) = bh;
204     fs->s_rs = rs;
205     fs->s_flags = flags;        /* O_RDONLY or O_RDWR */
206     fs->s_vp = vp;
207
208
209     myreiserfs_read_bitmap_blocks(fs, offset);
210
211     return fs;
212
213 }
214
215
216
217 /* copy reiserfs filesystem bitmap into memory bitmap */
218 int myreiserfs_fetch_disk_bitmap(reiserfs_bitmap_t bm,
219                                  reiserfs_filsys_t fs)
220 {
221     int i;
222     int bytes;
223     char *p;
224     int unused_bits;
225
226     //reiserfs_warning (stderr, "Fetching on-disk bitmap..");
227     assert(bm->bm_bit_size == SB_BLOCK_COUNT(fs));
228
229     bytes = fs->s_blocksize;
230     p = bm->bm_map;
231     for (i = 0; i < SB_BMAP_NR(fs); i++) {
232         if ((i == (SB_BMAP_NR(fs) - 1))
233             && bm->bm_byte_size % fs->s_blocksize)
234             bytes = bm->bm_byte_size % fs->s_blocksize;
235
236         memcpy(p, SB_AP_BITMAP(fs)[i]->b_data, bytes);
237         p += bytes;
238     }
239
240     /* on disk bitmap has bits out of SB_BLOCK_COUNT set to 1, where as
241        reiserfs_bitmap_t has those bits set to 0 */
242     unused_bits = bm->bm_byte_size * 8 - bm->bm_bit_size;
243     for (i = 0; i < unused_bits; i++)
244         clear_bit(bm->bm_bit_size + i, bm->bm_map);
245
246     bm->bm_set_bits = 0;
247     /* FIXME: optimize that */
248     for (i = 0; i < bm->bm_bit_size; i++)
249         if (reiserfs_bitmap_test_bit(bm, i))
250             bm->bm_set_bits++;
251     /* unused part of last bitmap block is filled with 0s */
252     if (bm->bm_bit_size % (fs->s_blocksize * 8))
253         for (i = SB_BLOCK_COUNT(fs) % (fs->s_blocksize * 8);
254              i < fs->s_blocksize * 8; i++)
255             if (!test_bit(i, SB_AP_BITMAP(fs)[SB_BMAP_NR(fs) - 1]->b_data)) {
256                 reiserfs_warning(stderr,
257                                  "fetch_bitmap: on-disk bitmap is not padded properly\n");
258                 break;
259             }
260     //reiserfs_warning (stderr, "done\n");
261     return 0;
262 }
263
264
265 void allocated_sectors(PARAMS * p, CPARAMS * cp)
266 {
267     unsigned long i, used = 0;
268     unsigned long bitmap_lg;
269     int off = 0;
270
271     void setbit(unsigned char *base, unsigned long bit) {
272         unsigned char mask[8] =
273             { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
274
275         base[bit >> 3] |= mask[bit & 7];
276     }
277
278     // TODO : check if block is really 4096 byte long...
279     // ...it seems to be
280     p->nb_sect = cp->blocks * 8;
281     off = cp->offset / 512;
282
283     p->bitmap = (unsigned char *) calloc(bitmap_lg =
284                                          (p->nb_sect + off + 7) / 8, 1);
285     p->bitmaplg = bitmap_lg;
286
287     // backup LVM: everything
288     for (i = 0; i < off; i++)
289         setbit(p->bitmap, i);
290     // backup Reiserfs
291     for (i = 0; i < p->nb_sect; i++)
292         if (reiserfs_bitmap_test_bit(cp->bm, i / 8)) {
293             setbit(p->bitmap, i + off);
294             used++;
295         }
296
297     sprintf(info1, "%lu", p->nb_sect + off);
298     sprintf(info2, "%lu", used + off);
299     print_sect_info(p->nb_sect + off, used + off);
300
301     if (p->nb_sect != lvm_sect && lvm_sect != 0) {
302       debug("Cannot backup this LVM/Reiserfs volume in optimized mode\n"
303             "because data may span multiple volumes.\n");
304       exit(1);
305
306     }
307     p->nb_sect += off;
308
309 }
310
311
312 int main(int argc, char *argv[])
313 {
314     reiserfs_bitmap_t bm;
315     reiserfs_filsys_t fs;
316     PARAMS params;
317     CPARAMS cp;
318     int err = 0;
319     long long offset;
320     int fd;
321
322     if (argc != 3) {
323         fprintf(stderr,
324                 "Usage : image_reiserfs [device] [image prefix name]\n");
325         exit(1);
326     }
327     // check for LVM
328     lvm_check(argv[1], &offset);
329
330     fs = myreiserfs_open(argv[1], O_RDONLY, &err, 0, offset);
331     if ((!(fs)) || err) {
332         debug("Reiserfs_open failed\n");
333         exit(1);
334     }
335     if (fs->s_blocksize != 4096) {
336         debug("Bad blocksize (!= 4096)\n");
337         exit(1);
338     }
339     debug("Bitmap  : %d bits\n", SB_BLOCK_COUNT(fs));
340     bm = reiserfs_create_bitmap(SB_BLOCK_COUNT(fs));
341     myreiserfs_fetch_disk_bitmap(bm, fs);
342     cp.bm = bm;
343     cp.offset = offset;
344     cp.blocks = rs_block_count(fs->s_rs);
345     assert(fs->s_blocksize == 4096);
346
347     /* for (i=0;i<SB_BLOCK_COUNT(fs)/8;i++) {
348        debug("%02x", bm->bm_map[i]);
349        }
350        debug("\n"); */
351
352     allocated_sectors(&params, &cp);
353
354     reiserfs_close(fs);
355
356     if (argv[2][0] == '?')
357         exit(0);
358
359     // Compress now
360     //
361
362     ui_send("init_backup", 5, argv[1], argv[2], info1, info2, argv[0]);
363     fd = open(argv[1], O_RDONLY);
364     compress_volume(fd, argv[2], &params, "RFS3");
365     close(fd);
366
367     return 0;
368 }
Note: See TracBrowser for help on using the browser.