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.c92
1 files changed, 44 insertions, 48 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 2023dc4ea306..d74a52bda540 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -81,9 +81,10 @@
81#define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1) 81#define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
82#define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1)) 82#define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1))
83 83
84typedef int (*leaf_call_t) (struct gfs2_inode *dip, 84typedef int (*leaf_call_t) (struct gfs2_inode *dip, u32 index, u32 len,
85 u32 index, u32 len, u64 leaf_no, 85 u64 leaf_no, void *data);
86 void *data); 86typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
87 const struct qstr *name, void *opaque);
87 88
88 89
89int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, 90int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
@@ -348,17 +349,13 @@ fail:
348 return (copied) ? copied : error; 349 return (copied) ? copied : error;
349} 350}
350 351
351typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
352 const struct qstr *name,
353 void *opaque);
354
355static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent, 352static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent,
356 const struct qstr *name, int ret) 353 const struct qstr *name, int ret)
357{ 354{
358 if (dent->de_inum.no_addr != 0 && 355 if (dent->de_inum.no_addr != 0 &&
359 be32_to_cpu(dent->de_hash) == name->hash && 356 be32_to_cpu(dent->de_hash) == name->hash &&
360 be16_to_cpu(dent->de_name_len) == name->len && 357 be16_to_cpu(dent->de_name_len) == name->len &&
361 memcmp((char *)(dent+1), name->name, name->len) == 0) 358 memcmp(dent+1, name->name, name->len) == 0)
362 return ret; 359 return ret;
363 return 0; 360 return 0;
364} 361}
@@ -483,8 +480,7 @@ wrong_type:
483 return -1; 480 return -1;
484} 481}
485 482
486static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, 483static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf,
487 void *buf,
488 unsigned int len, gfs2_dscan_t scan, 484 unsigned int len, gfs2_dscan_t scan,
489 const struct qstr *name, 485 const struct qstr *name,
490 void *opaque) 486 void *opaque)
@@ -500,7 +496,7 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
500 496
501 offset = ret; 497 offset = ret;
502 prev = NULL; 498 prev = NULL;
503 dent = (struct gfs2_dirent *)(buf + offset); 499 dent = buf + offset;
504 size = be16_to_cpu(dent->de_rec_len); 500 size = be16_to_cpu(dent->de_rec_len);
505 if (gfs2_check_dirent(dent, offset, size, len, 1)) 501 if (gfs2_check_dirent(dent, offset, size, len, 1))
506 goto consist_inode; 502 goto consist_inode;
@@ -512,7 +508,7 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
512 if (offset == len) 508 if (offset == len)
513 break; 509 break;
514 prev = dent; 510 prev = dent;
515 dent = (struct gfs2_dirent *)(buf + offset); 511 dent = buf + offset;
516 size = be16_to_cpu(dent->de_rec_len); 512 size = be16_to_cpu(dent->de_rec_len);
517 if (gfs2_check_dirent(dent, offset, size, len, 0)) 513 if (gfs2_check_dirent(dent, offset, size, len, 0))
518 goto consist_inode; 514 goto consist_inode;
@@ -567,6 +563,24 @@ static int dirent_first(struct gfs2_inode *dip, struct buffer_head *bh,
567 } 563 }
568} 564}
569 565
566static int dirent_check_reclen(struct gfs2_inode *dip,
567 const struct gfs2_dirent *d, const void *end_p)
568{
569 const void *ptr = d;
570 u16 rec_len = be16_to_cpu(d->de_rec_len);
571
572 if (unlikely(rec_len < sizeof(struct gfs2_dirent)))
573 goto broken;
574 ptr += rec_len;
575 if (ptr < end_p)
576 return rec_len;
577 if (ptr == end_p)
578 return -ENOENT;
579broken:
580 gfs2_consist_inode(dip);
581 return -EIO;
582}
583
570/** 584/**
571 * dirent_next - Next dirent 585 * dirent_next - Next dirent
572 * @dip: the directory 586 * @dip: the directory
@@ -579,33 +593,18 @@ static int dirent_first(struct gfs2_inode *dip, struct buffer_head *bh,
579static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh, 593static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh,
580 struct gfs2_dirent **dent) 594 struct gfs2_dirent **dent)
581{ 595{
582 struct gfs2_dirent *tmp, *cur; 596 struct gfs2_dirent *cur = *dent, *tmp;
583 char *bh_end; 597 char *bh_end = bh->b_data + bh->b_size;
584 u16 cur_rec_len; 598 int ret;
585
586 cur = *dent;
587 bh_end = bh->b_data + bh->b_size;
588 cur_rec_len = be16_to_cpu(cur->de_rec_len);
589
590 if ((char *)cur + cur_rec_len >= bh_end) {
591 if ((char *)cur + cur_rec_len > bh_end) {
592 gfs2_consist_inode(dip);
593 return -EIO;
594 }
595 return -ENOENT;
596 }
597
598 tmp = (struct gfs2_dirent *)((char *)cur + cur_rec_len);
599 599
600 if ((char *)tmp + be16_to_cpu(tmp->de_rec_len) > bh_end) { 600 ret = dirent_check_reclen(dip, cur, bh_end);
601 gfs2_consist_inode(dip); 601 if (ret < 0)
602 return -EIO; 602 return ret;
603 }
604 603
605 if (cur_rec_len == 0) { 604 tmp = (void *)cur + ret;
606 gfs2_consist_inode(dip); 605 ret = dirent_check_reclen(dip, tmp, bh_end);
607 return -EIO; 606 if (ret == -EIO)
608 } 607 return ret;
609 608
610 /* Only the first dent could ever have de_inum.no_addr == 0 */ 609 /* Only the first dent could ever have de_inum.no_addr == 0 */
611 if (!tmp->de_inum.no_addr) { 610 if (!tmp->de_inum.no_addr) {
@@ -614,7 +613,6 @@ static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh,
614 } 613 }
615 614
616 *dent = tmp; 615 *dent = tmp;
617
618 return 0; 616 return 0;
619} 617}
620 618
@@ -821,9 +819,9 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
821 gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF); 819 gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
822 leaf = (struct gfs2_leaf *)bh->b_data; 820 leaf = (struct gfs2_leaf *)bh->b_data;
823 leaf->lf_depth = cpu_to_be16(depth); 821 leaf->lf_depth = cpu_to_be16(depth);
824 leaf->lf_entries = cpu_to_be16(0); 822 leaf->lf_entries = 0;
825 leaf->lf_dirent_format = cpu_to_be16(GFS2_FORMAT_DE); 823 leaf->lf_dirent_format = cpu_to_be16(GFS2_FORMAT_DE);
826 leaf->lf_next = cpu_to_be64(0); 824 leaf->lf_next = 0;
827 memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved)); 825 memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved));
828 dent = (struct gfs2_dirent *)(leaf+1); 826 dent = (struct gfs2_dirent *)(leaf+1);
829 gfs2_qstr2dirent(&name, bh->b_size - sizeof(struct gfs2_leaf), dent); 827 gfs2_qstr2dirent(&name, bh->b_size - sizeof(struct gfs2_leaf), dent);
@@ -1152,14 +1150,14 @@ fail:
1152 1150
1153static int compare_dents(const void *a, const void *b) 1151static int compare_dents(const void *a, const void *b)
1154{ 1152{
1155 struct gfs2_dirent *dent_a, *dent_b; 1153 const struct gfs2_dirent *dent_a, *dent_b;
1156 u32 hash_a, hash_b; 1154 u32 hash_a, hash_b;
1157 int ret = 0; 1155 int ret = 0;
1158 1156
1159 dent_a = *(struct gfs2_dirent **)a; 1157 dent_a = *(const struct gfs2_dirent **)a;
1160 hash_a = be32_to_cpu(dent_a->de_hash); 1158 hash_a = be32_to_cpu(dent_a->de_hash);
1161 1159
1162 dent_b = *(struct gfs2_dirent **)b; 1160 dent_b = *(const struct gfs2_dirent **)b;
1163 hash_b = be32_to_cpu(dent_b->de_hash); 1161 hash_b = be32_to_cpu(dent_b->de_hash);
1164 1162
1165 if (hash_a > hash_b) 1163 if (hash_a > hash_b)
@@ -1175,9 +1173,7 @@ static int compare_dents(const void *a, const void *b)
1175 else if (len_a < len_b) 1173 else if (len_a < len_b)
1176 ret = -1; 1174 ret = -1;
1177 else 1175 else
1178 ret = memcmp((char *)(dent_a + 1), 1176 ret = memcmp(dent_a + 1, dent_b + 1, len_a);
1179 (char *)(dent_b + 1),
1180 len_a);
1181 } 1177 }
1182 1178
1183 return ret; 1179 return ret;
@@ -1246,7 +1242,7 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
1246 1242
1247 gfs2_inum_in(&inum, (char *)&dent->de_inum); 1243 gfs2_inum_in(&inum, (char *)&dent->de_inum);
1248 1244
1249 error = filldir(opaque, (char *)(dent + 1), 1245 error = filldir(opaque, (const char *)(dent + 1),
1250 be16_to_cpu(dent->de_name_len), 1246 be16_to_cpu(dent->de_name_len),
1251 off, &inum, 1247 off, &inum,
1252 be16_to_cpu(dent->de_type)); 1248 be16_to_cpu(dent->de_type));
@@ -1298,7 +1294,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
1298 return 0; 1294 return 0;
1299 1295
1300 error = -ENOMEM; 1296 error = -ENOMEM;
1301 larr = vmalloc((leaves + entries) * sizeof(void*)); 1297 larr = vmalloc((leaves + entries) * sizeof(void *));
1302 if (!larr) 1298 if (!larr)
1303 goto out; 1299 goto out;
1304 darr = (const struct gfs2_dirent **)(larr + leaves); 1300 darr = (const struct gfs2_dirent **)(larr + leaves);