aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/dir.c')
-rw-r--r--fs/gfs2/dir.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 82a1ac7895a2..a96fa07b3f3b 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1262,9 +1262,10 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
1262 u64 leaf_no) 1262 u64 leaf_no)
1263{ 1263{
1264 struct gfs2_inode *ip = GFS2_I(inode); 1264 struct gfs2_inode *ip = GFS2_I(inode);
1265 struct gfs2_sbd *sdp = GFS2_SB(inode);
1265 struct buffer_head *bh; 1266 struct buffer_head *bh;
1266 struct gfs2_leaf *lf; 1267 struct gfs2_leaf *lf;
1267 unsigned entries = 0; 1268 unsigned entries = 0, entries2 = 0;
1268 unsigned leaves = 0; 1269 unsigned leaves = 0;
1269 const struct gfs2_dirent **darr, *dent; 1270 const struct gfs2_dirent **darr, *dent;
1270 struct dirent_gather g; 1271 struct dirent_gather g;
@@ -1290,7 +1291,13 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
1290 return 0; 1291 return 0;
1291 1292
1292 error = -ENOMEM; 1293 error = -ENOMEM;
1293 larr = vmalloc((leaves + entries) * sizeof(void *)); 1294 /*
1295 * The extra 99 entries are not normally used, but are a buffer
1296 * zone in case the number of entries in the leaf is corrupt.
1297 * 99 is the maximum number of entries that can fit in a single
1298 * leaf block.
1299 */
1300 larr = vmalloc((leaves + entries + 99) * sizeof(void *));
1294 if (!larr) 1301 if (!larr)
1295 goto out; 1302 goto out;
1296 darr = (const struct gfs2_dirent **)(larr + leaves); 1303 darr = (const struct gfs2_dirent **)(larr + leaves);
@@ -1305,10 +1312,20 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
1305 lf = (struct gfs2_leaf *)bh->b_data; 1312 lf = (struct gfs2_leaf *)bh->b_data;
1306 lfn = be64_to_cpu(lf->lf_next); 1313 lfn = be64_to_cpu(lf->lf_next);
1307 if (lf->lf_entries) { 1314 if (lf->lf_entries) {
1315 entries2 += be16_to_cpu(lf->lf_entries);
1308 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, 1316 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
1309 gfs2_dirent_gather, NULL, &g); 1317 gfs2_dirent_gather, NULL, &g);
1310 error = PTR_ERR(dent); 1318 error = PTR_ERR(dent);
1311 if (IS_ERR(dent)) { 1319 if (IS_ERR(dent))
1320 goto out_kfree;
1321 if (entries2 != g.offset) {
1322 fs_warn(sdp, "Number of entries corrupt in dir "
1323 "leaf %llu, entries2 (%u) != "
1324 "g.offset (%u)\n",
1325 (unsigned long long)bh->b_blocknr,
1326 entries2, g.offset);
1327
1328 error = -EIO;
1312 goto out_kfree; 1329 goto out_kfree;
1313 } 1330 }
1314 error = 0; 1331 error = 0;
@@ -1318,6 +1335,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
1318 } 1335 }
1319 } while(lfn); 1336 } while(lfn);
1320 1337
1338 BUG_ON(entries2 != entries);
1321 error = do_filldir_main(ip, offset, opaque, filldir, darr, 1339 error = do_filldir_main(ip, offset, opaque, filldir, darr,
1322 entries, copied); 1340 entries, copied);
1323out_kfree: 1341out_kfree:
@@ -1401,6 +1419,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
1401 filldir_t filldir) 1419 filldir_t filldir)
1402{ 1420{
1403 struct gfs2_inode *dip = GFS2_I(inode); 1421 struct gfs2_inode *dip = GFS2_I(inode);
1422 struct gfs2_sbd *sdp = GFS2_SB(inode);
1404 struct dirent_gather g; 1423 struct dirent_gather g;
1405 const struct gfs2_dirent **darr, *dent; 1424 const struct gfs2_dirent **darr, *dent;
1406 struct buffer_head *dibh; 1425 struct buffer_head *dibh;
@@ -1423,8 +1442,8 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
1423 return error; 1442 return error;
1424 1443
1425 error = -ENOMEM; 1444 error = -ENOMEM;
1426 darr = kmalloc(dip->i_di.di_entries * sizeof(struct gfs2_dirent *), 1445 /* 96 is max number of dirents which can be stuffed into an inode */
1427 GFP_KERNEL); 1446 darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_KERNEL);
1428 if (darr) { 1447 if (darr) {
1429 g.pdent = darr; 1448 g.pdent = darr;
1430 g.offset = 0; 1449 g.offset = 0;
@@ -1434,6 +1453,15 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
1434 error = PTR_ERR(dent); 1453 error = PTR_ERR(dent);
1435 goto out; 1454 goto out;
1436 } 1455 }
1456 if (dip->i_di.di_entries != g.offset) {
1457 fs_warn(sdp, "Number of entries corrupt in dir %llu, "
1458 "ip->i_di.di_entries (%u) != g.offset (%u)\n",
1459 (unsigned long long)dip->i_num.no_addr,
1460 dip->i_di.di_entries,
1461 g.offset);
1462 error = -EIO;
1463 goto out;
1464 }
1437 error = do_filldir_main(dip, offset, opaque, filldir, darr, 1465 error = do_filldir_main(dip, offset, opaque, filldir, darr,
1438 dip->i_di.di_entries, &copied); 1466 dip->i_di.di_entries, &copied);
1439out: 1467out: