aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dir.c
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-11-13 17:49:17 -0500
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:36:53 -0500
commita22305cc693254a2aa651e797875669112ef8635 (patch)
tree6beabdffc91bec297824f2049293c14bb05daadb /fs/ocfs2/dir.c
parent5e96581a377fc6bd76e9b112da9aeb8a7ae8bf22 (diff)
ocfs2: Wrap dirblock reads in a dedicated function.
We have ocfs2_bread() as a vestige of the original ext-based dir code. It's only used by directories, though. Turn it into ocfs2_read_dir_block(), with a prototype matching the other metadata read functions. It's set up to validate dirblocks when the time comes. Signed-off-by: Joel Becker <joel.becker@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/dir.c')
-rw-r--r--fs/ocfs2/dir.c150
1 files changed, 88 insertions, 62 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 5777045f1a67..c2f3fd93be5c 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -82,49 +82,6 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
82 struct ocfs2_alloc_context *meta_ac, 82 struct ocfs2_alloc_context *meta_ac,
83 struct buffer_head **new_bh); 83 struct buffer_head **new_bh);
84 84
85static struct buffer_head *ocfs2_bread(struct inode *inode,
86 int block, int *err, int reada)
87{
88 struct buffer_head *bh = NULL;
89 int tmperr;
90 u64 p_blkno;
91 int readflags = 0;
92
93 if (reada)
94 readflags |= OCFS2_BH_READAHEAD;
95
96 if (((u64)block << inode->i_sb->s_blocksize_bits) >=
97 i_size_read(inode)) {
98 BUG_ON(!reada);
99 return NULL;
100 }
101
102 down_read(&OCFS2_I(inode)->ip_alloc_sem);
103 tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
104 NULL);
105 up_read(&OCFS2_I(inode)->ip_alloc_sem);
106 if (tmperr < 0) {
107 mlog_errno(tmperr);
108 goto fail;
109 }
110
111 tmperr = ocfs2_read_blocks(inode, p_blkno, 1, &bh, readflags);
112 if (tmperr < 0)
113 goto fail;
114
115 tmperr = 0;
116
117 *err = 0;
118 return bh;
119
120fail:
121 brelse(bh);
122 bh = NULL;
123
124 *err = -EIO;
125 return NULL;
126}
127
128/* 85/*
129 * bh passed here can be an inode block or a dir data block, depending 86 * bh passed here can be an inode block or a dir data block, depending
130 * on the inode inline data flag. 87 * on the inode inline data flag.
@@ -250,6 +207,76 @@ out:
250 return NULL; 207 return NULL;
251} 208}
252 209
210static int ocfs2_validate_dir_block(struct super_block *sb,
211 struct buffer_head *bh)
212{
213 /*
214 * Nothing yet. We don't validate dirents here, that's handled
215 * in-place when the code walks them.
216 */
217
218 return 0;
219}
220
221/*
222 * This function forces all errors to -EIO for consistency with its
223 * predecessor, ocfs2_bread(). We haven't audited what returning the
224 * real error codes would do to callers. We log the real codes with
225 * mlog_errno() before we squash them.
226 */
227static int ocfs2_read_dir_block(struct inode *inode, u64 v_block,
228 struct buffer_head **bh, int flags)
229{
230 int rc = 0;
231 struct buffer_head *tmp = *bh;
232 u64 p_blkno;
233
234 if (((u64)v_block << inode->i_sb->s_blocksize_bits) >=
235 i_size_read(inode)) {
236 BUG_ON(!(flags & OCFS2_BH_READAHEAD));
237 goto out;
238 }
239
240 down_read(&OCFS2_I(inode)->ip_alloc_sem);
241 rc = ocfs2_extent_map_get_blocks(inode, v_block, &p_blkno, NULL,
242 NULL);
243 up_read(&OCFS2_I(inode)->ip_alloc_sem);
244 if (rc) {
245 mlog_errno(rc);
246 goto out;
247 }
248
249 if (!p_blkno) {
250 rc = -EIO;
251 mlog(ML_ERROR,
252 "Directory #%llu contains a hole at offset %llu\n",
253 (unsigned long long)OCFS2_I(inode)->ip_blkno,
254 (unsigned long long)v_block << inode->i_sb->s_blocksize_bits);
255 goto out;
256 }
257
258 rc = ocfs2_read_blocks(inode, p_blkno, 1, &tmp, flags);
259 if (rc) {
260 mlog_errno(rc);
261 goto out;
262 }
263
264 if (!(flags & OCFS2_BH_READAHEAD)) {
265 rc = ocfs2_validate_dir_block(inode->i_sb, tmp);
266 if (rc) {
267 brelse(tmp);
268 goto out;
269 }
270 }
271
272 /* If ocfs2_read_blocks() got us a new bh, pass it up. */
273 if (!*bh)
274 *bh = tmp;
275
276out:
277 return rc ? -EIO : 0;
278}
279
253static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, 280static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
254 struct inode *dir, 281 struct inode *dir,
255 struct ocfs2_dir_entry **res_dir) 282 struct ocfs2_dir_entry **res_dir)
@@ -296,15 +323,17 @@ restart:
296 } 323 }
297 num++; 324 num++;
298 325
299 bh = ocfs2_bread(dir, b++, &err, 1); 326 bh = NULL;
327 err = ocfs2_read_dir_block(dir, b++, &bh,
328 OCFS2_BH_READAHEAD);
300 bh_use[ra_max] = bh; 329 bh_use[ra_max] = bh;
301 } 330 }
302 } 331 }
303 if ((bh = bh_use[ra_ptr++]) == NULL) 332 if ((bh = bh_use[ra_ptr++]) == NULL)
304 goto next; 333 goto next;
305 if (ocfs2_read_block(dir, block, &bh)) { 334 if (ocfs2_read_dir_block(dir, block, &bh, 0)) {
306 /* read error, skip block & hope for the best. 335 /* read error, skip block & hope for the best.
307 * ocfs2_read_block() has released the bh. */ 336 * ocfs2_read_dir_block() has released the bh. */
308 ocfs2_error(dir->i_sb, "reading directory %llu, " 337 ocfs2_error(dir->i_sb, "reading directory %llu, "
309 "offset %lu\n", 338 "offset %lu\n",
310 (unsigned long long)OCFS2_I(dir)->ip_blkno, 339 (unsigned long long)OCFS2_I(dir)->ip_blkno,
@@ -724,7 +753,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
724 int i, stored; 753 int i, stored;
725 struct buffer_head * bh, * tmp; 754 struct buffer_head * bh, * tmp;
726 struct ocfs2_dir_entry * de; 755 struct ocfs2_dir_entry * de;
727 int err;
728 struct super_block * sb = inode->i_sb; 756 struct super_block * sb = inode->i_sb;
729 unsigned int ra_sectors = 16; 757 unsigned int ra_sectors = 16;
730 758
@@ -735,12 +763,8 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
735 763
736 while (!error && !stored && *f_pos < i_size_read(inode)) { 764 while (!error && !stored && *f_pos < i_size_read(inode)) {
737 blk = (*f_pos) >> sb->s_blocksize_bits; 765 blk = (*f_pos) >> sb->s_blocksize_bits;
738 bh = ocfs2_bread(inode, blk, &err, 0); 766 if (ocfs2_read_dir_block(inode, blk, &bh, 0)) {
739 if (!bh) { 767 /* Skip the corrupt dirblock and keep trying */
740 mlog(ML_ERROR,
741 "directory #%llu contains a hole at offset %lld\n",
742 (unsigned long long)OCFS2_I(inode)->ip_blkno,
743 *f_pos);
744 *f_pos += sb->s_blocksize - offset; 768 *f_pos += sb->s_blocksize - offset;
745 continue; 769 continue;
746 } 770 }
@@ -754,8 +778,10 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
754 || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) { 778 || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) {
755 for (i = ra_sectors >> (sb->s_blocksize_bits - 9); 779 for (i = ra_sectors >> (sb->s_blocksize_bits - 9);
756 i > 0; i--) { 780 i > 0; i--) {
757 tmp = ocfs2_bread(inode, ++blk, &err, 1); 781 tmp = NULL;
758 brelse(tmp); 782 if (!ocfs2_read_dir_block(inode, ++blk, &tmp,
783 OCFS2_BH_READAHEAD))
784 brelse(tmp);
759 } 785 }
760 last_ra_blk = blk; 786 last_ra_blk = blk;
761 ra_sectors = 8; 787 ra_sectors = 8;
@@ -828,6 +854,7 @@ revalidate:
828 } 854 }
829 offset = 0; 855 offset = 0;
830 brelse(bh); 856 brelse(bh);
857 bh = NULL;
831 } 858 }
832 859
833 stored = 0; 860 stored = 0;
@@ -1680,8 +1707,8 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
1680 struct super_block *sb = dir->i_sb; 1707 struct super_block *sb = dir->i_sb;
1681 int status; 1708 int status;
1682 1709
1683 bh = ocfs2_bread(dir, 0, &status, 0); 1710 status = ocfs2_read_dir_block(dir, 0, &bh, 0);
1684 if (!bh) { 1711 if (status) {
1685 mlog_errno(status); 1712 mlog_errno(status);
1686 goto bail; 1713 goto bail;
1687 } 1714 }
@@ -1702,11 +1729,10 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
1702 status = -ENOSPC; 1729 status = -ENOSPC;
1703 goto bail; 1730 goto bail;
1704 } 1731 }
1705 bh = ocfs2_bread(dir, 1732 status = ocfs2_read_dir_block(dir,
1706 offset >> sb->s_blocksize_bits, 1733 offset >> sb->s_blocksize_bits,
1707 &status, 1734 &bh, 0);
1708 0); 1735 if (status) {
1709 if (!bh) {
1710 mlog_errno(status); 1736 mlog_errno(status);
1711 goto bail; 1737 goto bail;
1712 } 1738 }