uint32_t lgfs2_log_header_hash(char *buf) { /* lh_hash only CRCs the fields in the old lh, which ends where lh_crc is now */ const off_t v1_end = offsetof(struct gfs2_log_header, lh_hash) + 4; return gfs2_disk_hash(buf, v1_end); }
static int gfs2_dhash(const struct dentry *dentry, const struct inode *inode, struct qstr *str) { str->hash = gfs2_disk_hash(str->name, str->len); return 0; }
/** * Intialise and write the data blocks for a new journal as a contiguous * extent. The indirect blocks pointing to these data blocks should have been * written separately using lgfs2_write_filemeta() and the extent should have * been allocated using lgfs2_file_alloc(). * ip: The journal's inode * Returns 0 on success or -1 with errno set on error. */ int lgfs2_write_journal_data(struct gfs2_inode *ip) { uint32_t hash; struct gfs2_log_header lh = { .lh_header.mh_magic = GFS2_MAGIC, .lh_header.mh_type = GFS2_METATYPE_LH, .lh_header.mh_format = GFS2_FORMAT_LH, .lh_flags = GFS2_LOG_HEAD_UNMOUNT, }; struct gfs2_buffer_head *bh; struct gfs2_sbd *sdp = ip->i_sbd; unsigned blocks = (ip->i_di.di_size + sdp->bsize - 1) / sdp->bsize; uint64_t jext0 = ip->i_di.di_num.no_addr + ip->i_di.di_blocks - blocks; uint64_t seq = ((blocks) * (random() / (RAND_MAX + 1.0))); bh = bget(sdp, jext0); if (bh == NULL) return -1; do { lh.lh_sequence = seq; lh.lh_blkno = bh->b_blocknr - jext0; gfs2_log_header_out(&lh, bh); hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header)); ((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash); if (bwrite(bh)) { free(bh); return -1; } if (++seq == blocks) seq = 0; } while (++bh->b_blocknr < jext0 + blocks); free(bh); return 0; } int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned int blocks) { struct gfs2_log_header lh; unsigned int x; uint64_t seq = ((blocks) * (random() / (RAND_MAX + 1.0))); uint32_t hash; unsigned int height; /* Build the height up so our journal blocks will be contiguous and */ /* not broken up by indirect block pages. */ height = calc_tree_height(jnl, (blocks + 1) * bsize); build_height(jnl, height); memset(&lh, 0, sizeof(struct gfs2_log_header)); lh.lh_header.mh_magic = GFS2_MAGIC; lh.lh_header.mh_type = GFS2_METATYPE_LH; lh.lh_header.mh_format = GFS2_FORMAT_LH; lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT; for (x = 0; x < blocks; x++) { struct gfs2_buffer_head *bh = get_file_buf(jnl, x, TRUE); if (!bh) return -1; bmodified(bh); brelse(bh); } for (x = 0; x < blocks; x++) { struct gfs2_buffer_head *bh = get_file_buf(jnl, x, FALSE); if (!bh) return -1; memset(bh->b_data, 0, bsize); lh.lh_sequence = seq; lh.lh_blkno = x; gfs2_log_header_out(&lh, bh); hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header)); ((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash); bmodified(bh); brelse(bh); if (++seq == blocks) seq = 0; } return 0; } int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex) { char name[256]; int ret; sprintf(name, "journal%u", j); sdp->md.journal[j] = createi(jindex, name, S_IFREG | 0600, GFS2_DIF_SYSTEM); if (sdp->md.journal[j] == NULL) { return errno; } ret = write_journal(sdp->md.journal[j], sdp->bsize, sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift); return ret; }