root/trunk/client/revimage/image_xfs.c

Revision 197, 7.1 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 #include <linux/types.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <sys/ioctl.h>
34 #include <unistd.h>
35 #include <netinet/in.h>
36
37 #include "compress.h"
38 #include "client.h"
39 #include "image_xfs.h"
40
41 char info1[32], info2[32];
42
43 struct xfs_superblock sb;
44
45 /* proto */
46 void scanSbtree(int fd, PARAMS *p, struct xfs_agf *agf, __u32 root, __u32 levels);
47 void scanfuncBno(int fd, PARAMS *p, char *ablock, __u32 level, struct xfs_agf *agf);
48
49 /*  */
50 inline __u64 ntohll(__u64 number)
51 {
52   return ( htonl( (number >> 32) & 0xFFFFFFFF) |
53            ((__u64) (htonl(number & 0xFFFFFFFF))  << 32));
54 }
55
56 /* check for XFS */
57 void checkit(char *dev)
58 {
59   int fd, bs;
60   __u8 buf[512];
61
62   fd = open (dev, O_RDONLY);
63   if (fd == -1) exit(1); 
64   if (read(fd, buf, 256) != 256) exit(1);
65  
66   if (strncmp (buf, "XFSB", 4) == 0)
67     {
68       debug("XFSB magic found\n");
69       bs = (buf[4]<<24) + (buf[5]<<16) + (buf[6]<<8) + (buf[7]);
70       debug("Block size : %d\n", bs);
71       if (bs != 4096)
72         {
73           debug ("Strange block size %d ! Only 4096 supported. \n", bs);
74           exit(1);
75         }
76     }
77   else
78     {
79       debug("XFSB magic not found\n");
80       exit(1);
81     }
82   close (fd);
83 }
84
85
86 int readdata(int fd, void *buf, __u64 offset, __u32 size)
87 {
88   if (lseek64(fd, offset, SEEK_SET) == -1)
89     {
90       perror("lseek64 readdata()");
91     }
92
93   read(fd, buf, size);
94  
95   return 0;
96 }
97
98 /* AG to offset conversion */
99 __u64 convertAgbToDaddr(__u32 agno, __u32 Agblockno)
100 {
101   __u64 FSBlock;
102
103   FSBlock = (((__u64)agno)*((__u64)ntohl(sb.sb_agblocks)))+((__u64)Agblockno);
104   return (FSBlock * (__u64)4096);
105 }
106
107 __u64 convertAgToDaddr(__u32 agno, __u32 Offset)
108 {
109   return (convertAgbToDaddr(agno, 0)+((__u64)Offset)*((__u64)BBSIZE));
110 }
111
112
113
114 void addtohist(PARAMS *p, __u32 agno, __u32 Agblockno, __u64 Len)
115 {
116   __u64 i;
117   __u64 Base;
118
119   Base = (((__u64)agno) * ((__u64)ntohl(sb.sb_agblocks))) + ((__u64)Agblockno);
120   // debug("%lld , %lld\n", Base, Len);
121   for (i=0; i < Len; i++) {
122     /* unset 8 bits since one block = 8 sectors */
123     p->bitmap[Base+i] = 0;
124   }
125 }
126
127 void scanFreelist(int fd, PARAMS *p, struct xfs_agf *agf)
128 {
129   __u32 agno = ntohl(agf->agf_seqno);
130   struct xfs_agfl       agfl;
131   __u32 blockno, i;
132
133   if (ntohl(agf->agf_flcount) == 0)
134     return;
135
136   readdata(fd, &agfl, convertAgToDaddr(agno, XFS_AGFL_DADDR), sizeof(agfl));
137
138   // process list
139   i = ntohl(agf->agf_flfirst);
140   for (;;)
141     {
142       blockno = ntohl(agfl.agfl_bno[i]);
143       addtohist(p, agno, blockno, 1);
144       if (i == ntohl(agf->agf_fllast))
145         break;
146       if (++i == XFS_AGFL_SIZE)
147         i = 0;
148     }
149 }
150
151 void scanSbtree(int fd, PARAMS *p, struct xfs_agf *agf, __u32 root, __u32 levels)
152 {
153   char buf[MAX_XFSBLOCKSIZE];
154
155   readdata(fd, buf, convertAgbToDaddr(ntohl(agf->agf_seqno), root), 4096);
156   scanfuncBno(fd, p, buf, levels - 1, agf);
157 }
158
159
160 void scanfuncBno(int fd, PARAMS *p, char *ablock, __u32 level, struct xfs_agf *agf)
161 {
162   xfs_alloc_block       *block = (xfs_alloc_block *) ablock;
163   xfs_alloc_ptr         *pp;
164   xfs_alloc_rec         *rp;
165   int i, mxr;
166
167
168   if (level == 0)
169     {
170       rp = (xfs_alloc_rec*) (ablock + sizeof(xfs_alloc_block));
171
172       for (i = 0; i < ntohs(block->bb_numrecs); i++) {
173         addtohist(p, ntohl(agf->agf_seqno), ntohl(rp[i].ar_startblock), ntohl(rp[i].ar_blockcount));
174       }
175       return;
176     }
177    
178   mxr  = (int)((4096 - (uint)sizeof(xfs_alloc_block)) / ((uint)sizeof(xfs_alloc_key) + (uint)sizeof(xfs_alloc_ptr)));
179   pp = (xfs_alloc_ptr *)((char *)(ablock) + sizeof(xfs_alloc_block) + (mxr * sizeof(xfs_alloc_key)));     
180   for (i = 0; i < ntohs(block->bb_numrecs); i++)
181     {
182       scanSbtree(fd, p, agf, ntohl(pp[i]), level);
183     } 
184 }
185
186
187
188 /*  */
189 void readsb(PARAMS *p, char *dev)
190 {
191    int fd;
192    __u32 agcount, agblocks, i;
193    __u64 blocks, fblocks, used = 0;
194    int bits[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
195    
196    fd = open (dev, O_RDONLY);
197    if (fd == -1) exit(1); 
198    if (read(fd, &sb, sizeof(xfs_superblock)) != sizeof(xfs_superblock)) exit(1);
199    
200    blocks = ntohll(sb.sb_dblocks);
201    fblocks = ntohll(sb.sb_fdblocks);
202    agcount = ntohl(sb.sb_agcount);
203    agblocks = ntohl(sb.sb_agblocks);
204
205    debug("Total Blocks  : %lld\n", blocks);
206    debug("Used Blocks   : %lld\n", blocks - fblocks );
207    debug("Alloc groups  : %d\n", agcount);
208    debug("Alloc blocks  : %d\n", agblocks);
209    debug("Volume name   : %12s\n", sb.sb_fname);
210
211    /* alloc bitmap */
212    /* 1 block = 8 sectors */
213    p->bitmap = (unsigned char *) calloc (1, blocks);
214    p->bitmaplg = blocks;
215    /* fill bitmap */
216    memset(p->bitmap, 255, blocks);
217    p->nb_sect = blocks * 8;
218    
219    /* rewind */
220    lseek(fd, 0, SEEK_SET);
221
222    /* AG loop */
223    for (i = 0; i < agcount ; i++)
224      {
225        struct xfs_agf agf;
226        
227        if (lseek64(fd, convertAgToDaddr(i, XFS_AGF_DADDR), SEEK_SET) == -1)
228          {
229            perror("=lseek64");
230          }
231
232        read(fd, &agf, sizeof(struct xfs_agf));
233
234        if ((ntohl(agf.agf_magicnum)) != XFS_AGF_MAGIC)
235          {
236            debug("No magic found in AG %d\n", i);
237            exit(1);
238          }
239              
240        debug("Alloc %d: %u free\n", i, ntohl(agf.agf_freeblks));
241        
242        scanFreelist(fd, p, &agf);
243        scanSbtree(fd, p, &agf, ntohl(agf.agf_roots[XFS_BTNUM_BNO]), ntohl(agf.agf_levels[XFS_BTNUM_BNO]));
244        
245      }
246  
247    /* count used (verification) */
248    for (i = 0; i < p->bitmaplg; i++)
249      used += (bits[p->bitmap[i] >> 4] + bits[p->bitmap[i] & 15]);
250
251    debug ("Used sectors : %lld (total : %lld)\n", used, p->nb_sect);
252
253    if (used == (blocks - fblocks)*8) {
254      debug ("Verified bitmap count OK\n");
255    } else {
256      debug ("Superblock used block count and bitmap count do not match !\n");
257      debug ("%lld != %lld\n", used, (blocks - fblocks)*8);
258      if (used > (blocks - fblocks)*8) {
259        debug ("Since my count is greater, let's continue !\n");
260      } else
261        exit(1);
262    }
263
264    sprintf(info1, "%llu", p->nb_sect);
265    sprintf(info2, "%llu", used);
266    print_sect_info(p->nb_sect, used);
267 }
268
269
270 int main (int argc, char *argv[])
271 {
272   int fd;
273   PARAMS params;
274
275    if (argc != 3)
276     {
277       fprintf (stderr, "Usage : image_xfs [device] [image prefix name]\n");
278       exit (1);
279     }
280
281   checkit(argv[1]);
282   readsb(&params, argv[1]);
283    
284   if (argv[2][0] == '?')
285     exit (0);
286
287   ui_send("init_backup", 5, argv[1], argv[2], info1, info2, argv[0]);
288   fd = open (argv[1], O_RDONLY);
289   compress_volume (fd, argv[2], &params, "XFS");
290   close (fd);
291
292   return 0;
293 }
Note: See TracBrowser for help on using the browser.