Commit 30460e1e authored by Carlos Maiolino's avatar Carlos Maiolino Committed by Al Viro
Browse files

fs: Enable bmap() function to properly return errors



By now, bmap() will either return the physical block number related to
the requested file offset or 0 in case of error or the requested offset
maps into a hole.
This patch makes the needed changes to enable bmap() to proper return
errors, using the return value as an error return, and now, a pointer
must be passed to bmap() to be filled with the mapped physical block.

It will change the behavior of bmap() on return:

- negative value in case of error
- zero on success or map fell into a hole

In case of a hole, the *block will be zero too

Since this is a prep patch, by now, the only error return is -EINVAL if
->bmap doesn't exist.

Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarCarlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c79f46a2
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -364,7 +364,7 @@ static int read_page(struct file *file, unsigned long index,
	int ret = 0;
	struct inode *inode = file_inode(file);
	struct buffer_head *bh;
	sector_t block;
	sector_t block, blk_cur;

	pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
		 (unsigned long long)index << PAGE_SHIFT);
@@ -375,17 +375,21 @@ static int read_page(struct file *file, unsigned long index,
		goto out;
	}
	attach_page_buffers(page, bh);
	block = index << (PAGE_SHIFT - inode->i_blkbits);
	blk_cur = index << (PAGE_SHIFT - inode->i_blkbits);
	while (bh) {
		block = blk_cur;

		if (count == 0)
			bh->b_blocknr = 0;
		else {
			bh->b_blocknr = bmap(inode, block);
			if (bh->b_blocknr == 0) {
				/* Cannot use this file! */
			ret = bmap(inode, &block);
			if (ret || !block) {
				ret = -EINVAL;
				bh->b_blocknr = 0;
				goto out;
			}

			bh->b_blocknr = block;
			bh->b_bdev = inode->i_sb->s_bdev;
			if (count < (1<<inode->i_blkbits))
				count = 0;
@@ -399,7 +403,7 @@ static int read_page(struct file *file, unsigned long index,
			set_buffer_mapped(bh);
			submit_bh(REQ_OP_READ, 0, bh);
		}
		block++;
		blk_cur++;
		bh = bh->b_this_page;
	}
	page->index = index;
+11 −5
Original line number Diff line number Diff line
@@ -3170,12 +3170,16 @@ static int check_swap_activate(struct file *swap_file, unsigned int max)
	while ((probe_block + blocks_per_page) <= last_block && page_no < max) {
		unsigned block_in_page;
		sector_t first_block;
		sector_t block = 0;
		int	 err = 0;

		cond_resched();

		first_block = bmap(inode, probe_block);
		if (first_block == 0)
		block = probe_block;
		err = bmap(inode, &block);
		if (err || !block)
			goto bad_bmap;
		first_block = block;

		/*
		 * It must be PAGE_SIZE aligned on-disk
@@ -3187,11 +3191,13 @@ static int check_swap_activate(struct file *swap_file, unsigned int max)

		for (block_in_page = 1; block_in_page < blocks_per_page;
					block_in_page++) {
			sector_t block;

			block = bmap(inode, probe_block + block_in_page);
			if (block == 0)
			block = probe_block + block_in_page;
			err = bmap(inode, &block);

			if (err || !block)
				goto bad_bmap;

			if (block != first_block + block_in_page) {
				/* Discontiguity */
				probe_block++;
+19 −13
Original line number Diff line number Diff line
@@ -1598,25 +1598,31 @@ retry:
}
EXPORT_SYMBOL(iput);

#ifdef CONFIG_BLOCK
/**
 *	bmap	- find a block number in a file
 *	@inode: inode of file
 *	@block: block to find
 *	@inode:  inode owning the block number being requested
 *	@block: pointer containing the block to find
 *
 *	Returns the block number on the device holding the inode that
 *	is the disk block number for the block of the file requested.
 *	That is, asked for block 4 of inode 1 the function will return the
 *	disk block relative to the disk start that holds that block of the
 *	file.
 *	Replaces the value in *block with the block number on the device holding
 *	corresponding to the requested block number in the file.
 *	That is, asked for block 4 of inode 1 the function will replace the
 *	4 in *block, with disk block relative to the disk start that holds that
 *	block of the file.
 *
 *	Returns -EINVAL in case of error, 0 otherwise. If mapping falls into a
 *	hole, returns 0 and *block is also set to 0.
 */
sector_t bmap(struct inode *inode, sector_t block)
int bmap(struct inode *inode, sector_t *block)
{
	sector_t res = 0;
	if (inode->i_mapping->a_ops->bmap)
		res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
	return res;
	if (!inode->i_mapping->a_ops->bmap)
		return -EINVAL;

	*block = inode->i_mapping->a_ops->bmap(inode->i_mapping, *block);
	return 0;
}
EXPORT_SYMBOL(bmap);
#endif

/*
 * With relative atime, only update atime if the previous atime is
+15 −7
Original line number Diff line number Diff line
@@ -795,18 +795,23 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
{
	int err = 0;
	unsigned long long ret;
	sector_t block = 0;

	if (journal->j_inode) {
		ret = bmap(journal->j_inode, blocknr);
		if (ret)
			*retp = ret;
		else {
		block = blocknr;
		ret = bmap(journal->j_inode, &block);

		if (ret || !block) {
			printk(KERN_ALERT "%s: journal block not found "
					"at offset %lu on %s\n",
			       __func__, blocknr, journal->j_devname);
			err = -EIO;
			__journal_abort_soft(journal, err);

		} else {
			*retp = block;
		}

	} else {
		*retp = blocknr; /* +journal->j_blk_offset */
	}
@@ -1244,11 +1249,14 @@ journal_t *jbd2_journal_init_dev(struct block_device *bdev,
journal_t *jbd2_journal_init_inode(struct inode *inode)
{
	journal_t *journal;
	sector_t blocknr;
	char *p;
	unsigned long long blocknr;
	int err = 0;

	blocknr = 0;
	err = bmap(inode, &blocknr);

	blocknr = bmap(inode, 0);
	if (!blocknr) {
	if (err || !blocknr) {
		pr_err("%s: Cannot locate journal superblock\n",
			__func__);
		return NULL;
+8 −1
Original line number Diff line number Diff line
@@ -2865,9 +2865,16 @@ static inline ssize_t generic_write_sync(struct kiocb *iocb, ssize_t count)

extern void emergency_sync(void);
extern void emergency_remount(void);

#ifdef CONFIG_BLOCK
extern sector_t bmap(struct inode *, sector_t);
extern int bmap(struct inode *inode, sector_t *block);
#else
static inline int bmap(struct inode *inode,  sector_t *block)
{
	return -EINVAL;
}
#endif

extern int notify_change(struct dentry *, struct iattr *, struct inode **);
extern int inode_permission(struct inode *, int);
extern int generic_permission(struct inode *, int);
Loading