| From 1175c3acd51544b831e77a3459d07086ba04745d Mon Sep 17 00:00:00 2001 |
| From: "Darrick J. Wong" <darrick.wong@oracle.com> |
| Date: Thu, 2 Feb 2017 15:13:58 -0800 |
| Subject: [PATCH] xfs: fail _dir_open when readahead fails |
| |
| commit 7a652bbe366464267190c2792a32ce4fff5595ef upstream. |
| |
| When we open a directory, we try to readahead block 0 of the directory |
| on the assumption that we're going to need it soon. If the bmbt is |
| corrupt, the directory will never be usable and the readahead fails |
| immediately, so we might as well prevent the directory from being opened |
| at all. This prevents a subsequent read or modify operation from |
| hitting it and taking the fs offline. |
| |
| NOTE: We're only checking for early failures in the block mapping, not |
| the readahead directory block itself. |
| |
| Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> |
| Reviewed-by: Eric Sandeen <sandeen@redhat.com> |
| Reviewed-by: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c |
| index f2dc1a950c85..1bdf2888295b 100644 |
| --- a/fs/xfs/libxfs/xfs_da_btree.c |
| +++ b/fs/xfs/libxfs/xfs_da_btree.c |
| @@ -2633,7 +2633,7 @@ out_free: |
| /* |
| * Readahead the dir/attr block. |
| */ |
| -xfs_daddr_t |
| +int |
| xfs_da_reada_buf( |
| struct xfs_inode *dp, |
| xfs_dablk_t bno, |
| @@ -2664,7 +2664,5 @@ out_free: |
| if (mapp != &map) |
| kmem_free(mapp); |
| |
| - if (error) |
| - return -1; |
| - return mappedbno; |
| + return error; |
| } |
| diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h |
| index 98c75cbe6ac2..4e29cb6a3627 100644 |
| --- a/fs/xfs/libxfs/xfs_da_btree.h |
| +++ b/fs/xfs/libxfs/xfs_da_btree.h |
| @@ -201,7 +201,7 @@ int xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp, |
| xfs_dablk_t bno, xfs_daddr_t mappedbno, |
| struct xfs_buf **bpp, int whichfork, |
| const struct xfs_buf_ops *ops); |
| -xfs_daddr_t xfs_da_reada_buf(struct xfs_inode *dp, xfs_dablk_t bno, |
| +int xfs_da_reada_buf(struct xfs_inode *dp, xfs_dablk_t bno, |
| xfs_daddr_t mapped_bno, int whichfork, |
| const struct xfs_buf_ops *ops); |
| int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, |
| diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c |
| index e612a0233710..ad02b0ed671f 100644 |
| --- a/fs/xfs/xfs_file.c |
| +++ b/fs/xfs/xfs_file.c |
| @@ -1035,9 +1035,9 @@ xfs_dir_open( |
| */ |
| mode = xfs_ilock_data_map_shared(ip); |
| if (ip->i_d.di_nextents > 0) |
| - xfs_dir3_data_readahead(ip, 0, -1); |
| + error = xfs_dir3_data_readahead(ip, 0, -1); |
| xfs_iunlock(ip, mode); |
| - return 0; |
| + return error; |
| } |
| |
| STATIC int |
| -- |
| 2.12.0 |
| |