Line data Source code
1 : #include "clusterautoconfig.h"
2 :
3 : #include <stdio.h>
4 : #include <stdlib.h>
5 : #include <string.h>
6 : #include <stdint.h>
7 : #include <inttypes.h>
8 : #include <sys/types.h>
9 : #include <sys/stat.h>
10 : #include <fcntl.h>
11 : #include <unistd.h>
12 : #include <errno.h>
13 : #include <uuid.h>
14 :
15 : #include "libgfs2.h"
16 : #include "crc32c.h"
17 :
18 71 : int lgfs2_build_master(struct lgfs2_sbd *sdp)
19 : {
20 : struct lgfs2_inum inum;
21 : uint64_t bn;
22 71 : struct lgfs2_buffer_head *bh = NULL;
23 71 : int err = lgfs2_dinode_alloc(sdp, 1, &bn);
24 :
25 71 : if (err != 0)
26 0 : return -1;
27 :
28 71 : inum.in_formal_ino = sdp->md.next_inum++;
29 71 : inum.in_addr = bn;
30 :
31 71 : err = lgfs2_init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
32 71 : if (err != 0)
33 0 : return -1;
34 :
35 71 : sdp->master_dir = lgfs2_inode_get(sdp, bh);
36 71 : if (sdp->master_dir == NULL)
37 0 : return -1;
38 :
39 71 : sdp->master_dir->bh_owned = 1;
40 71 : return 0;
41 : }
42 :
43 111 : int lgfs2_sb_write(const struct lgfs2_sbd *sdp, int fd)
44 : {
45 111 : int i, err = -1;
46 : struct iovec *iov;
47 111 : const size_t sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sdp->sd_bsize;
48 111 : const size_t len = sb_addr + 1;
49 :
50 : /* We only need 2 blocks: one for zeroing and a second for the superblock */
51 111 : char *buf = calloc(2, sdp->sd_bsize);
52 111 : if (buf == NULL)
53 0 : return -1;
54 :
55 111 : iov = malloc(len * sizeof(*iov));
56 111 : if (iov == NULL)
57 0 : goto out_buf;
58 :
59 2942 : for (i = 0; i < len; i++) {
60 2831 : iov[i].iov_base = buf;
61 2831 : iov[i].iov_len = sdp->sd_bsize;
62 : }
63 :
64 111 : lgfs2_sb_out(sdp, buf + sdp->sd_bsize);
65 111 : iov[sb_addr].iov_base = buf + sdp->sd_bsize;
66 :
67 111 : if (pwritev(fd, iov, len, 0) < (len * sdp->sd_bsize))
68 0 : goto out_iov;
69 :
70 111 : err = 0;
71 111 : out_iov:
72 111 : free(iov);
73 111 : out_buf:
74 111 : free(buf);
75 111 : return err;
76 : }
77 :
78 4376533 : uint32_t lgfs2_log_header_hash(char *buf)
79 : {
80 : /* lh_hash only CRCs the fields in the old lh, which ends where lh_crc is now */
81 4376533 : const off_t v1_end = offsetof(struct gfs2_log_header, lh_hash) + 4;
82 :
83 4376533 : return lgfs2_disk_hash(buf, v1_end);
84 : }
85 :
86 4376533 : uint32_t lgfs2_log_header_crc(char *buf, unsigned bsize)
87 : {
88 : /* lh_crc CRCs the rest of the block starting after lh_crc */
89 4376533 : const off_t v1_end = offsetof(struct gfs2_log_header, lh_hash) + 4;
90 4376533 : const unsigned char *lb = (const unsigned char *)buf;
91 :
92 4376533 : return crc32c(~0, lb + v1_end + 4, bsize - v1_end - 4);
93 : }
94 :
95 : /**
96 : * Intialise and write the data blocks for a new journal as a contiguous
97 : * extent. The indirect blocks pointing to these data blocks should have been
98 : * written separately using lgfs2_write_filemeta() and the extent should have
99 : * been allocated using lgfs2_file_alloc().
100 : * ip: The journal's inode
101 : * Returns 0 on success or -1 with errno set on error.
102 : */
103 78 : int lgfs2_write_journal_data(struct lgfs2_inode *ip)
104 : {
105 78 : struct lgfs2_sbd *sdp = ip->i_sbd;
106 78 : unsigned blocks = (ip->i_size + sdp->sd_bsize - 1) / sdp->sd_bsize;
107 78 : uint64_t jext0 = ip->i_num.in_addr + ip->i_blocks - blocks;
108 : /* Not a security sensitive use of random() */
109 : /* coverity[dont_call:SUPPRESS] */
110 78 : uint64_t seq = blocks * (random() / (RAND_MAX + 1.0));
111 : struct gfs2_log_header *lh;
112 78 : uint64_t jblk = jext0;
113 : char *buf;
114 :
115 78 : buf = calloc(1, sdp->sd_bsize);
116 78 : if (buf == NULL)
117 0 : return -1;
118 :
119 78 : lh = (void *)buf;
120 78 : lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
121 78 : lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
122 78 : lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
123 78 : lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_USERSPACE);
124 78 : lh->lh_jinode = cpu_to_be64(ip->i_num.in_addr);
125 :
126 78 : crc32c_optimization_init();
127 : do {
128 : uint32_t hash;
129 :
130 2416640 : lh->lh_sequence = cpu_to_be64(seq);
131 2416640 : lh->lh_blkno = cpu_to_be32(jblk - jext0);
132 2416640 : hash = lgfs2_log_header_hash(buf);
133 2416640 : lh->lh_hash = cpu_to_be32(hash);
134 2416640 : lh->lh_addr = cpu_to_be64(jblk);
135 2416640 : hash = lgfs2_log_header_crc(buf, sdp->sd_bsize);
136 2416640 : lh->lh_crc = cpu_to_be32(hash);
137 :
138 2416640 : if (pwrite(sdp->device_fd, buf, sdp->sd_bsize, jblk * sdp->sd_bsize) != sdp->sd_bsize) {
139 0 : free(buf);
140 0 : return -1;
141 : }
142 :
143 2416640 : lh->lh_crc = 0;
144 2416640 : lh->lh_hash = 0;
145 :
146 2416640 : if (++seq == blocks)
147 78 : seq = 0;
148 :
149 2416640 : } while (++jblk < jext0 + blocks);
150 :
151 78 : free(buf);
152 78 : return 0;
153 : }
154 :
155 102400 : static struct lgfs2_buffer_head *lgfs2_get_file_buf(struct lgfs2_inode *ip, uint64_t lbn, int prealloc)
156 : {
157 102400 : struct lgfs2_sbd *sdp = ip->i_sbd;
158 : uint64_t dbn;
159 102400 : int new = 1;
160 :
161 102400 : if (ip->i_height == 0 && lgfs2_unstuff_dinode(ip))
162 0 : return NULL;
163 :
164 102400 : if (lgfs2_block_map(ip, lbn, &new, &dbn, NULL, prealloc))
165 0 : return NULL;
166 102400 : if (!dbn)
167 0 : return NULL;
168 :
169 102400 : if (!prealloc && new &&
170 69632 : ip->i_size < (lbn + 1) << sdp->sd_bsize_shift) {
171 69632 : lgfs2_bmodified(ip->i_bh);
172 69632 : ip->i_size = (lbn + 1) << sdp->sd_bsize_shift;
173 : }
174 102400 : if (dbn == ip->i_num.in_addr)
175 0 : return ip->i_bh;
176 : else
177 102400 : return lgfs2_bread(sdp, dbn);
178 : }
179 :
180 1 : int lgfs2_write_journal(struct lgfs2_inode *jnl, unsigned bsize, unsigned int blocks)
181 : {
182 : struct gfs2_log_header *lh;
183 : uint32_t x;
184 : /* Not a security sensitive use of random() */
185 : /* coverity[dont_call:SUPPRESS] */
186 1 : uint64_t seq = blocks * (random() / (RAND_MAX + 1.0));
187 : uint32_t hash;
188 : unsigned int height;
189 :
190 : /* Build the height up so our journal blocks will be contiguous and */
191 : /* not broken up by indirect block pages. */
192 1 : height = lgfs2_calc_tree_height(jnl, (blocks + 1) * bsize);
193 1 : if (lgfs2_build_height(jnl, height))
194 0 : return -1;
195 :
196 32769 : for (x = 0; x < blocks; x++) {
197 32768 : struct lgfs2_buffer_head *bh = lgfs2_get_file_buf(jnl, x, 1);
198 32768 : if (!bh)
199 0 : return -1;
200 32768 : lgfs2_bmodified(bh);
201 32768 : lgfs2_brelse(bh);
202 : }
203 1 : crc32c_optimization_init();
204 32769 : for (x = 0; x < blocks; x++) {
205 32768 : struct lgfs2_buffer_head *bh = lgfs2_get_file_buf(jnl, x, 0);
206 32768 : if (!bh)
207 0 : return -1;
208 :
209 32768 : memset(bh->b_data, 0, bsize);
210 32768 : lh = (void *)bh->b_data;
211 32768 : lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
212 32768 : lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
213 32768 : lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
214 32768 : lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_USERSPACE);
215 32768 : lh->lh_jinode = cpu_to_be64(jnl->i_num.in_addr);
216 32768 : lh->lh_sequence = cpu_to_be64(seq);
217 32768 : lh->lh_blkno = cpu_to_be32(x);
218 :
219 32768 : hash = lgfs2_log_header_hash(bh->b_data);
220 32768 : lh->lh_hash = cpu_to_be32(hash);
221 32768 : lh->lh_addr = cpu_to_be64(bh->b_blocknr);
222 :
223 32768 : hash = lgfs2_log_header_crc(bh->b_data, bsize);
224 32768 : lh->lh_crc = cpu_to_be32(hash);
225 32768 : lgfs2_bmodified(bh);
226 32768 : lgfs2_brelse(bh);
227 :
228 32768 : if (++seq == blocks)
229 1 : seq = 0;
230 : }
231 :
232 1 : return 0;
233 : }
234 :
235 1 : int lgfs2_build_journal(struct lgfs2_sbd *sdp, int j, struct lgfs2_inode *jindex, unsigned size_mb)
236 : {
237 : char name[256];
238 : int ret;
239 :
240 1 : sprintf(name, "journal%u", j);
241 1 : sdp->md.journal[j] = lgfs2_createi(jindex, name, S_IFREG | 0600,
242 : GFS2_DIF_SYSTEM);
243 1 : if (sdp->md.journal[j] == NULL) {
244 0 : return errno;
245 : }
246 1 : ret = lgfs2_write_journal(sdp->md.journal[j], sdp->sd_bsize,
247 1 : size_mb << 20 >> sdp->sd_bsize_shift);
248 1 : return ret;
249 : }
250 :
251 : /**
252 : * Write a jindex file given a list of journal inums.
253 : * master: Inode of the master directory
254 : * jnls: List of inum structures relating to previously created journals.
255 : * nmemb: The number of entries in the list (number of journals).
256 : * Returns 0 on success or non-zero on error with errno set.
257 : */
258 71 : struct lgfs2_inode *lgfs2_build_jindex(struct lgfs2_inode *master, struct lgfs2_inum *jnls, size_t nmemb)
259 : {
260 : char fname[GFS2_FNAMESIZE + 1];
261 : struct lgfs2_inode *jindex;
262 :
263 71 : if (nmemb == 0 || jnls == NULL) {
264 0 : errno = EINVAL;
265 0 : return NULL;
266 : }
267 71 : jindex = lgfs2_createi(master, "jindex", S_IFDIR | 0700, GFS2_DIF_SYSTEM);
268 71 : if (jindex == NULL)
269 0 : return NULL;
270 :
271 71 : fname[GFS2_FNAMESIZE] = '\0';
272 :
273 149 : for (unsigned j = 0; j < nmemb; j++) {
274 : int ret;
275 :
276 78 : snprintf(fname, GFS2_FNAMESIZE, "journal%u", j);
277 78 : ret = lgfs2_dir_add(jindex, fname, strlen(fname), &jnls[j], IF2DT(S_IFREG | 0600));
278 78 : if (ret) {
279 0 : lgfs2_inode_put(&jindex);
280 0 : return NULL;
281 : }
282 : }
283 71 : return jindex;
284 : }
285 :
286 78 : struct lgfs2_inode *lgfs2_build_inum_range(struct lgfs2_inode *per_node, unsigned int j)
287 : {
288 : char name[256];
289 : struct lgfs2_inode *ip;
290 :
291 78 : sprintf(name, "inum_range%u", j);
292 78 : ip = lgfs2_createi(per_node, name, S_IFREG | 0600,
293 : GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
294 78 : if (ip == NULL)
295 0 : return NULL;
296 :
297 78 : ip->i_size = sizeof(struct gfs2_inum_range);
298 78 : lgfs2_dinode_out(ip, ip->i_bh->b_data);
299 78 : lgfs2_bmodified(ip->i_bh);
300 78 : return ip;
301 : }
302 :
303 78 : struct lgfs2_inode *lgfs2_build_statfs_change(struct lgfs2_inode *per_node, unsigned int j)
304 : {
305 : char name[256];
306 : struct lgfs2_inode *ip;
307 :
308 78 : sprintf(name, "statfs_change%u", j);
309 78 : ip = lgfs2_createi(per_node, name, S_IFREG | 0600,
310 : GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
311 78 : if (ip == NULL)
312 0 : return NULL;
313 :
314 78 : ip->i_size = sizeof(struct gfs2_statfs_change);
315 78 : lgfs2_dinode_out(ip, ip->i_bh->b_data);
316 78 : lgfs2_bmodified(ip->i_bh);
317 78 : return ip;
318 : }
319 :
320 78 : struct lgfs2_inode *lgfs2_build_quota_change(struct lgfs2_inode *per_node, unsigned int j, unsigned int size_mb)
321 : {
322 78 : struct lgfs2_sbd *sdp = per_node->i_sbd;
323 : struct gfs2_meta_header mh;
324 : char name[256];
325 : struct lgfs2_inode *ip;
326 78 : unsigned int blocks = size_mb << (20 - sdp->sd_bsize_shift);
327 : unsigned int x;
328 : unsigned int hgt;
329 : struct lgfs2_buffer_head *bh;
330 :
331 78 : memset(&mh, 0, sizeof(struct gfs2_meta_header));
332 78 : mh.mh_magic = cpu_to_be32(GFS2_MAGIC);
333 78 : mh.mh_type = cpu_to_be32(GFS2_METATYPE_QC);
334 78 : mh.mh_format = cpu_to_be32(GFS2_FORMAT_QC);
335 :
336 78 : sprintf(name, "quota_change%u", j);
337 78 : ip = lgfs2_createi(per_node, name, S_IFREG | 0600, GFS2_DIF_SYSTEM);
338 78 : if (ip == NULL)
339 0 : return NULL;
340 :
341 78 : hgt = lgfs2_calc_tree_height(ip, (blocks + 1) * sdp->sd_bsize);
342 78 : if (lgfs2_build_height(ip, hgt)) {
343 0 : lgfs2_inode_free(&ip);
344 0 : return NULL;
345 : }
346 :
347 36942 : for (x = 0; x < blocks; x++) {
348 36864 : bh = lgfs2_get_file_buf(ip, x, 0);
349 36864 : if (!bh) {
350 0 : lgfs2_inode_free(&ip);
351 0 : return NULL;
352 : }
353 :
354 36864 : memset(bh->b_data, 0, sdp->sd_bsize);
355 36864 : memcpy(bh->b_data, &mh, sizeof(mh));
356 36864 : lgfs2_bmodified(bh);
357 36864 : lgfs2_brelse(bh);
358 : }
359 78 : return ip;
360 : }
361 :
362 71 : struct lgfs2_inode *lgfs2_build_inum(struct lgfs2_sbd *sdp)
363 : {
364 : struct lgfs2_inode *ip;
365 :
366 71 : ip = lgfs2_createi(sdp->master_dir, "inum", S_IFREG | 0600,
367 : GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
368 71 : return ip;
369 : }
370 :
371 71 : struct lgfs2_inode *lgfs2_build_statfs(struct lgfs2_sbd *sdp)
372 : {
373 : struct lgfs2_inode *ip;
374 :
375 71 : ip = lgfs2_createi(sdp->master_dir, "statfs", S_IFREG | 0600,
376 : GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
377 71 : return ip;
378 : }
379 :
380 71 : struct lgfs2_inode *lgfs2_build_rindex(struct lgfs2_sbd *sdp)
381 : {
382 : struct lgfs2_inode *ip;
383 71 : struct osi_node *n, *next = NULL;
384 : struct lgfs2_rgrp_tree *rl;
385 : struct gfs2_rindex ri;
386 : int count;
387 :
388 71 : ip = lgfs2_createi(sdp->master_dir, "rindex", S_IFREG | 0600,
389 : GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
390 71 : if (ip == NULL)
391 0 : return NULL;
392 :
393 71 : ip->i_payload_format = GFS2_FORMAT_RI;
394 71 : lgfs2_bmodified(ip->i_bh);
395 :
396 71 : memset(&ri, 0, sizeof(struct gfs2_rindex));
397 6581 : for (n = osi_first(&sdp->rgtree); n; n = next) {
398 6510 : next = osi_next(n);
399 6510 : rl = (struct lgfs2_rgrp_tree *)n;
400 :
401 6510 : lgfs2_rindex_out(rl, &ri);
402 :
403 6510 : count = lgfs2_writei(ip, &ri, ip->i_size, sizeof(struct gfs2_rindex));
404 6510 : if (count != sizeof(struct gfs2_rindex)) {
405 0 : lgfs2_inode_free(&ip);
406 0 : return NULL;
407 : }
408 : }
409 71 : memset(&ri, 0, sizeof(struct gfs2_rindex));
410 71 : count = __lgfs2_writei(ip, &ri, ip->i_size, sizeof(struct gfs2_rindex), 0);
411 71 : if (count != sizeof(struct gfs2_rindex)) {
412 0 : lgfs2_inode_free(&ip);
413 0 : return NULL;
414 : }
415 71 : return ip;
416 : }
417 :
418 71 : struct lgfs2_inode *lgfs2_build_quota(struct lgfs2_sbd *sdp)
419 : {
420 : struct lgfs2_inode *ip;
421 : struct gfs2_quota qu;
422 : int count;
423 :
424 71 : ip = lgfs2_createi(sdp->master_dir, "quota", S_IFREG | 0600,
425 : GFS2_DIF_SYSTEM | GFS2_DIF_JDATA);
426 71 : if (ip == NULL)
427 0 : return NULL;
428 :
429 71 : ip->i_payload_format = GFS2_FORMAT_QU;
430 71 : lgfs2_bmodified(ip->i_bh);
431 :
432 71 : memset(&qu, 0, sizeof(struct gfs2_quota));
433 71 : qu.qu_value = cpu_to_be64(1);
434 :
435 71 : count = lgfs2_writei(ip, &qu, ip->i_size, sizeof(struct gfs2_quota));
436 71 : if (count != sizeof(struct gfs2_quota)) {
437 0 : lgfs2_inode_free(&ip);
438 0 : return NULL;
439 : }
440 71 : count = lgfs2_writei(ip, &qu, ip->i_size, sizeof(struct gfs2_quota));
441 71 : if (count != sizeof(struct gfs2_quota)) {
442 0 : lgfs2_inode_free(&ip);
443 0 : return NULL;
444 : }
445 :
446 71 : return ip;
447 : }
448 :
449 71 : int lgfs2_build_root(struct lgfs2_sbd *sdp)
450 : {
451 : struct lgfs2_inum inum;
452 : uint64_t bn;
453 71 : struct lgfs2_buffer_head *bh = NULL;
454 71 : int err = lgfs2_dinode_alloc(sdp, 1, &bn);
455 :
456 71 : if (err != 0)
457 0 : return -1;
458 :
459 71 : inum.in_formal_ino = sdp->md.next_inum++;
460 71 : inum.in_addr = bn;
461 :
462 71 : err = lgfs2_init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, 0, &inum);
463 71 : if (err != 0)
464 0 : return -1;
465 :
466 71 : sdp->md.rooti = lgfs2_inode_get(sdp, bh);
467 71 : if (sdp->md.rooti == NULL)
468 0 : return -1;
469 :
470 71 : sdp->md.rooti->bh_owned = 1;
471 71 : return 0;
472 : }
473 :
474 71 : int lgfs2_init_inum(struct lgfs2_sbd *sdp)
475 : {
476 71 : struct lgfs2_inode *ip = sdp->md.inum;
477 : __be64 buf;
478 : int count;
479 :
480 71 : buf = cpu_to_be64(sdp->md.next_inum);
481 71 : count = lgfs2_writei(ip, &buf, 0, sizeof(uint64_t));
482 71 : if (count != sizeof(uint64_t))
483 0 : return -1;
484 :
485 71 : return 0;
486 : }
487 :
488 71 : int lgfs2_init_statfs(struct lgfs2_sbd *sdp, struct gfs2_statfs_change *res)
489 : {
490 71 : struct lgfs2_inode *ip = sdp->md.statfs;
491 : struct gfs2_statfs_change sc;
492 : int count;
493 :
494 71 : sc.sc_total = cpu_to_be64(sdp->blks_total);
495 71 : sc.sc_free = cpu_to_be64(sdp->blks_total - sdp->blks_alloced);
496 71 : sc.sc_dinodes = cpu_to_be64(sdp->dinodes_alloced);
497 :
498 71 : count = lgfs2_writei(ip, &sc, 0, sizeof(sc));
499 71 : if (count != sizeof(sc))
500 0 : return -1;
501 :
502 71 : if (res)
503 71 : *res = sc;
504 71 : return 0;
505 : }
506 :
507 16379023 : int lgfs2_check_meta(const char *buf, int type)
508 : {
509 16379023 : struct gfs2_meta_header *mh = (struct gfs2_meta_header *)buf;
510 16379023 : uint32_t check_magic = be32_to_cpu(mh->mh_magic);
511 16379023 : uint32_t check_type = be32_to_cpu(mh->mh_type);
512 :
513 16379023 : if((check_magic != GFS2_MAGIC) || (type && (check_type != type)))
514 7429035 : return -1;
515 8949988 : return 0;
516 : }
517 :
518 177977 : unsigned lgfs2_bm_scan(struct lgfs2_rgrp_tree *rgd, unsigned idx, uint64_t *buf, uint8_t state)
519 : {
520 177977 : struct lgfs2_bitmap *bi = &rgd->rt_bits[idx];
521 177977 : unsigned n = 0;
522 177977 : uint32_t blk = 0;
523 :
524 178810 : while(blk < (bi->bi_len * GFS2_NBBY)) {
525 178741 : blk = lgfs2_bitfit((uint8_t *)bi->bi_data + bi->bi_offset,
526 : bi->bi_len, blk, state);
527 178741 : if (blk == LGFS2_BFITNOENT)
528 177908 : break;
529 833 : buf[n++] = blk + (bi->bi_start * GFS2_NBBY) + rgd->rt_data0;
530 833 : blk++;
531 : }
532 177977 : return n;
533 : }
|