diff options
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/acl.c | 17 | ||||
-rw-r--r-- | fs/ext3/acl.h | 2 | ||||
-rw-r--r-- | fs/ext3/balloc.c | 135 | ||||
-rw-r--r-- | fs/ext3/file.c | 4 | ||||
-rw-r--r-- | fs/ext3/inode.c | 7 | ||||
-rw-r--r-- | fs/ext3/namei.c | 37 | ||||
-rw-r--r-- | fs/ext3/super.c | 58 | ||||
-rw-r--r-- | fs/ext3/xattr.c | 2 |
8 files changed, 136 insertions, 126 deletions
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index 638c13a26c03..3ac38266fc9e 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c | |||
@@ -393,7 +393,8 @@ ext3_acl_chmod(struct inode *inode) | |||
393 | int retries = 0; | 393 | int retries = 0; |
394 | 394 | ||
395 | retry: | 395 | retry: |
396 | handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); | 396 | handle = ext3_journal_start(inode, |
397 | EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); | ||
397 | if (IS_ERR(handle)) { | 398 | if (IS_ERR(handle)) { |
398 | error = PTR_ERR(handle); | 399 | error = PTR_ERR(handle); |
399 | ext3_std_error(inode->i_sb, error); | 400 | ext3_std_error(inode->i_sb, error); |
@@ -417,12 +418,12 @@ static size_t | |||
417 | ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len, | 418 | ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len, |
418 | const char *name, size_t name_len) | 419 | const char *name, size_t name_len) |
419 | { | 420 | { |
420 | const size_t size = sizeof(XATTR_NAME_ACL_ACCESS); | 421 | const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); |
421 | 422 | ||
422 | if (!test_opt(inode->i_sb, POSIX_ACL)) | 423 | if (!test_opt(inode->i_sb, POSIX_ACL)) |
423 | return 0; | 424 | return 0; |
424 | if (list && size <= list_len) | 425 | if (list && size <= list_len) |
425 | memcpy(list, XATTR_NAME_ACL_ACCESS, size); | 426 | memcpy(list, POSIX_ACL_XATTR_ACCESS, size); |
426 | return size; | 427 | return size; |
427 | } | 428 | } |
428 | 429 | ||
@@ -430,12 +431,12 @@ static size_t | |||
430 | ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len, | 431 | ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len, |
431 | const char *name, size_t name_len) | 432 | const char *name, size_t name_len) |
432 | { | 433 | { |
433 | const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT); | 434 | const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); |
434 | 435 | ||
435 | if (!test_opt(inode->i_sb, POSIX_ACL)) | 436 | if (!test_opt(inode->i_sb, POSIX_ACL)) |
436 | return 0; | 437 | return 0; |
437 | if (list && size <= list_len) | 438 | if (list && size <= list_len) |
438 | memcpy(list, XATTR_NAME_ACL_DEFAULT, size); | 439 | memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); |
439 | return size; | 440 | return size; |
440 | } | 441 | } |
441 | 442 | ||
@@ -503,7 +504,7 @@ ext3_xattr_set_acl(struct inode *inode, int type, const void *value, | |||
503 | acl = NULL; | 504 | acl = NULL; |
504 | 505 | ||
505 | retry: | 506 | retry: |
506 | handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); | 507 | handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); |
507 | if (IS_ERR(handle)) | 508 | if (IS_ERR(handle)) |
508 | return PTR_ERR(handle); | 509 | return PTR_ERR(handle); |
509 | error = ext3_set_acl(handle, inode, type, acl); | 510 | error = ext3_set_acl(handle, inode, type, acl); |
@@ -535,14 +536,14 @@ ext3_xattr_set_acl_default(struct inode *inode, const char *name, | |||
535 | } | 536 | } |
536 | 537 | ||
537 | struct xattr_handler ext3_xattr_acl_access_handler = { | 538 | struct xattr_handler ext3_xattr_acl_access_handler = { |
538 | .prefix = XATTR_NAME_ACL_ACCESS, | 539 | .prefix = POSIX_ACL_XATTR_ACCESS, |
539 | .list = ext3_xattr_list_acl_access, | 540 | .list = ext3_xattr_list_acl_access, |
540 | .get = ext3_xattr_get_acl_access, | 541 | .get = ext3_xattr_get_acl_access, |
541 | .set = ext3_xattr_set_acl_access, | 542 | .set = ext3_xattr_set_acl_access, |
542 | }; | 543 | }; |
543 | 544 | ||
544 | struct xattr_handler ext3_xattr_acl_default_handler = { | 545 | struct xattr_handler ext3_xattr_acl_default_handler = { |
545 | .prefix = XATTR_NAME_ACL_DEFAULT, | 546 | .prefix = POSIX_ACL_XATTR_DEFAULT, |
546 | .list = ext3_xattr_list_acl_default, | 547 | .list = ext3_xattr_list_acl_default, |
547 | .get = ext3_xattr_get_acl_default, | 548 | .get = ext3_xattr_get_acl_default, |
548 | .set = ext3_xattr_set_acl_default, | 549 | .set = ext3_xattr_set_acl_default, |
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h index 98af0c0d0ba9..92d50b53a933 100644 --- a/fs/ext3/acl.h +++ b/fs/ext3/acl.h | |||
@@ -4,7 +4,7 @@ | |||
4 | (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org> | 4 | (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/xattr_acl.h> | 7 | #include <linux/posix_acl_xattr.h> |
8 | 8 | ||
9 | #define EXT3_ACL_VERSION 0x0001 | 9 | #define EXT3_ACL_VERSION 0x0001 |
10 | 10 | ||
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index ccd632fcc6d8..e463dca008e4 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -749,24 +749,24 @@ fail_access: | |||
749 | * to find a free region that is of my size and has not | 749 | * to find a free region that is of my size and has not |
750 | * been reserved. | 750 | * been reserved. |
751 | * | 751 | * |
752 | * on succeed, it returns the reservation window to be appended to. | ||
753 | * failed, return NULL. | ||
754 | */ | 752 | */ |
755 | static struct ext3_reserve_window_node *find_next_reservable_window( | 753 | static int find_next_reservable_window( |
756 | struct ext3_reserve_window_node *search_head, | 754 | struct ext3_reserve_window_node *search_head, |
757 | unsigned long size, int *start_block, | 755 | struct ext3_reserve_window_node *my_rsv, |
756 | struct super_block * sb, int start_block, | ||
758 | int last_block) | 757 | int last_block) |
759 | { | 758 | { |
760 | struct rb_node *next; | 759 | struct rb_node *next; |
761 | struct ext3_reserve_window_node *rsv, *prev; | 760 | struct ext3_reserve_window_node *rsv, *prev; |
762 | int cur; | 761 | int cur; |
762 | int size = my_rsv->rsv_goal_size; | ||
763 | 763 | ||
764 | /* TODO: make the start of the reservation window byte-aligned */ | 764 | /* TODO: make the start of the reservation window byte-aligned */ |
765 | /* cur = *start_block & ~7;*/ | 765 | /* cur = *start_block & ~7;*/ |
766 | cur = *start_block; | 766 | cur = start_block; |
767 | rsv = search_head; | 767 | rsv = search_head; |
768 | if (!rsv) | 768 | if (!rsv) |
769 | return NULL; | 769 | return -1; |
770 | 770 | ||
771 | while (1) { | 771 | while (1) { |
772 | if (cur <= rsv->rsv_end) | 772 | if (cur <= rsv->rsv_end) |
@@ -782,11 +782,11 @@ static struct ext3_reserve_window_node *find_next_reservable_window( | |||
782 | * space with expected-size (or more)... | 782 | * space with expected-size (or more)... |
783 | */ | 783 | */ |
784 | if (cur > last_block) | 784 | if (cur > last_block) |
785 | return NULL; /* fail */ | 785 | return -1; /* fail */ |
786 | 786 | ||
787 | prev = rsv; | 787 | prev = rsv; |
788 | next = rb_next(&rsv->rsv_node); | 788 | next = rb_next(&rsv->rsv_node); |
789 | rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node); | 789 | rsv = list_entry(next,struct ext3_reserve_window_node,rsv_node); |
790 | 790 | ||
791 | /* | 791 | /* |
792 | * Reached the last reservation, we can just append to the | 792 | * Reached the last reservation, we can just append to the |
@@ -813,8 +813,25 @@ static struct ext3_reserve_window_node *find_next_reservable_window( | |||
813 | * return the reservation window that we could append to. | 813 | * return the reservation window that we could append to. |
814 | * succeed. | 814 | * succeed. |
815 | */ | 815 | */ |
816 | *start_block = cur; | 816 | |
817 | return prev; | 817 | if ((prev != my_rsv) && (!rsv_is_empty(&my_rsv->rsv_window))) |
818 | rsv_window_remove(sb, my_rsv); | ||
819 | |||
820 | /* | ||
821 | * Let's book the whole avaliable window for now. We will check the | ||
822 | * disk bitmap later and then, if there are free blocks then we adjust | ||
823 | * the window size if it's larger than requested. | ||
824 | * Otherwise, we will remove this node from the tree next time | ||
825 | * call find_next_reservable_window. | ||
826 | */ | ||
827 | my_rsv->rsv_start = cur; | ||
828 | my_rsv->rsv_end = cur + size - 1; | ||
829 | my_rsv->rsv_alloc_hit = 0; | ||
830 | |||
831 | if (prev != my_rsv) | ||
832 | ext3_rsv_window_add(sb, my_rsv); | ||
833 | |||
834 | return 0; | ||
818 | } | 835 | } |
819 | 836 | ||
820 | /** | 837 | /** |
@@ -852,6 +869,7 @@ static struct ext3_reserve_window_node *find_next_reservable_window( | |||
852 | * @sb: the super block | 869 | * @sb: the super block |
853 | * @group: the group we are trying to allocate in | 870 | * @group: the group we are trying to allocate in |
854 | * @bitmap_bh: the block group block bitmap | 871 | * @bitmap_bh: the block group block bitmap |
872 | * | ||
855 | */ | 873 | */ |
856 | static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, | 874 | static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, |
857 | int goal, struct super_block *sb, | 875 | int goal, struct super_block *sb, |
@@ -860,10 +878,10 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, | |||
860 | struct ext3_reserve_window_node *search_head; | 878 | struct ext3_reserve_window_node *search_head; |
861 | int group_first_block, group_end_block, start_block; | 879 | int group_first_block, group_end_block, start_block; |
862 | int first_free_block; | 880 | int first_free_block; |
863 | int reservable_space_start; | ||
864 | struct ext3_reserve_window_node *prev_rsv; | ||
865 | struct rb_root *fs_rsv_root = &EXT3_SB(sb)->s_rsv_window_root; | 881 | struct rb_root *fs_rsv_root = &EXT3_SB(sb)->s_rsv_window_root; |
866 | unsigned long size; | 882 | unsigned long size; |
883 | int ret; | ||
884 | spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock; | ||
867 | 885 | ||
868 | group_first_block = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) + | 886 | group_first_block = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) + |
869 | group * EXT3_BLOCKS_PER_GROUP(sb); | 887 | group * EXT3_BLOCKS_PER_GROUP(sb); |
@@ -875,6 +893,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, | |||
875 | start_block = goal + group_first_block; | 893 | start_block = goal + group_first_block; |
876 | 894 | ||
877 | size = my_rsv->rsv_goal_size; | 895 | size = my_rsv->rsv_goal_size; |
896 | |||
878 | if (!rsv_is_empty(&my_rsv->rsv_window)) { | 897 | if (!rsv_is_empty(&my_rsv->rsv_window)) { |
879 | /* | 898 | /* |
880 | * if the old reservation is cross group boundary | 899 | * if the old reservation is cross group boundary |
@@ -908,6 +927,8 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, | |||
908 | my_rsv->rsv_goal_size= size; | 927 | my_rsv->rsv_goal_size= size; |
909 | } | 928 | } |
910 | } | 929 | } |
930 | |||
931 | spin_lock(rsv_lock); | ||
911 | /* | 932 | /* |
912 | * shift the search start to the window near the goal block | 933 | * shift the search start to the window near the goal block |
913 | */ | 934 | */ |
@@ -921,11 +942,16 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, | |||
921 | * need to check the bitmap after we found a reservable window. | 942 | * need to check the bitmap after we found a reservable window. |
922 | */ | 943 | */ |
923 | retry: | 944 | retry: |
924 | prev_rsv = find_next_reservable_window(search_head, size, | 945 | ret = find_next_reservable_window(search_head, my_rsv, sb, |
925 | &start_block, group_end_block); | 946 | start_block, group_end_block); |
926 | if (prev_rsv == NULL) | 947 | |
927 | goto failed; | 948 | if (ret == -1) { |
928 | reservable_space_start = start_block; | 949 | if (!rsv_is_empty(&my_rsv->rsv_window)) |
950 | rsv_window_remove(sb, my_rsv); | ||
951 | spin_unlock(rsv_lock); | ||
952 | return -1; | ||
953 | } | ||
954 | |||
929 | /* | 955 | /* |
930 | * On success, find_next_reservable_window() returns the | 956 | * On success, find_next_reservable_window() returns the |
931 | * reservation window where there is a reservable space after it. | 957 | * reservation window where there is a reservable space after it. |
@@ -937,8 +963,9 @@ retry: | |||
937 | * block. Search start from the start block of the reservable space | 963 | * block. Search start from the start block of the reservable space |
938 | * we just found. | 964 | * we just found. |
939 | */ | 965 | */ |
966 | spin_unlock(rsv_lock); | ||
940 | first_free_block = bitmap_search_next_usable_block( | 967 | first_free_block = bitmap_search_next_usable_block( |
941 | reservable_space_start - group_first_block, | 968 | my_rsv->rsv_start - group_first_block, |
942 | bitmap_bh, group_end_block - group_first_block + 1); | 969 | bitmap_bh, group_end_block - group_first_block + 1); |
943 | 970 | ||
944 | if (first_free_block < 0) { | 971 | if (first_free_block < 0) { |
@@ -946,54 +973,29 @@ retry: | |||
946 | * no free block left on the bitmap, no point | 973 | * no free block left on the bitmap, no point |
947 | * to reserve the space. return failed. | 974 | * to reserve the space. return failed. |
948 | */ | 975 | */ |
949 | goto failed; | 976 | spin_lock(rsv_lock); |
977 | if (!rsv_is_empty(&my_rsv->rsv_window)) | ||
978 | rsv_window_remove(sb, my_rsv); | ||
979 | spin_unlock(rsv_lock); | ||
980 | return -1; /* failed */ | ||
950 | } | 981 | } |
982 | |||
951 | start_block = first_free_block + group_first_block; | 983 | start_block = first_free_block + group_first_block; |
952 | /* | 984 | /* |
953 | * check if the first free block is within the | 985 | * check if the first free block is within the |
954 | * free space we just found | 986 | * free space we just reserved |
955 | */ | 987 | */ |
956 | if ((start_block >= reservable_space_start) && | 988 | if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end) |
957 | (start_block < reservable_space_start + size)) | 989 | return 0; /* success */ |
958 | goto found_rsv_window; | ||
959 | /* | 990 | /* |
960 | * if the first free bit we found is out of the reservable space | 991 | * if the first free bit we found is out of the reservable space |
961 | * this means there is no free block on the reservable space | 992 | * continue search for next reservable space, |
962 | * we should continue search for next reservable space, | ||
963 | * start from where the free block is, | 993 | * start from where the free block is, |
964 | * we also shift the list head to where we stopped last time | 994 | * we also shift the list head to where we stopped last time |
965 | */ | 995 | */ |
966 | search_head = prev_rsv; | 996 | search_head = my_rsv; |
997 | spin_lock(rsv_lock); | ||
967 | goto retry; | 998 | goto retry; |
968 | |||
969 | found_rsv_window: | ||
970 | /* | ||
971 | * great! the reservable space contains some free blocks. | ||
972 | * if the search returns that we should add the new | ||
973 | * window just next to where the old window, we don't | ||
974 | * need to remove the old window first then add it to the | ||
975 | * same place, just update the new start and new end. | ||
976 | */ | ||
977 | if (my_rsv != prev_rsv) { | ||
978 | if (!rsv_is_empty(&my_rsv->rsv_window)) | ||
979 | rsv_window_remove(sb, my_rsv); | ||
980 | } | ||
981 | my_rsv->rsv_start = reservable_space_start; | ||
982 | my_rsv->rsv_end = my_rsv->rsv_start + size - 1; | ||
983 | my_rsv->rsv_alloc_hit = 0; | ||
984 | if (my_rsv != prev_rsv) { | ||
985 | ext3_rsv_window_add(sb, my_rsv); | ||
986 | } | ||
987 | return 0; /* succeed */ | ||
988 | failed: | ||
989 | /* | ||
990 | * failed to find a new reservation window in the current | ||
991 | * group, remove the current(stale) reservation window | ||
992 | * if there is any | ||
993 | */ | ||
994 | if (!rsv_is_empty(&my_rsv->rsv_window)) | ||
995 | rsv_window_remove(sb, my_rsv); | ||
996 | return -1; /* failed */ | ||
997 | } | 999 | } |
998 | 1000 | ||
999 | /* | 1001 | /* |
@@ -1023,7 +1025,6 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | |||
1023 | int goal, struct ext3_reserve_window_node * my_rsv, | 1025 | int goal, struct ext3_reserve_window_node * my_rsv, |
1024 | int *errp) | 1026 | int *errp) |
1025 | { | 1027 | { |
1026 | spinlock_t *rsv_lock; | ||
1027 | unsigned long group_first_block; | 1028 | unsigned long group_first_block; |
1028 | int ret = 0; | 1029 | int ret = 0; |
1029 | int fatal; | 1030 | int fatal; |
@@ -1052,7 +1053,6 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | |||
1052 | ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, NULL); | 1053 | ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, NULL); |
1053 | goto out; | 1054 | goto out; |
1054 | } | 1055 | } |
1055 | rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock; | ||
1056 | /* | 1056 | /* |
1057 | * goal is a group relative block number (if there is a goal) | 1057 | * goal is a group relative block number (if there is a goal) |
1058 | * 0 < goal < EXT3_BLOCKS_PER_GROUP(sb) | 1058 | * 0 < goal < EXT3_BLOCKS_PER_GROUP(sb) |
@@ -1078,30 +1078,21 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | |||
1078 | * then we could go to allocate from the reservation window directly. | 1078 | * then we could go to allocate from the reservation window directly. |
1079 | */ | 1079 | */ |
1080 | while (1) { | 1080 | while (1) { |
1081 | struct ext3_reserve_window rsv_copy; | 1081 | if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) || |
1082 | 1082 | !goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) { | |
1083 | rsv_copy._rsv_start = my_rsv->rsv_start; | ||
1084 | rsv_copy._rsv_end = my_rsv->rsv_end; | ||
1085 | |||
1086 | if (rsv_is_empty(&rsv_copy) || (ret < 0) || | ||
1087 | !goal_in_my_reservation(&rsv_copy, goal, group, sb)) { | ||
1088 | spin_lock(rsv_lock); | ||
1089 | ret = alloc_new_reservation(my_rsv, goal, sb, | 1083 | ret = alloc_new_reservation(my_rsv, goal, sb, |
1090 | group, bitmap_bh); | 1084 | group, bitmap_bh); |
1091 | rsv_copy._rsv_start = my_rsv->rsv_start; | ||
1092 | rsv_copy._rsv_end = my_rsv->rsv_end; | ||
1093 | spin_unlock(rsv_lock); | ||
1094 | if (ret < 0) | 1085 | if (ret < 0) |
1095 | break; /* failed */ | 1086 | break; /* failed */ |
1096 | 1087 | ||
1097 | if (!goal_in_my_reservation(&rsv_copy, goal, group, sb)) | 1088 | if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) |
1098 | goal = -1; | 1089 | goal = -1; |
1099 | } | 1090 | } |
1100 | if ((rsv_copy._rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) | 1091 | if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) |
1101 | || (rsv_copy._rsv_end < group_first_block)) | 1092 | || (my_rsv->rsv_end < group_first_block)) |
1102 | BUG(); | 1093 | BUG(); |
1103 | ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, | 1094 | ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, |
1104 | &rsv_copy); | 1095 | &my_rsv->rsv_window); |
1105 | if (ret >= 0) { | 1096 | if (ret >= 0) { |
1106 | my_rsv->rsv_alloc_hit++; | 1097 | my_rsv->rsv_alloc_hit++; |
1107 | break; /* succeed */ | 1098 | break; /* succeed */ |
diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 5ad8cf0292df..98e78345ead9 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c | |||
@@ -36,7 +36,11 @@ static int ext3_release_file (struct inode * inode, struct file * filp) | |||
36 | /* if we are the last writer on the inode, drop the block reservation */ | 36 | /* if we are the last writer on the inode, drop the block reservation */ |
37 | if ((filp->f_mode & FMODE_WRITE) && | 37 | if ((filp->f_mode & FMODE_WRITE) && |
38 | (atomic_read(&inode->i_writecount) == 1)) | 38 | (atomic_read(&inode->i_writecount) == 1)) |
39 | { | ||
40 | down(&EXT3_I(inode)->truncate_sem); | ||
39 | ext3_discard_reservation(inode); | 41 | ext3_discard_reservation(inode); |
42 | up(&EXT3_I(inode)->truncate_sem); | ||
43 | } | ||
40 | if (is_dx(inode) && filp->private_data) | 44 | if (is_dx(inode) && filp->private_data) |
41 | ext3_htree_free_dir_info(filp->private_data); | 45 | ext3_htree_free_dir_info(filp->private_data); |
42 | 46 | ||
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 0d5fa73b18dc..0b2db4f618cb 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -128,7 +128,7 @@ static unsigned long blocks_for_truncate(struct inode *inode) | |||
128 | if (needed > EXT3_MAX_TRANS_DATA) | 128 | if (needed > EXT3_MAX_TRANS_DATA) |
129 | needed = EXT3_MAX_TRANS_DATA; | 129 | needed = EXT3_MAX_TRANS_DATA; |
130 | 130 | ||
131 | return EXT3_DATA_TRANS_BLOCKS + needed; | 131 | return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed; |
132 | } | 132 | } |
133 | 133 | ||
134 | /* | 134 | /* |
@@ -2763,7 +2763,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr) | |||
2763 | 2763 | ||
2764 | /* (user+group)*(old+new) structure, inode write (sb, | 2764 | /* (user+group)*(old+new) structure, inode write (sb, |
2765 | * inode block, ? - but truncate inode update has it) */ | 2765 | * inode block, ? - but truncate inode update has it) */ |
2766 | handle = ext3_journal_start(inode, 4*EXT3_QUOTA_INIT_BLOCKS+3); | 2766 | handle = ext3_journal_start(inode, 2*(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+ |
2767 | EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+3); | ||
2767 | if (IS_ERR(handle)) { | 2768 | if (IS_ERR(handle)) { |
2768 | error = PTR_ERR(handle); | 2769 | error = PTR_ERR(handle); |
2769 | goto err_out; | 2770 | goto err_out; |
@@ -2861,7 +2862,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode) | |||
2861 | #ifdef CONFIG_QUOTA | 2862 | #ifdef CONFIG_QUOTA |
2862 | /* We know that structure was already allocated during DQUOT_INIT so | 2863 | /* We know that structure was already allocated during DQUOT_INIT so |
2863 | * we will be updating only the data blocks + inodes */ | 2864 | * we will be updating only the data blocks + inodes */ |
2864 | ret += 2*EXT3_QUOTA_TRANS_BLOCKS; | 2865 | ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb); |
2865 | #endif | 2866 | #endif |
2866 | 2867 | ||
2867 | return ret; | 2868 | return ret; |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 79742d824a0a..50378d8ff84b 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -932,8 +932,16 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, | |||
932 | struct inode *dir = dentry->d_parent->d_inode; | 932 | struct inode *dir = dentry->d_parent->d_inode; |
933 | 933 | ||
934 | sb = dir->i_sb; | 934 | sb = dir->i_sb; |
935 | if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err))) | 935 | /* NFS may look up ".." - look at dx_root directory block */ |
936 | return NULL; | 936 | if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){ |
937 | if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err))) | ||
938 | return NULL; | ||
939 | } else { | ||
940 | frame = frames; | ||
941 | frame->bh = NULL; /* for dx_release() */ | ||
942 | frame->at = (struct dx_entry *)frames; /* hack for zero entry*/ | ||
943 | dx_set_block(frame->at, 0); /* dx_root block is 0 */ | ||
944 | } | ||
937 | hash = hinfo.hash; | 945 | hash = hinfo.hash; |
938 | do { | 946 | do { |
939 | block = dx_get_block(frame->at); | 947 | block = dx_get_block(frame->at); |
@@ -1637,9 +1645,9 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode, | |||
1637 | int err, retries = 0; | 1645 | int err, retries = 0; |
1638 | 1646 | ||
1639 | retry: | 1647 | retry: |
1640 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + | 1648 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + |
1641 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + | 1649 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + |
1642 | 2*EXT3_QUOTA_INIT_BLOCKS); | 1650 | 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); |
1643 | if (IS_ERR(handle)) | 1651 | if (IS_ERR(handle)) |
1644 | return PTR_ERR(handle); | 1652 | return PTR_ERR(handle); |
1645 | 1653 | ||
@@ -1671,9 +1679,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry, | |||
1671 | return -EINVAL; | 1679 | return -EINVAL; |
1672 | 1680 | ||
1673 | retry: | 1681 | retry: |
1674 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + | 1682 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + |
1675 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + | 1683 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + |
1676 | 2*EXT3_QUOTA_INIT_BLOCKS); | 1684 | 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); |
1677 | if (IS_ERR(handle)) | 1685 | if (IS_ERR(handle)) |
1678 | return PTR_ERR(handle); | 1686 | return PTR_ERR(handle); |
1679 | 1687 | ||
@@ -1707,9 +1715,9 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode) | |||
1707 | return -EMLINK; | 1715 | return -EMLINK; |
1708 | 1716 | ||
1709 | retry: | 1717 | retry: |
1710 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + | 1718 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + |
1711 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + | 1719 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + |
1712 | 2*EXT3_QUOTA_INIT_BLOCKS); | 1720 | 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); |
1713 | if (IS_ERR(handle)) | 1721 | if (IS_ERR(handle)) |
1714 | return PTR_ERR(handle); | 1722 | return PTR_ERR(handle); |
1715 | 1723 | ||
@@ -1998,7 +2006,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry) | |||
1998 | /* Initialize quotas before so that eventual writes go in | 2006 | /* Initialize quotas before so that eventual writes go in |
1999 | * separate transaction */ | 2007 | * separate transaction */ |
2000 | DQUOT_INIT(dentry->d_inode); | 2008 | DQUOT_INIT(dentry->d_inode); |
2001 | handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); | 2009 | handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb)); |
2002 | if (IS_ERR(handle)) | 2010 | if (IS_ERR(handle)) |
2003 | return PTR_ERR(handle); | 2011 | return PTR_ERR(handle); |
2004 | 2012 | ||
@@ -2057,7 +2065,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry) | |||
2057 | /* Initialize quotas before so that eventual writes go | 2065 | /* Initialize quotas before so that eventual writes go |
2058 | * in separate transaction */ | 2066 | * in separate transaction */ |
2059 | DQUOT_INIT(dentry->d_inode); | 2067 | DQUOT_INIT(dentry->d_inode); |
2060 | handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); | 2068 | handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb)); |
2061 | if (IS_ERR(handle)) | 2069 | if (IS_ERR(handle)) |
2062 | return PTR_ERR(handle); | 2070 | return PTR_ERR(handle); |
2063 | 2071 | ||
@@ -2112,9 +2120,9 @@ static int ext3_symlink (struct inode * dir, | |||
2112 | return -ENAMETOOLONG; | 2120 | return -ENAMETOOLONG; |
2113 | 2121 | ||
2114 | retry: | 2122 | retry: |
2115 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + | 2123 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + |
2116 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + | 2124 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + |
2117 | 2*EXT3_QUOTA_INIT_BLOCKS); | 2125 | 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); |
2118 | if (IS_ERR(handle)) | 2126 | if (IS_ERR(handle)) |
2119 | return PTR_ERR(handle); | 2127 | return PTR_ERR(handle); |
2120 | 2128 | ||
@@ -2166,7 +2174,7 @@ static int ext3_link (struct dentry * old_dentry, | |||
2166 | return -EMLINK; | 2174 | return -EMLINK; |
2167 | 2175 | ||
2168 | retry: | 2176 | retry: |
2169 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + | 2177 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + |
2170 | EXT3_INDEX_EXTRA_TRANS_BLOCKS); | 2178 | EXT3_INDEX_EXTRA_TRANS_BLOCKS); |
2171 | if (IS_ERR(handle)) | 2179 | if (IS_ERR(handle)) |
2172 | return PTR_ERR(handle); | 2180 | return PTR_ERR(handle); |
@@ -2208,7 +2216,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, | |||
2208 | * in separate transaction */ | 2216 | * in separate transaction */ |
2209 | if (new_dentry->d_inode) | 2217 | if (new_dentry->d_inode) |
2210 | DQUOT_INIT(new_dentry->d_inode); | 2218 | DQUOT_INIT(new_dentry->d_inode); |
2211 | handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + | 2219 | handle = ext3_journal_start(old_dir, 2 * |
2220 | EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) + | ||
2212 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); | 2221 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); |
2213 | if (IS_ERR(handle)) | 2222 | if (IS_ERR(handle)) |
2214 | return PTR_ERR(handle); | 2223 | return PTR_ERR(handle); |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 981ccb233ef5..a6d1779d7de4 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -589,7 +589,7 @@ enum { | |||
589 | Opt_commit, Opt_journal_update, Opt_journal_inum, | 589 | Opt_commit, Opt_journal_update, Opt_journal_inum, |
590 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 590 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
591 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 591 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
592 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, | 592 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, |
593 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, | 593 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, |
594 | }; | 594 | }; |
595 | 595 | ||
@@ -634,10 +634,10 @@ static match_table_t tokens = { | |||
634 | {Opt_grpjquota, "grpjquota=%s"}, | 634 | {Opt_grpjquota, "grpjquota=%s"}, |
635 | {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, | 635 | {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, |
636 | {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, | 636 | {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, |
637 | {Opt_ignore, "grpquota"}, | 637 | {Opt_quota, "grpquota"}, |
638 | {Opt_ignore, "noquota"}, | 638 | {Opt_noquota, "noquota"}, |
639 | {Opt_ignore, "quota"}, | 639 | {Opt_quota, "quota"}, |
640 | {Opt_ignore, "usrquota"}, | 640 | {Opt_quota, "usrquota"}, |
641 | {Opt_barrier, "barrier=%u"}, | 641 | {Opt_barrier, "barrier=%u"}, |
642 | {Opt_err, NULL}, | 642 | {Opt_err, NULL}, |
643 | {Opt_resize, "resize"}, | 643 | {Opt_resize, "resize"}, |
@@ -876,6 +876,7 @@ set_qf_name: | |||
876 | sbi->s_qf_names[qtype] = NULL; | 876 | sbi->s_qf_names[qtype] = NULL; |
877 | return 0; | 877 | return 0; |
878 | } | 878 | } |
879 | set_opt(sbi->s_mount_opt, QUOTA); | ||
879 | break; | 880 | break; |
880 | case Opt_offusrjquota: | 881 | case Opt_offusrjquota: |
881 | qtype = USRQUOTA; | 882 | qtype = USRQUOTA; |
@@ -898,6 +899,17 @@ clear_qf_name: | |||
898 | case Opt_jqfmt_vfsv0: | 899 | case Opt_jqfmt_vfsv0: |
899 | sbi->s_jquota_fmt = QFMT_VFS_V0; | 900 | sbi->s_jquota_fmt = QFMT_VFS_V0; |
900 | break; | 901 | break; |
902 | case Opt_quota: | ||
903 | set_opt(sbi->s_mount_opt, QUOTA); | ||
904 | break; | ||
905 | case Opt_noquota: | ||
906 | if (sb_any_quota_enabled(sb)) { | ||
907 | printk(KERN_ERR "EXT3-fs: Cannot change quota " | ||
908 | "options when quota turned on.\n"); | ||
909 | return 0; | ||
910 | } | ||
911 | clear_opt(sbi->s_mount_opt, QUOTA); | ||
912 | break; | ||
901 | #else | 913 | #else |
902 | case Opt_usrjquota: | 914 | case Opt_usrjquota: |
903 | case Opt_grpjquota: | 915 | case Opt_grpjquota: |
@@ -909,6 +921,9 @@ clear_qf_name: | |||
909 | "EXT3-fs: journalled quota options not " | 921 | "EXT3-fs: journalled quota options not " |
910 | "supported.\n"); | 922 | "supported.\n"); |
911 | break; | 923 | break; |
924 | case Opt_quota: | ||
925 | case Opt_noquota: | ||
926 | break; | ||
912 | #endif | 927 | #endif |
913 | case Opt_abort: | 928 | case Opt_abort: |
914 | set_opt(sbi->s_mount_opt, ABORT); | 929 | set_opt(sbi->s_mount_opt, ABORT); |
@@ -929,7 +944,8 @@ clear_qf_name: | |||
929 | "for remount\n"); | 944 | "for remount\n"); |
930 | return 0; | 945 | return 0; |
931 | } | 946 | } |
932 | match_int(&args[0], &option); | 947 | if (match_int(&args[0], &option) != 0) |
948 | return 0; | ||
933 | *n_blocks_count = option; | 949 | *n_blocks_count = option; |
934 | break; | 950 | break; |
935 | case Opt_nobh: | 951 | case Opt_nobh: |
@@ -2238,7 +2254,7 @@ static int ext3_dquot_initialize(struct inode *inode, int type) | |||
2238 | int ret, err; | 2254 | int ret, err; |
2239 | 2255 | ||
2240 | /* We may create quota structure so we need to reserve enough blocks */ | 2256 | /* We may create quota structure so we need to reserve enough blocks */ |
2241 | handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); | 2257 | handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)); |
2242 | if (IS_ERR(handle)) | 2258 | if (IS_ERR(handle)) |
2243 | return PTR_ERR(handle); | 2259 | return PTR_ERR(handle); |
2244 | ret = dquot_initialize(inode, type); | 2260 | ret = dquot_initialize(inode, type); |
@@ -2254,7 +2270,7 @@ static int ext3_dquot_drop(struct inode *inode) | |||
2254 | int ret, err; | 2270 | int ret, err; |
2255 | 2271 | ||
2256 | /* We may delete quota structure so we need to reserve enough blocks */ | 2272 | /* We may delete quota structure so we need to reserve enough blocks */ |
2257 | handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); | 2273 | handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb)); |
2258 | if (IS_ERR(handle)) | 2274 | if (IS_ERR(handle)) |
2259 | return PTR_ERR(handle); | 2275 | return PTR_ERR(handle); |
2260 | ret = dquot_drop(inode); | 2276 | ret = dquot_drop(inode); |
@@ -2272,7 +2288,7 @@ static int ext3_write_dquot(struct dquot *dquot) | |||
2272 | 2288 | ||
2273 | inode = dquot_to_inode(dquot); | 2289 | inode = dquot_to_inode(dquot); |
2274 | handle = ext3_journal_start(inode, | 2290 | handle = ext3_journal_start(inode, |
2275 | EXT3_QUOTA_TRANS_BLOCKS); | 2291 | EXT3_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); |
2276 | if (IS_ERR(handle)) | 2292 | if (IS_ERR(handle)) |
2277 | return PTR_ERR(handle); | 2293 | return PTR_ERR(handle); |
2278 | ret = dquot_commit(dquot); | 2294 | ret = dquot_commit(dquot); |
@@ -2288,7 +2304,7 @@ static int ext3_acquire_dquot(struct dquot *dquot) | |||
2288 | handle_t *handle; | 2304 | handle_t *handle; |
2289 | 2305 | ||
2290 | handle = ext3_journal_start(dquot_to_inode(dquot), | 2306 | handle = ext3_journal_start(dquot_to_inode(dquot), |
2291 | EXT3_QUOTA_INIT_BLOCKS); | 2307 | EXT3_QUOTA_INIT_BLOCKS(dquot->dq_sb)); |
2292 | if (IS_ERR(handle)) | 2308 | if (IS_ERR(handle)) |
2293 | return PTR_ERR(handle); | 2309 | return PTR_ERR(handle); |
2294 | ret = dquot_acquire(dquot); | 2310 | ret = dquot_acquire(dquot); |
@@ -2304,7 +2320,7 @@ static int ext3_release_dquot(struct dquot *dquot) | |||
2304 | handle_t *handle; | 2320 | handle_t *handle; |
2305 | 2321 | ||
2306 | handle = ext3_journal_start(dquot_to_inode(dquot), | 2322 | handle = ext3_journal_start(dquot_to_inode(dquot), |
2307 | EXT3_QUOTA_INIT_BLOCKS); | 2323 | EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb)); |
2308 | if (IS_ERR(handle)) | 2324 | if (IS_ERR(handle)) |
2309 | return PTR_ERR(handle); | 2325 | return PTR_ERR(handle); |
2310 | ret = dquot_release(dquot); | 2326 | ret = dquot_release(dquot); |
@@ -2348,22 +2364,8 @@ static int ext3_write_info(struct super_block *sb, int type) | |||
2348 | */ | 2364 | */ |
2349 | static int ext3_quota_on_mount(struct super_block *sb, int type) | 2365 | static int ext3_quota_on_mount(struct super_block *sb, int type) |
2350 | { | 2366 | { |
2351 | int err; | 2367 | return vfs_quota_on_mount(sb, EXT3_SB(sb)->s_qf_names[type], |
2352 | struct dentry *dentry; | 2368 | EXT3_SB(sb)->s_jquota_fmt, type); |
2353 | struct qstr name = { .name = EXT3_SB(sb)->s_qf_names[type], | ||
2354 | .hash = 0, | ||
2355 | .len = strlen(EXT3_SB(sb)->s_qf_names[type])}; | ||
2356 | |||
2357 | dentry = lookup_hash(&name, sb->s_root); | ||
2358 | if (IS_ERR(dentry)) | ||
2359 | return PTR_ERR(dentry); | ||
2360 | err = vfs_quota_on_mount(type, EXT3_SB(sb)->s_jquota_fmt, dentry); | ||
2361 | /* Now invalidate and put the dentry - quota got its own reference | ||
2362 | * to inode and dentry has at least wrong hash so we had better | ||
2363 | * throw it away */ | ||
2364 | d_invalidate(dentry); | ||
2365 | dput(dentry); | ||
2366 | return err; | ||
2367 | } | 2369 | } |
2368 | 2370 | ||
2369 | /* | 2371 | /* |
@@ -2375,6 +2377,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, | |||
2375 | int err; | 2377 | int err; |
2376 | struct nameidata nd; | 2378 | struct nameidata nd; |
2377 | 2379 | ||
2380 | if (!test_opt(sb, QUOTA)) | ||
2381 | return -EINVAL; | ||
2378 | /* Not journalling quota? */ | 2382 | /* Not journalling quota? */ |
2379 | if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] && | 2383 | if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] && |
2380 | !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) | 2384 | !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) |
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 4cbc6d0212d3..3f9dfa643b19 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c | |||
@@ -1044,7 +1044,7 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name, | |||
1044 | int error, retries = 0; | 1044 | int error, retries = 0; |
1045 | 1045 | ||
1046 | retry: | 1046 | retry: |
1047 | handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); | 1047 | handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); |
1048 | if (IS_ERR(handle)) { | 1048 | if (IS_ERR(handle)) { |
1049 | error = PTR_ERR(handle); | 1049 | error = PTR_ERR(handle); |
1050 | } else { | 1050 | } else { |