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: Christoph Hellwig <hch@lst.de> Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
c79f46a282
Коммит
30460e1ea3
|
@ -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;
|
||||
|
|
|
@ -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++;
|
||||
|
|
30
fs/inode.c
30
fs/inode.c
|
@ -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
|
||||
|
|
|
@ -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 = bmap(inode, 0);
|
||||
if (!blocknr) {
|
||||
blocknr = 0;
|
||||
err = bmap(inode, &blocknr);
|
||||
|
||||
if (err || !blocknr) {
|
||||
pr_err("%s: Cannot locate journal superblock\n",
|
||||
__func__);
|
||||
return NULL;
|
||||
|
|
|
@ -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);
|
||||
|
|
11
mm/page_io.c
11
mm/page_io.c
|
@ -177,8 +177,9 @@ int generic_swapfile_activate(struct swap_info_struct *sis,
|
|||
|
||||
cond_resched();
|
||||
|
||||
first_block = bmap(inode, probe_block);
|
||||
if (first_block == 0)
|
||||
first_block = probe_block;
|
||||
ret = bmap(inode, &first_block);
|
||||
if (ret || !first_block)
|
||||
goto bad_bmap;
|
||||
|
||||
/*
|
||||
|
@ -193,9 +194,11 @@ int generic_swapfile_activate(struct swap_info_struct *sis,
|
|||
block_in_page++) {
|
||||
sector_t block;
|
||||
|
||||
block = bmap(inode, probe_block + block_in_page);
|
||||
if (block == 0)
|
||||
block = probe_block + block_in_page;
|
||||
ret = bmap(inode, &block);
|
||||
if (ret || !block)
|
||||
goto bad_bmap;
|
||||
|
||||
if (block != first_block + block_in_page) {
|
||||
/* Discontiguity */
|
||||
probe_block++;
|
||||
|
|
Загрузка…
Ссылка в новой задаче