aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r--fs/ext4/namei.c361
1 files changed, 194 insertions, 167 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 603e4ebbd0ac..426211882f72 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -53,7 +53,7 @@ static struct buffer_head *ext4_append(handle_t *handle,
53 ext4_lblk_t *block) 53 ext4_lblk_t *block)
54{ 54{
55 struct buffer_head *bh; 55 struct buffer_head *bh;
56 int err = 0; 56 int err;
57 57
58 if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb && 58 if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb &&
59 ((inode->i_size >> 10) >= 59 ((inode->i_size >> 10) >=
@@ -62,9 +62,9 @@ static struct buffer_head *ext4_append(handle_t *handle,
62 62
63 *block = inode->i_size >> inode->i_sb->s_blocksize_bits; 63 *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
64 64
65 bh = ext4_bread(handle, inode, *block, 1, &err); 65 bh = ext4_bread(handle, inode, *block, 1);
66 if (!bh) 66 if (IS_ERR(bh))
67 return ERR_PTR(err); 67 return bh;
68 inode->i_size += inode->i_sb->s_blocksize; 68 inode->i_size += inode->i_sb->s_blocksize;
69 EXT4_I(inode)->i_disksize = inode->i_size; 69 EXT4_I(inode)->i_disksize = inode->i_size;
70 BUFFER_TRACE(bh, "get_write_access"); 70 BUFFER_TRACE(bh, "get_write_access");
@@ -94,20 +94,20 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
94{ 94{
95 struct buffer_head *bh; 95 struct buffer_head *bh;
96 struct ext4_dir_entry *dirent; 96 struct ext4_dir_entry *dirent;
97 int err = 0, is_dx_block = 0; 97 int is_dx_block = 0;
98 98
99 bh = ext4_bread(NULL, inode, block, 0, &err); 99 bh = ext4_bread(NULL, inode, block, 0);
100 if (!bh) { 100 if (IS_ERR(bh)) {
101 if (err == 0) {
102 ext4_error_inode(inode, __func__, line, block,
103 "Directory hole found");
104 return ERR_PTR(-EIO);
105 }
106 __ext4_warning(inode->i_sb, __func__, line, 101 __ext4_warning(inode->i_sb, __func__, line,
107 "error reading directory block " 102 "error %ld reading directory block "
108 "(ino %lu, block %lu)", inode->i_ino, 103 "(ino %lu, block %lu)", PTR_ERR(bh), inode->i_ino,
109 (unsigned long) block); 104 (unsigned long) block);
110 return ERR_PTR(err); 105
106 return bh;
107 }
108 if (!bh) {
109 ext4_error_inode(inode, __func__, line, block, "Directory hole found");
110 return ERR_PTR(-EIO);
111 } 111 }
112 dirent = (struct ext4_dir_entry *) bh->b_data; 112 dirent = (struct ext4_dir_entry *) bh->b_data;
113 /* Determine whether or not we have an index block */ 113 /* Determine whether or not we have an index block */
@@ -124,8 +124,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
124 "directory leaf block found instead of index block"); 124 "directory leaf block found instead of index block");
125 return ERR_PTR(-EIO); 125 return ERR_PTR(-EIO);
126 } 126 }
127 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 127 if (!ext4_has_metadata_csum(inode->i_sb) ||
128 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) ||
129 buffer_verified(bh)) 128 buffer_verified(bh))
130 return bh; 129 return bh;
131 130
@@ -253,8 +252,7 @@ static unsigned dx_node_limit(struct inode *dir);
253static struct dx_frame *dx_probe(const struct qstr *d_name, 252static struct dx_frame *dx_probe(const struct qstr *d_name,
254 struct inode *dir, 253 struct inode *dir,
255 struct dx_hash_info *hinfo, 254 struct dx_hash_info *hinfo,
256 struct dx_frame *frame, 255 struct dx_frame *frame);
257 int *err);
258static void dx_release(struct dx_frame *frames); 256static void dx_release(struct dx_frame *frames);
259static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, 257static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
260 struct dx_hash_info *hinfo, struct dx_map_entry map[]); 258 struct dx_hash_info *hinfo, struct dx_map_entry map[]);
@@ -270,8 +268,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
270 __u32 *start_hash); 268 __u32 *start_hash);
271static struct buffer_head * ext4_dx_find_entry(struct inode *dir, 269static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
272 const struct qstr *d_name, 270 const struct qstr *d_name,
273 struct ext4_dir_entry_2 **res_dir, 271 struct ext4_dir_entry_2 **res_dir);
274 int *err);
275static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, 272static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
276 struct inode *inode); 273 struct inode *inode);
277 274
@@ -340,8 +337,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
340{ 337{
341 struct ext4_dir_entry_tail *t; 338 struct ext4_dir_entry_tail *t;
342 339
343 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 340 if (!ext4_has_metadata_csum(inode->i_sb))
344 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
345 return 1; 341 return 1;
346 342
347 t = get_dirent_tail(inode, dirent); 343 t = get_dirent_tail(inode, dirent);
@@ -362,8 +358,7 @@ static void ext4_dirent_csum_set(struct inode *inode,
362{ 358{
363 struct ext4_dir_entry_tail *t; 359 struct ext4_dir_entry_tail *t;
364 360
365 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 361 if (!ext4_has_metadata_csum(inode->i_sb))
366 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
367 return; 362 return;
368 363
369 t = get_dirent_tail(inode, dirent); 364 t = get_dirent_tail(inode, dirent);
@@ -438,8 +433,7 @@ static int ext4_dx_csum_verify(struct inode *inode,
438 struct dx_tail *t; 433 struct dx_tail *t;
439 int count_offset, limit, count; 434 int count_offset, limit, count;
440 435
441 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 436 if (!ext4_has_metadata_csum(inode->i_sb))
442 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
443 return 1; 437 return 1;
444 438
445 c = get_dx_countlimit(inode, dirent, &count_offset); 439 c = get_dx_countlimit(inode, dirent, &count_offset);
@@ -468,8 +462,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent)
468 struct dx_tail *t; 462 struct dx_tail *t;
469 int count_offset, limit, count; 463 int count_offset, limit, count;
470 464
471 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 465 if (!ext4_has_metadata_csum(inode->i_sb))
472 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
473 return; 466 return;
474 467
475 c = get_dx_countlimit(inode, dirent, &count_offset); 468 c = get_dx_countlimit(inode, dirent, &count_offset);
@@ -557,8 +550,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
557 unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) - 550 unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) -
558 EXT4_DIR_REC_LEN(2) - infosize; 551 EXT4_DIR_REC_LEN(2) - infosize;
559 552
560 if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, 553 if (ext4_has_metadata_csum(dir->i_sb))
561 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
562 entry_space -= sizeof(struct dx_tail); 554 entry_space -= sizeof(struct dx_tail);
563 return entry_space / sizeof(struct dx_entry); 555 return entry_space / sizeof(struct dx_entry);
564} 556}
@@ -567,8 +559,7 @@ static inline unsigned dx_node_limit(struct inode *dir)
567{ 559{
568 unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0); 560 unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0);
569 561
570 if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, 562 if (ext4_has_metadata_csum(dir->i_sb))
571 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
572 entry_space -= sizeof(struct dx_tail); 563 entry_space -= sizeof(struct dx_tail);
573 return entry_space / sizeof(struct dx_entry); 564 return entry_space / sizeof(struct dx_entry);
574} 565}
@@ -641,7 +632,9 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
641 u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; 632 u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
642 struct stats stats; 633 struct stats stats;
643 printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); 634 printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range);
644 if (!(bh = ext4_bread (NULL,dir, block, 0,&err))) continue; 635 bh = ext4_bread(NULL,dir, block, 0);
636 if (!bh || IS_ERR(bh))
637 continue;
645 stats = levels? 638 stats = levels?
646 dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): 639 dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
647 dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0); 640 dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0);
@@ -669,29 +662,25 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
669 */ 662 */
670static struct dx_frame * 663static struct dx_frame *
671dx_probe(const struct qstr *d_name, struct inode *dir, 664dx_probe(const struct qstr *d_name, struct inode *dir,
672 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) 665 struct dx_hash_info *hinfo, struct dx_frame *frame_in)
673{ 666{
674 unsigned count, indirect; 667 unsigned count, indirect;
675 struct dx_entry *at, *entries, *p, *q, *m; 668 struct dx_entry *at, *entries, *p, *q, *m;
676 struct dx_root *root; 669 struct dx_root *root;
677 struct buffer_head *bh;
678 struct dx_frame *frame = frame_in; 670 struct dx_frame *frame = frame_in;
671 struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR);
679 u32 hash; 672 u32 hash;
680 673
681 frame->bh = NULL; 674 frame->bh = ext4_read_dirblock(dir, 0, INDEX);
682 bh = ext4_read_dirblock(dir, 0, INDEX); 675 if (IS_ERR(frame->bh))
683 if (IS_ERR(bh)) { 676 return (struct dx_frame *) frame->bh;
684 *err = PTR_ERR(bh); 677
685 goto fail; 678 root = (struct dx_root *) frame->bh->b_data;
686 }
687 root = (struct dx_root *) bh->b_data;
688 if (root->info.hash_version != DX_HASH_TEA && 679 if (root->info.hash_version != DX_HASH_TEA &&
689 root->info.hash_version != DX_HASH_HALF_MD4 && 680 root->info.hash_version != DX_HASH_HALF_MD4 &&
690 root->info.hash_version != DX_HASH_LEGACY) { 681 root->info.hash_version != DX_HASH_LEGACY) {
691 ext4_warning(dir->i_sb, "Unrecognised inode hash code %d", 682 ext4_warning(dir->i_sb, "Unrecognised inode hash code %d",
692 root->info.hash_version); 683 root->info.hash_version);
693 brelse(bh);
694 *err = ERR_BAD_DX_DIR;
695 goto fail; 684 goto fail;
696 } 685 }
697 hinfo->hash_version = root->info.hash_version; 686 hinfo->hash_version = root->info.hash_version;
@@ -705,16 +694,12 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
705 if (root->info.unused_flags & 1) { 694 if (root->info.unused_flags & 1) {
706 ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x", 695 ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x",
707 root->info.unused_flags); 696 root->info.unused_flags);
708 brelse(bh);
709 *err = ERR_BAD_DX_DIR;
710 goto fail; 697 goto fail;
711 } 698 }
712 699
713 if ((indirect = root->info.indirect_levels) > 1) { 700 if ((indirect = root->info.indirect_levels) > 1) {
714 ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x", 701 ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x",
715 root->info.indirect_levels); 702 root->info.indirect_levels);
716 brelse(bh);
717 *err = ERR_BAD_DX_DIR;
718 goto fail; 703 goto fail;
719 } 704 }
720 705
@@ -724,27 +709,21 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
724 if (dx_get_limit(entries) != dx_root_limit(dir, 709 if (dx_get_limit(entries) != dx_root_limit(dir,
725 root->info.info_length)) { 710 root->info.info_length)) {
726 ext4_warning(dir->i_sb, "dx entry: limit != root limit"); 711 ext4_warning(dir->i_sb, "dx entry: limit != root limit");
727 brelse(bh);
728 *err = ERR_BAD_DX_DIR;
729 goto fail; 712 goto fail;
730 } 713 }
731 714
732 dxtrace(printk("Look up %x", hash)); 715 dxtrace(printk("Look up %x", hash));
733 while (1) 716 while (1) {
734 {
735 count = dx_get_count(entries); 717 count = dx_get_count(entries);
736 if (!count || count > dx_get_limit(entries)) { 718 if (!count || count > dx_get_limit(entries)) {
737 ext4_warning(dir->i_sb, 719 ext4_warning(dir->i_sb,
738 "dx entry: no count or count > limit"); 720 "dx entry: no count or count > limit");
739 brelse(bh); 721 goto fail;
740 *err = ERR_BAD_DX_DIR;
741 goto fail2;
742 } 722 }
743 723
744 p = entries + 1; 724 p = entries + 1;
745 q = entries + count - 1; 725 q = entries + count - 1;
746 while (p <= q) 726 while (p <= q) {
747 {
748 m = p + (q - p)/2; 727 m = p + (q - p)/2;
749 dxtrace(printk(".")); 728 dxtrace(printk("."));
750 if (dx_get_hash(m) > hash) 729 if (dx_get_hash(m) > hash)
@@ -753,8 +732,7 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
753 p = m + 1; 732 p = m + 1;
754 } 733 }
755 734
756 if (0) // linear search cross check 735 if (0) { // linear search cross check
757 {
758 unsigned n = count - 1; 736 unsigned n = count - 1;
759 at = entries; 737 at = entries;
760 while (n--) 738 while (n--)
@@ -771,38 +749,35 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
771 749
772 at = p - 1; 750 at = p - 1;
773 dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); 751 dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
774 frame->bh = bh;
775 frame->entries = entries; 752 frame->entries = entries;
776 frame->at = at; 753 frame->at = at;
777 if (!indirect--) return frame; 754 if (!indirect--)
778 bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX); 755 return frame;
779 if (IS_ERR(bh)) { 756 frame++;
780 *err = PTR_ERR(bh); 757 frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
781 goto fail2; 758 if (IS_ERR(frame->bh)) {
759 ret_err = (struct dx_frame *) frame->bh;
760 frame->bh = NULL;
761 goto fail;
782 } 762 }
783 entries = ((struct dx_node *) bh->b_data)->entries; 763 entries = ((struct dx_node *) frame->bh->b_data)->entries;
784 764
785 if (dx_get_limit(entries) != dx_node_limit (dir)) { 765 if (dx_get_limit(entries) != dx_node_limit (dir)) {
786 ext4_warning(dir->i_sb, 766 ext4_warning(dir->i_sb,
787 "dx entry: limit != node limit"); 767 "dx entry: limit != node limit");
788 brelse(bh); 768 goto fail;
789 *err = ERR_BAD_DX_DIR;
790 goto fail2;
791 } 769 }
792 frame++;
793 frame->bh = NULL;
794 } 770 }
795fail2: 771fail:
796 while (frame >= frame_in) { 772 while (frame >= frame_in) {
797 brelse(frame->bh); 773 brelse(frame->bh);
798 frame--; 774 frame--;
799 } 775 }
800fail: 776 if (ret_err == ERR_PTR(ERR_BAD_DX_DIR))
801 if (*err == ERR_BAD_DX_DIR)
802 ext4_warning(dir->i_sb, 777 ext4_warning(dir->i_sb,
803 "Corrupt dir inode %lu, running e2fsck is " 778 "Corrupt dir inode %lu, running e2fsck is "
804 "recommended.", dir->i_ino); 779 "recommended.", dir->i_ino);
805 return NULL; 780 return ret_err;
806} 781}
807 782
808static void dx_release (struct dx_frame *frames) 783static void dx_release (struct dx_frame *frames)
@@ -988,9 +963,9 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
988 } 963 }
989 hinfo.hash = start_hash; 964 hinfo.hash = start_hash;
990 hinfo.minor_hash = 0; 965 hinfo.minor_hash = 0;
991 frame = dx_probe(NULL, dir, &hinfo, frames, &err); 966 frame = dx_probe(NULL, dir, &hinfo, frames);
992 if (!frame) 967 if (IS_ERR(frame))
993 return err; 968 return PTR_ERR(frame);
994 969
995 /* Add '.' and '..' from the htree header */ 970 /* Add '.' and '..' from the htree header */
996 if (!start_hash && !start_minor_hash) { 971 if (!start_hash && !start_minor_hash) {
@@ -1227,8 +1202,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
1227 buffer */ 1202 buffer */
1228 int num = 0; 1203 int num = 0;
1229 ext4_lblk_t nblocks; 1204 ext4_lblk_t nblocks;
1230 int i, err = 0; 1205 int i, namelen;
1231 int namelen;
1232 1206
1233 *res_dir = NULL; 1207 *res_dir = NULL;
1234 sb = dir->i_sb; 1208 sb = dir->i_sb;
@@ -1258,17 +1232,13 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
1258 goto restart; 1232 goto restart;
1259 } 1233 }
1260 if (is_dx(dir)) { 1234 if (is_dx(dir)) {
1261 bh = ext4_dx_find_entry(dir, d_name, res_dir, &err); 1235 bh = ext4_dx_find_entry(dir, d_name, res_dir);
1262 /* 1236 /*
1263 * On success, or if the error was file not found, 1237 * On success, or if the error was file not found,
1264 * return. Otherwise, fall back to doing a search the 1238 * return. Otherwise, fall back to doing a search the
1265 * old fashioned way. 1239 * old fashioned way.
1266 */ 1240 */
1267 if (err == -ENOENT) 1241 if (!IS_ERR(bh) || PTR_ERR(bh) != ERR_BAD_DX_DIR)
1268 return NULL;
1269 if (err && err != ERR_BAD_DX_DIR)
1270 return ERR_PTR(err);
1271 if (bh)
1272 return bh; 1242 return bh;
1273 dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, " 1243 dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
1274 "falling back\n")); 1244 "falling back\n"));
@@ -1298,10 +1268,10 @@ restart:
1298 break; 1268 break;
1299 } 1269 }
1300 num++; 1270 num++;
1301 bh = ext4_getblk(NULL, dir, b++, 0, &err); 1271 bh = ext4_getblk(NULL, dir, b++, 0);
1302 if (unlikely(err)) { 1272 if (unlikely(IS_ERR(bh))) {
1303 if (ra_max == 0) 1273 if (ra_max == 0)
1304 return ERR_PTR(err); 1274 return bh;
1305 break; 1275 break;
1306 } 1276 }
1307 bh_use[ra_max] = bh; 1277 bh_use[ra_max] = bh;
@@ -1366,7 +1336,7 @@ cleanup_and_exit:
1366} 1336}
1367 1337
1368static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name, 1338static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
1369 struct ext4_dir_entry_2 **res_dir, int *err) 1339 struct ext4_dir_entry_2 **res_dir)
1370{ 1340{
1371 struct super_block * sb = dir->i_sb; 1341 struct super_block * sb = dir->i_sb;
1372 struct dx_hash_info hinfo; 1342 struct dx_hash_info hinfo;
@@ -1375,25 +1345,23 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
1375 ext4_lblk_t block; 1345 ext4_lblk_t block;
1376 int retval; 1346 int retval;
1377 1347
1378 if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err))) 1348 frame = dx_probe(d_name, dir, &hinfo, frames);
1379 return NULL; 1349 if (IS_ERR(frame))
1350 return (struct buffer_head *) frame;
1380 do { 1351 do {
1381 block = dx_get_block(frame->at); 1352 block = dx_get_block(frame->at);
1382 bh = ext4_read_dirblock(dir, block, DIRENT); 1353 bh = ext4_read_dirblock(dir, block, DIRENT);
1383 if (IS_ERR(bh)) { 1354 if (IS_ERR(bh))
1384 *err = PTR_ERR(bh);
1385 goto errout; 1355 goto errout;
1386 } 1356
1387 retval = search_dirblock(bh, dir, d_name, 1357 retval = search_dirblock(bh, dir, d_name,
1388 block << EXT4_BLOCK_SIZE_BITS(sb), 1358 block << EXT4_BLOCK_SIZE_BITS(sb),
1389 res_dir); 1359 res_dir);
1390 if (retval == 1) { /* Success! */ 1360 if (retval == 1)
1391 dx_release(frames); 1361 goto success;
1392 return bh;
1393 }
1394 brelse(bh); 1362 brelse(bh);
1395 if (retval == -1) { 1363 if (retval == -1) {
1396 *err = ERR_BAD_DX_DIR; 1364 bh = ERR_PTR(ERR_BAD_DX_DIR);
1397 goto errout; 1365 goto errout;
1398 } 1366 }
1399 1367
@@ -1402,18 +1370,19 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
1402 frames, NULL); 1370 frames, NULL);
1403 if (retval < 0) { 1371 if (retval < 0) {
1404 ext4_warning(sb, 1372 ext4_warning(sb,
1405 "error reading index page in directory #%lu", 1373 "error %d reading index page in directory #%lu",
1406 dir->i_ino); 1374 retval, dir->i_ino);
1407 *err = retval; 1375 bh = ERR_PTR(retval);
1408 goto errout; 1376 goto errout;
1409 } 1377 }
1410 } while (retval == 1); 1378 } while (retval == 1);
1411 1379
1412 *err = -ENOENT; 1380 bh = NULL;
1413errout: 1381errout:
1414 dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name)); 1382 dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name));
1415 dx_release (frames); 1383success:
1416 return NULL; 1384 dx_release(frames);
1385 return bh;
1417} 1386}
1418 1387
1419static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) 1388static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
@@ -1441,7 +1410,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
1441 dentry); 1410 dentry);
1442 return ERR_PTR(-EIO); 1411 return ERR_PTR(-EIO);
1443 } 1412 }
1444 inode = ext4_iget(dir->i_sb, ino); 1413 inode = ext4_iget_normal(dir->i_sb, ino);
1445 if (inode == ERR_PTR(-ESTALE)) { 1414 if (inode == ERR_PTR(-ESTALE)) {
1446 EXT4_ERROR_INODE(dir, 1415 EXT4_ERROR_INODE(dir,
1447 "deleted inode referenced: %u", 1416 "deleted inode referenced: %u",
@@ -1474,7 +1443,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
1474 return ERR_PTR(-EIO); 1443 return ERR_PTR(-EIO);
1475 } 1444 }
1476 1445
1477 return d_obtain_alias(ext4_iget(child->d_inode->i_sb, ino)); 1446 return d_obtain_alias(ext4_iget_normal(child->d_inode->i_sb, ino));
1478} 1447}
1479 1448
1480/* 1449/*
@@ -1533,7 +1502,7 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
1533 */ 1502 */
1534static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, 1503static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
1535 struct buffer_head **bh,struct dx_frame *frame, 1504 struct buffer_head **bh,struct dx_frame *frame,
1536 struct dx_hash_info *hinfo, int *error) 1505 struct dx_hash_info *hinfo)
1537{ 1506{
1538 unsigned blocksize = dir->i_sb->s_blocksize; 1507 unsigned blocksize = dir->i_sb->s_blocksize;
1539 unsigned count, continued; 1508 unsigned count, continued;
@@ -1548,16 +1517,14 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
1548 int csum_size = 0; 1517 int csum_size = 0;
1549 int err = 0, i; 1518 int err = 0, i;
1550 1519
1551 if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, 1520 if (ext4_has_metadata_csum(dir->i_sb))
1552 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
1553 csum_size = sizeof(struct ext4_dir_entry_tail); 1521 csum_size = sizeof(struct ext4_dir_entry_tail);
1554 1522
1555 bh2 = ext4_append(handle, dir, &newblock); 1523 bh2 = ext4_append(handle, dir, &newblock);
1556 if (IS_ERR(bh2)) { 1524 if (IS_ERR(bh2)) {
1557 brelse(*bh); 1525 brelse(*bh);
1558 *bh = NULL; 1526 *bh = NULL;
1559 *error = PTR_ERR(bh2); 1527 return (struct ext4_dir_entry_2 *) bh2;
1560 return NULL;
1561 } 1528 }
1562 1529
1563 BUFFER_TRACE(*bh, "get_write_access"); 1530 BUFFER_TRACE(*bh, "get_write_access");
@@ -1617,8 +1584,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
1617 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); 1584 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
1618 1585
1619 /* Which block gets the new entry? */ 1586 /* Which block gets the new entry? */
1620 if (hinfo->hash >= hash2) 1587 if (hinfo->hash >= hash2) {
1621 {
1622 swap(*bh, bh2); 1588 swap(*bh, bh2);
1623 de = de2; 1589 de = de2;
1624 } 1590 }
@@ -1638,8 +1604,7 @@ journal_error:
1638 brelse(bh2); 1604 brelse(bh2);
1639 *bh = NULL; 1605 *bh = NULL;
1640 ext4_std_error(dir->i_sb, err); 1606 ext4_std_error(dir->i_sb, err);
1641 *error = err; 1607 return ERR_PTR(err);
1642 return NULL;
1643} 1608}
1644 1609
1645int ext4_find_dest_de(struct inode *dir, struct inode *inode, 1610int ext4_find_dest_de(struct inode *dir, struct inode *inode,
@@ -1718,8 +1683,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
1718 int csum_size = 0; 1683 int csum_size = 0;
1719 int err; 1684 int err;
1720 1685
1721 if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 1686 if (ext4_has_metadata_csum(inode->i_sb))
1722 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
1723 csum_size = sizeof(struct ext4_dir_entry_tail); 1687 csum_size = sizeof(struct ext4_dir_entry_tail);
1724 1688
1725 if (!de) { 1689 if (!de) {
@@ -1786,8 +1750,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1786 struct fake_dirent *fde; 1750 struct fake_dirent *fde;
1787 int csum_size = 0; 1751 int csum_size = 0;
1788 1752
1789 if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 1753 if (ext4_has_metadata_csum(inode->i_sb))
1790 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
1791 csum_size = sizeof(struct ext4_dir_entry_tail); 1754 csum_size = sizeof(struct ext4_dir_entry_tail);
1792 1755
1793 blocksize = dir->i_sb->s_blocksize; 1756 blocksize = dir->i_sb->s_blocksize;
@@ -1853,31 +1816,39 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1853 hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; 1816 hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
1854 hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; 1817 hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
1855 ext4fs_dirhash(name, namelen, &hinfo); 1818 ext4fs_dirhash(name, namelen, &hinfo);
1819 memset(frames, 0, sizeof(frames));
1856 frame = frames; 1820 frame = frames;
1857 frame->entries = entries; 1821 frame->entries = entries;
1858 frame->at = entries; 1822 frame->at = entries;
1859 frame->bh = bh; 1823 frame->bh = bh;
1860 bh = bh2; 1824 bh = bh2;
1861 1825
1862 ext4_handle_dirty_dx_node(handle, dir, frame->bh); 1826 retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
1863 ext4_handle_dirty_dirent_node(handle, dir, bh); 1827 if (retval)
1828 goto out_frames;
1829 retval = ext4_handle_dirty_dirent_node(handle, dir, bh);
1830 if (retval)
1831 goto out_frames;
1864 1832
1865 de = do_split(handle,dir, &bh, frame, &hinfo, &retval); 1833 de = do_split(handle,dir, &bh, frame, &hinfo);
1866 if (!de) { 1834 if (IS_ERR(de)) {
1867 /* 1835 retval = PTR_ERR(de);
1868 * Even if the block split failed, we have to properly write 1836 goto out_frames;
1869 * out all the changes we did so far. Otherwise we can end up
1870 * with corrupted filesystem.
1871 */
1872 ext4_mark_inode_dirty(handle, dir);
1873 dx_release(frames);
1874 return retval;
1875 } 1837 }
1876 dx_release(frames); 1838 dx_release(frames);
1877 1839
1878 retval = add_dirent_to_buf(handle, dentry, inode, de, bh); 1840 retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
1879 brelse(bh); 1841 brelse(bh);
1880 return retval; 1842 return retval;
1843out_frames:
1844 /*
1845 * Even if the block split failed, we have to properly write
1846 * out all the changes we did so far. Otherwise we can end up
1847 * with corrupted filesystem.
1848 */
1849 ext4_mark_inode_dirty(handle, dir);
1850 dx_release(frames);
1851 return retval;
1881} 1852}
1882 1853
1883/* 1854/*
@@ -1904,8 +1875,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
1904 ext4_lblk_t block, blocks; 1875 ext4_lblk_t block, blocks;
1905 int csum_size = 0; 1876 int csum_size = 0;
1906 1877
1907 if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 1878 if (ext4_has_metadata_csum(inode->i_sb))
1908 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
1909 csum_size = sizeof(struct ext4_dir_entry_tail); 1879 csum_size = sizeof(struct ext4_dir_entry_tail);
1910 1880
1911 sb = dir->i_sb; 1881 sb = dir->i_sb;
@@ -1982,9 +1952,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
1982 struct ext4_dir_entry_2 *de; 1952 struct ext4_dir_entry_2 *de;
1983 int err; 1953 int err;
1984 1954
1985 frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err); 1955 frame = dx_probe(&dentry->d_name, dir, &hinfo, frames);
1986 if (!frame) 1956 if (IS_ERR(frame))
1987 return err; 1957 return PTR_ERR(frame);
1988 entries = frame->entries; 1958 entries = frame->entries;
1989 at = frame->at; 1959 at = frame->at;
1990 bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT); 1960 bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
@@ -2095,9 +2065,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
2095 goto cleanup; 2065 goto cleanup;
2096 } 2066 }
2097 } 2067 }
2098 de = do_split(handle, dir, &bh, frame, &hinfo, &err); 2068 de = do_split(handle, dir, &bh, frame, &hinfo);
2099 if (!de) 2069 if (IS_ERR(de)) {
2070 err = PTR_ERR(de);
2100 goto cleanup; 2071 goto cleanup;
2072 }
2101 err = add_dirent_to_buf(handle, dentry, inode, de, bh); 2073 err = add_dirent_to_buf(handle, dentry, inode, de, bh);
2102 goto cleanup; 2074 goto cleanup;
2103 2075
@@ -2167,8 +2139,7 @@ static int ext4_delete_entry(handle_t *handle,
2167 return err; 2139 return err;
2168 } 2140 }
2169 2141
2170 if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, 2142 if (ext4_has_metadata_csum(dir->i_sb))
2171 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
2172 csum_size = sizeof(struct ext4_dir_entry_tail); 2143 csum_size = sizeof(struct ext4_dir_entry_tail);
2173 2144
2174 BUFFER_TRACE(bh, "get_write_access"); 2145 BUFFER_TRACE(bh, "get_write_access");
@@ -2387,8 +2358,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
2387 int csum_size = 0; 2358 int csum_size = 0;
2388 int err; 2359 int err;
2389 2360
2390 if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, 2361 if (ext4_has_metadata_csum(dir->i_sb))
2391 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
2392 csum_size = sizeof(struct ext4_dir_entry_tail); 2362 csum_size = sizeof(struct ext4_dir_entry_tail);
2393 2363
2394 if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { 2364 if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@@ -2403,10 +2373,6 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
2403 dir_block = ext4_append(handle, inode, &block); 2373 dir_block = ext4_append(handle, inode, &block);
2404 if (IS_ERR(dir_block)) 2374 if (IS_ERR(dir_block))
2405 return PTR_ERR(dir_block); 2375 return PTR_ERR(dir_block);
2406 BUFFER_TRACE(dir_block, "get_write_access");
2407 err = ext4_journal_get_write_access(handle, dir_block);
2408 if (err)
2409 goto out;
2410 de = (struct ext4_dir_entry_2 *)dir_block->b_data; 2376 de = (struct ext4_dir_entry_2 *)dir_block->b_data;
2411 ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0); 2377 ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0);
2412 set_nlink(inode, 2); 2378 set_nlink(inode, 2);
@@ -2573,7 +2539,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
2573 int err = 0, rc; 2539 int err = 0, rc;
2574 bool dirty = false; 2540 bool dirty = false;
2575 2541
2576 if (!sbi->s_journal) 2542 if (!sbi->s_journal || is_bad_inode(inode))
2577 return 0; 2543 return 0;
2578 2544
2579 WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) && 2545 WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
@@ -3190,6 +3156,39 @@ static void ext4_update_dir_count(handle_t *handle, struct ext4_renament *ent)
3190 } 3156 }
3191} 3157}
3192 3158
3159static struct inode *ext4_whiteout_for_rename(struct ext4_renament *ent,
3160 int credits, handle_t **h)
3161{
3162 struct inode *wh;
3163 handle_t *handle;
3164 int retries = 0;
3165
3166 /*
3167 * for inode block, sb block, group summaries,
3168 * and inode bitmap
3169 */
3170 credits += (EXT4_MAXQUOTAS_TRANS_BLOCKS(ent->dir->i_sb) +
3171 EXT4_XATTR_TRANS_BLOCKS + 4);
3172retry:
3173 wh = ext4_new_inode_start_handle(ent->dir, S_IFCHR | WHITEOUT_MODE,
3174 &ent->dentry->d_name, 0, NULL,
3175 EXT4_HT_DIR, credits);
3176
3177 handle = ext4_journal_current_handle();
3178 if (IS_ERR(wh)) {
3179 if (handle)
3180 ext4_journal_stop(handle);
3181 if (PTR_ERR(wh) == -ENOSPC &&
3182 ext4_should_retry_alloc(ent->dir->i_sb, &retries))
3183 goto retry;
3184 } else {
3185 *h = handle;
3186 init_special_inode(wh, wh->i_mode, WHITEOUT_DEV);
3187 wh->i_op = &ext4_special_inode_operations;
3188 }
3189 return wh;
3190}
3191
3193/* 3192/*
3194 * Anybody can rename anything with this: the permission checks are left to the 3193 * Anybody can rename anything with this: the permission checks are left to the
3195 * higher-level routines. 3194 * higher-level routines.
@@ -3199,7 +3198,8 @@ static void ext4_update_dir_count(handle_t *handle, struct ext4_renament *ent)
3199 * This comes from rename(const char *oldpath, const char *newpath) 3198 * This comes from rename(const char *oldpath, const char *newpath)
3200 */ 3199 */
3201static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, 3200static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3202 struct inode *new_dir, struct dentry *new_dentry) 3201 struct inode *new_dir, struct dentry *new_dentry,
3202 unsigned int flags)
3203{ 3203{
3204 handle_t *handle = NULL; 3204 handle_t *handle = NULL;
3205 struct ext4_renament old = { 3205 struct ext4_renament old = {
@@ -3214,6 +3214,9 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3214 }; 3214 };
3215 int force_reread; 3215 int force_reread;
3216 int retval; 3216 int retval;
3217 struct inode *whiteout = NULL;
3218 int credits;
3219 u8 old_file_type;
3217 3220
3218 dquot_initialize(old.dir); 3221 dquot_initialize(old.dir);
3219 dquot_initialize(new.dir); 3222 dquot_initialize(new.dir);
@@ -3252,11 +3255,17 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3252 if (new.inode && !test_opt(new.dir->i_sb, NO_AUTO_DA_ALLOC)) 3255 if (new.inode && !test_opt(new.dir->i_sb, NO_AUTO_DA_ALLOC))
3253 ext4_alloc_da_blocks(old.inode); 3256 ext4_alloc_da_blocks(old.inode);
3254 3257
3255 handle = ext4_journal_start(old.dir, EXT4_HT_DIR, 3258 credits = (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) +
3256 (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) + 3259 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2);
3257 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2)); 3260 if (!(flags & RENAME_WHITEOUT)) {
3258 if (IS_ERR(handle)) 3261 handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits);
3259 return PTR_ERR(handle); 3262 if (IS_ERR(handle))
3263 return PTR_ERR(handle);
3264 } else {
3265 whiteout = ext4_whiteout_for_rename(&old, credits, &handle);
3266 if (IS_ERR(whiteout))
3267 return PTR_ERR(whiteout);
3268 }
3260 3269
3261 if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir)) 3270 if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir))
3262 ext4_handle_sync(handle); 3271 ext4_handle_sync(handle);
@@ -3284,13 +3293,26 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3284 */ 3293 */
3285 force_reread = (new.dir->i_ino == old.dir->i_ino && 3294 force_reread = (new.dir->i_ino == old.dir->i_ino &&
3286 ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA)); 3295 ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA));
3296
3297 old_file_type = old.de->file_type;
3298 if (whiteout) {
3299 /*
3300 * Do this before adding a new entry, so the old entry is sure
3301 * to be still pointing to the valid old entry.
3302 */
3303 retval = ext4_setent(handle, &old, whiteout->i_ino,
3304 EXT4_FT_CHRDEV);
3305 if (retval)
3306 goto end_rename;
3307 ext4_mark_inode_dirty(handle, whiteout);
3308 }
3287 if (!new.bh) { 3309 if (!new.bh) {
3288 retval = ext4_add_entry(handle, new.dentry, old.inode); 3310 retval = ext4_add_entry(handle, new.dentry, old.inode);
3289 if (retval) 3311 if (retval)
3290 goto end_rename; 3312 goto end_rename;
3291 } else { 3313 } else {
3292 retval = ext4_setent(handle, &new, 3314 retval = ext4_setent(handle, &new,
3293 old.inode->i_ino, old.de->file_type); 3315 old.inode->i_ino, old_file_type);
3294 if (retval) 3316 if (retval)
3295 goto end_rename; 3317 goto end_rename;
3296 } 3318 }
@@ -3305,10 +3327,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3305 old.inode->i_ctime = ext4_current_time(old.inode); 3327 old.inode->i_ctime = ext4_current_time(old.inode);
3306 ext4_mark_inode_dirty(handle, old.inode); 3328 ext4_mark_inode_dirty(handle, old.inode);
3307 3329
3308 /* 3330 if (!whiteout) {
3309 * ok, that's it 3331 /*
3310 */ 3332 * ok, that's it
3311 ext4_rename_delete(handle, &old, force_reread); 3333 */
3334 ext4_rename_delete(handle, &old, force_reread);
3335 }
3312 3336
3313 if (new.inode) { 3337 if (new.inode) {
3314 ext4_dec_count(handle, new.inode); 3338 ext4_dec_count(handle, new.inode);
@@ -3344,6 +3368,12 @@ end_rename:
3344 brelse(old.dir_bh); 3368 brelse(old.dir_bh);
3345 brelse(old.bh); 3369 brelse(old.bh);
3346 brelse(new.bh); 3370 brelse(new.bh);
3371 if (whiteout) {
3372 if (retval)
3373 drop_nlink(whiteout);
3374 unlock_new_inode(whiteout);
3375 iput(whiteout);
3376 }
3347 if (handle) 3377 if (handle)
3348 ext4_journal_stop(handle); 3378 ext4_journal_stop(handle);
3349 return retval; 3379 return retval;
@@ -3476,18 +3506,15 @@ static int ext4_rename2(struct inode *old_dir, struct dentry *old_dentry,
3476 struct inode *new_dir, struct dentry *new_dentry, 3506 struct inode *new_dir, struct dentry *new_dentry,
3477 unsigned int flags) 3507 unsigned int flags)
3478{ 3508{
3479 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) 3509 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
3480 return -EINVAL; 3510 return -EINVAL;
3481 3511
3482 if (flags & RENAME_EXCHANGE) { 3512 if (flags & RENAME_EXCHANGE) {
3483 return ext4_cross_rename(old_dir, old_dentry, 3513 return ext4_cross_rename(old_dir, old_dentry,
3484 new_dir, new_dentry); 3514 new_dir, new_dentry);
3485 } 3515 }
3486 /* 3516
3487 * Existence checking was done by the VFS, otherwise "RENAME_NOREPLACE" 3517 return ext4_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
3488 * is equivalent to regular rename.
3489 */
3490 return ext4_rename(old_dir, old_dentry, new_dir, new_dentry);
3491} 3518}
3492 3519
3493/* 3520/*