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