Esempio n. 1
0
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;
}
Esempio n. 3
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;
}