Exemple #1
0
/**
 * nilfs_compute_checksum - compute checksum of blocks continuously
 * @nilfs: nilfs object
 * @bhs: buffer head of start block
 * @sum: place to store result
 * @offset: offset bytes in the first block
 * @check_bytes: number of bytes to be checked
 * @start: DBN of start block
 * @nblock: number of blocks to be checked
 */
static int nilfs_compute_checksum(struct the_nilfs *nilfs,
				  struct buffer_head *bhs, u32 *sum,
				  unsigned long offset, u64 check_bytes,
				  sector_t start, unsigned long nblock)
{
	unsigned int blocksize = nilfs->ns_blocksize;
	unsigned long size;
	u32 crc;

	BUG_ON(offset >= blocksize);
	check_bytes -= offset;
	size = min_t(u64, check_bytes, blocksize - offset);
	crc = crc32_le(nilfs->ns_crc_seed,
		       (unsigned char *)bhs->b_data + offset, size);
	if (--nblock > 0) {
		do {
			struct buffer_head *bh;

			bh = __bread(nilfs->ns_bdev, ++start, blocksize);
			if (!bh)
				return -EIO;
			check_bytes -= size;
			size = min_t(u64, check_bytes, blocksize);
			crc = crc32_le(crc, bh->b_data, size);
			brelse(bh);
		} while (--nblock > 0);
	}
	*sum = crc;
	return 0;
}
s32 bdev_read(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read)
{
	BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
	FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
#ifdef CONFIG_EXFAT_KERNEL_DEBUG
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	long flags = sbi->debug_flags;

	if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
		return FFS_MEDIAERR;
#endif /* CONFIG_EXFAT_KERNEL_DEBUG */

	if (!p_bd->opened)
		return FFS_MEDIAERR;

	if (*bh)
		__brelse(*bh);

	if (read)
		*bh = __bread(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits);
	else
		*bh = __getblk(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits);

	if (*bh)
		return FFS_SUCCESS;

	WARN(!p_fs->dev_ejected,
		"[EXFAT] No bh, device seems wrong or to be ejected.\n");

	return FFS_MEDIAERR;
}
Exemple #3
0
/**
 * nilfs_read_log_header - read summary header of the specified log
 * @nilfs: nilfs object
 * @start_blocknr: start block number of the log
 * @sum: pointer to return segment summary structure
 */
static struct buffer_head *
nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr,
		      struct nilfs_segment_summary **sum)
{
	struct buffer_head *bh_sum;

	bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
	if (bh_sum)
		*sum = (struct nilfs_segment_summary *)bh_sum->b_data;
	return bh_sum;
}
Exemple #4
0
static int bdev_read_page(struct block_device *bdev, long pos, void *buf)
{
	struct buffer_head *bh;
	BUG_ON (pos%PAGE_SIZE);
	bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
	if (!bh || (!bh->b_data)) {
		return -1;
	}
	memcpy(buf, bh->b_data, PAGE_SIZE);	/* FIXME: may need kmap() */
	BUG_ON(!buffer_uptodate(bh));
	brelse(bh);
	return 0;
} 
Exemple #5
0
static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
				     struct nilfs_recovery_block *rb,
				     struct page *page)
{
	struct buffer_head *bh_org;
	void *kaddr;

	bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize);
	if (unlikely(!bh_org))
		return -EIO;

	kaddr = kmap_atomic(page);
	memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
	kunmap_atomic(kaddr);
	brelse(bh_org);
	return 0;
}
Exemple #6
0
/**
 * nilfs_read_super_root_block - read super root block
 * @nilfs: nilfs object
 * @sr_block: disk block number of the super root block
 * @pbh: address of a buffer_head pointer to return super root buffer
 * @check: CRC check flag
 */
int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block,
				struct buffer_head **pbh, int check)
{
	struct buffer_head *bh_sr;
	struct nilfs_super_root *sr;
	u32 crc;
	int ret;

	*pbh = NULL;
	bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize);
	if (unlikely(!bh_sr)) {
		ret = NILFS_SEG_FAIL_IO;
		goto failed;
	}

	sr = (struct nilfs_super_root *)bh_sr->b_data;
	if (check) {
		unsigned int bytes = le16_to_cpu(sr->sr_bytes);

		if (bytes == 0 || bytes > nilfs->ns_blocksize) {
			ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
			goto failed_bh;
		}
		if (nilfs_compute_checksum(
			    nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes,
			    sr_block, 1)) {
			ret = NILFS_SEG_FAIL_IO;
			goto failed_bh;
		}
		if (crc != le32_to_cpu(sr->sr_sum)) {
			ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
			goto failed_bh;
		}
	}
	*pbh = bh_sr;
	return 0;

 failed_bh:
	brelse(bh_sr);

 failed:
	return nilfs_warn_segment_error(nilfs->ns_sb, ret);
}
Exemple #7
0
/**
 * nilfs_read_summary_info - read an item on summary blocks of a log
 * @nilfs: nilfs object
 * @pbh: the current buffer head on summary blocks [in, out]
 * @offset: the current byte offset on summary blocks [in, out]
 * @bytes: byte size of the item to be read
 */
static void *nilfs_read_summary_info(struct the_nilfs *nilfs,
				     struct buffer_head **pbh,
				     unsigned int *offset, unsigned int bytes)
{
	void *ptr;
	sector_t blocknr;

	BUG_ON((*pbh)->b_size < *offset);
	if (bytes > (*pbh)->b_size - *offset) {
		blocknr = (*pbh)->b_blocknr;
		brelse(*pbh);
		*pbh = __bread(nilfs->ns_bdev, blocknr + 1,
			       nilfs->ns_blocksize);
		if (unlikely(!*pbh))
			return NULL;
		*offset = 0;
	}
	ptr = (*pbh)->b_data + *offset;
	*offset += bytes;
	return ptr;
}
Exemple #8
0
static int bdev_write_page(struct block_device *bdev, long pos, void *buf)
{
#if 0
	struct buffer_head *bh;
	BUG_ON (pos%PAGE_SIZE);
	bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
	if (!bh || (!bh->b_data)) {
		return -1;
	}
	memcpy(bh->b_data, buf, PAGE_SIZE);	/* FIXME: may need kmap() */
	BUG_ON(!buffer_uptodate(bh));
	generic_make_request(WRITE, bh);
	if (!buffer_uptodate(bh))
		printk(KERN_CRIT "%sWarning %s: Fixing swap signatures unsuccessful...\n", name_resume, resume_file);
	wait_on_buffer(bh);
	brelse(bh);
	return 0;
#endif
	printk(KERN_CRIT "%sWarning %s: Fixing swap signatures unimplemented...\n", name_resume, resume_file);
	return 0;
}
Exemple #9
0
s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read)
{
	FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
	u8 blksize_bits = sb->s_blocksize_bits;
#ifdef CONFIG_SDFAT_DBG_IOCTL
	struct sdfat_sb_info *sbi = SDFAT_SB(sb);
	long flags = sbi->debug_flags;

	if (flags & SDFAT_DEBUGFLAGS_ERROR_RW)	
		return -EIO;
#endif /* CONFIG_SDFAT_DBG_IOCTL */

	if (!fsi->bd_opened) 
		return -EIO;

	brelse(*bh);

	if (read)
		*bh = __bread(sb->s_bdev, secno, num_secs << blksize_bits);
	else
		*bh = __getblk(sb->s_bdev, secno, num_secs << blksize_bits);

	/* read successfully */
	if (*bh)
		return 0;

	/* 
	 * patch 1.2.4 : reset ONCE warning message per volume.
	 */
	if(!(fsi->prev_eio & SDFAT_EIO_READ)) {
		fsi->prev_eio |= SDFAT_EIO_READ;
		sdfat_log_msg(sb, KERN_ERR, "%s: No bh. I/O error.", __func__);
#ifdef CONFIG_SDFAT_DEBUG
		sdfat_debug_warn_on(1);
#endif
	}

	return -EIO;

}
Exemple #10
0
/**
 * nilfs_skip_summary_info - skip items on summary blocks of a log
 * @nilfs: nilfs object
 * @pbh: the current buffer head on summary blocks [in, out]
 * @offset: the current byte offset on summary blocks [in, out]
 * @bytes: byte size of the item to be skipped
 * @count: number of items to be skipped
 */
static void nilfs_skip_summary_info(struct the_nilfs *nilfs,
				    struct buffer_head **pbh,
				    unsigned int *offset, unsigned int bytes,
				    unsigned long count)
{
	unsigned int rest_item_in_current_block
		= ((*pbh)->b_size - *offset) / bytes;

	if (count <= rest_item_in_current_block) {
		*offset += bytes * count;
	} else {
		sector_t blocknr = (*pbh)->b_blocknr;
		unsigned int nitem_per_block = (*pbh)->b_size / bytes;
		unsigned int bcnt;

		count -= rest_item_in_current_block;
		bcnt = DIV_ROUND_UP(count, nitem_per_block);
		*offset = bytes * (count - (bcnt - 1) * nitem_per_block);

		brelse(*pbh);
		*pbh = __bread(nilfs->ns_bdev, blocknr + bcnt,
			       nilfs->ns_blocksize);
	}
}
Exemple #11
0
/**
 * nilfs_scan_dsync_log - get block information of a log written for data sync
 * @nilfs: nilfs object
 * @start_blocknr: start block number of the log
 * @sum: log summary information
 * @head: list head to add nilfs_recovery_block struct
 */
static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr,
				struct nilfs_segment_summary *sum,
				struct list_head *head)
{
	struct buffer_head *bh;
	unsigned int offset;
	u32 nfinfo, sumbytes;
	sector_t blocknr;
	ino_t ino;
	int err = -EIO;

	nfinfo = le32_to_cpu(sum->ss_nfinfo);
	if (!nfinfo)
		return 0;

	sumbytes = le32_to_cpu(sum->ss_sumbytes);
	blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize);
	bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
	if (unlikely(!bh))
		goto out;

	offset = le16_to_cpu(sum->ss_bytes);
	for (;;) {
		unsigned long nblocks, ndatablk, nnodeblk;
		struct nilfs_finfo *finfo;

		finfo = nilfs_read_summary_info(nilfs, &bh, &offset,
						sizeof(*finfo));
		if (unlikely(!finfo))
			goto out;

		ino = le64_to_cpu(finfo->fi_ino);
		nblocks = le32_to_cpu(finfo->fi_nblocks);
		ndatablk = le32_to_cpu(finfo->fi_ndatablk);
		nnodeblk = nblocks - ndatablk;

		while (ndatablk-- > 0) {
			struct nilfs_recovery_block *rb;
			struct nilfs_binfo_v *binfo;

			binfo = nilfs_read_summary_info(nilfs, &bh, &offset,
							sizeof(*binfo));
			if (unlikely(!binfo))
				goto out;

			rb = kmalloc(sizeof(*rb), GFP_NOFS);
			if (unlikely(!rb)) {
				err = -ENOMEM;
				goto out;
			}
			rb->ino = ino;
			rb->blocknr = blocknr++;
			rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr);
			rb->blkoff = le64_to_cpu(binfo->bi_blkoff);
			/* INIT_LIST_HEAD(&rb->list); */
			list_add_tail(&rb->list, head);
		}
		if (--nfinfo == 0)
			break;
		blocknr += nnodeblk; /* always 0 for data sync logs */
		nilfs_skip_summary_info(nilfs, &bh, &offset, sizeof(__le64),
					nnodeblk);
		if (unlikely(!bh))
			goto out;
	}
	err = 0;
 out:
	brelse(bh);   /* brelse(NULL) is just ignored */
	return err;
}
Exemple #12
0
/******************************************************************************
 *
 * axfs_get_sb_block
 *
 * Description:
 *      Populates a axfs_fill_super_info struct after sanity checking the
 *    block device
 *
 * Parameters:
 *    (IN) fs_type - pointer to file_system_type
 *
 *    (IN) flags - mount flags
 *
 *    (IN) dev_name - block device name passed in from mount
 *
 *    (IN) secondary_blk_dev - block device name enter from mount -o
 *
 * Returns:
 *    pointer to a axfs_file_super_info or an error pointer
 *
 *****************************************************************************/
static struct axfs_fill_super_info *axfs_get_sb_block(struct file_system_type *fs_type,
				   int flags, const char *dev_name, char *secondary_blk_dev)
{
	struct nameidata nd;
	struct buffer_head *bh = NULL;
	struct axfs_fill_super_info *output;
	struct block_device *bdev = NULL;
	int err;

	err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
	if (err)
		return ERR_PTR(-EINVAL);

	if (secondary_blk_dev) {
		printk(KERN_ERR "axfs: can't mount 2 block device's \"%s\" and \"%s\"\n", dev_name, secondary_blk_dev);
		err = -EINVAL;
		goto path_out;
	}

	if (!S_ISBLK(nd.path.dentry->d_inode->i_mode)) {
		err = -EINVAL;
		goto path_out;
	}

	if (nd.path.mnt->mnt_flags & MNT_NODEV) {
		err = -EACCES;
		goto path_out;
	}

	bdev = open_bdev_exclusive(dev_name, flags, fs_type);

	if (IS_ERR(bdev)){
		err = PTR_ERR(bdev);
		goto path_out;
	}

	bh = __bread(bdev, 0, bdev->bd_block_size);
	if (!bh) {
		err = -EIO;
		goto out;
	}

	output = (struct axfs_fill_super_info *)vmalloc(sizeof(struct axfs_fill_super_info));
	if(!output) {
		err = -ENOMEM;
		goto out;
	}
	output->onmedia_super_block = (struct axfs_super_onmedia *)vmalloc(sizeof(struct axfs_super_onmedia));
	if(!output->onmedia_super_block) {
		err = -ENOMEM;
		goto out;
	}
	memcpy((char *)output->onmedia_super_block, bh->b_data, sizeof(struct axfs_super_onmedia));

	if(IS_ERR(output)) {
		err = PTR_ERR(output);
		goto out;
	}

	output->physical_start_address = 0;
	output->virtual_start_address = 0;

	path_put(&nd.path);
	close_bdev_exclusive(bdev, flags);
	free_buffer_head(bh);

	return output;

out:
	close_bdev_exclusive(bdev,flags);
	if (bh) {
		free_buffer_head(bh);
	}

path_out:
	path_put(&nd.path);
	printk(KERN_NOTICE "axfs_get_sb_block(): Invalid device \"%s\"\n",
	       dev_name);
	return ERR_PTR(err);
}