OSDN Git Service

fs: Enable bmap() function to properly return errors
authorCarlos Maiolino <cmaiolino@redhat.com>
Thu, 9 Jan 2020 13:30:41 +0000 (14:30 +0100)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 3 Feb 2020 13:05:37 +0000 (08:05 -0500)
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>
drivers/md/md-bitmap.c
fs/f2fs/data.c
fs/inode.c
fs/jbd2/journal.c
include/linux/fs.h
mm/page_io.c

index 3ad1824..92d3b51 100644 (file)
@@ -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;
index a034cd0..e948902 100644 (file)
@@ -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++;
index 96d62d9..5dacfa1 100644 (file)
@@ -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
- *
- *     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.
+ *     @inode:  inode owning the block number being requested
+ *     @block: pointer containing the block to find
+ *
+ *     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
index 5e408ee..01fa5d2 100644 (file)
@@ -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;
index 98e0349..f762e07 100644 (file)
@@ -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);
index 3a198de..76965be 100644 (file)
@@ -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++;