Pull ext4 updates from Ted Ts'o: "Scalability improvements when allocating inodes, and some miscellaneous bug fixes and cleanups" * tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: avoid Y2038 overflow in recently_deleted() ext4: fix fault handling when mounted with -o dax,ro ext4: fix quota inconsistency during orphan cleanup for read-only mounts ext4: fix incorrect quotaoff if the quota feature is enabled ext4: remove useless test and assignment in strtohash functions ext4: backward compatibility support for Lustre ea_inode implementation ext4: remove timebomb in ext4_decode_extra_time() ext4: use sizeof(*ptr) ext4: in ext4_seek_{hole,data}, return -ENXIO for negative offsets ext4: reduce lock contention in __ext4_new_inode ext4: cleanup goto next group ext4: do not unnecessarily allocate buffer in recently_deleted()
Unified · Split
| @@ -411,7 +411,7 @@ static struct dir_private_info *ext4_htree_create_dir_info(struct file *filp, · 410 unmodified lines | |||
| 411 | { | 411 | { |
| 412 | struct dir_private_info *p; | 412 | struct dir_private_info *p; |
| 413 | 413 | ||
| 414 | p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL); | 414 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 415 | if (!p) | 415 | if (!p) |
| 416 | return NULL; | 416 | return NULL; |
| 417 | p->curr_hash = pos2maj_hash(filp, pos); | 417 | p->curr_hash = pos2maj_hash(filp, pos); |
| @@ -838,13 +838,11 @@ static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra) · 837 unmodified lines | |||
| 838 | { | 838 | { |
| 839 | if (unlikely(sizeof(time->tv_sec) > 4 && | 839 | if (unlikely(sizeof(time->tv_sec) > 4 && |
| 840 | (extra & cpu_to_le32(EXT4_EPOCH_MASK)))) { | 840 | (extra & cpu_to_le32(EXT4_EPOCH_MASK)))) { |
| 841 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0) | 841 | |
| 842 | #if 1 | ||
| 842 | /* Handle legacy encoding of pre-1970 dates with epoch | 843 | /* Handle legacy encoding of pre-1970 dates with epoch |
| 843 | * bits 1,1. We assume that by kernel version 4.20, | 844 | * bits 1,1. (This backwards compatibility may be removed |
| 844 | * everyone will have run fsck over the affected | 845 | * at the discretion of the ext4 developers.) |
| 845 | * filesystems to correct the problem. (This | ||
| 846 | * backwards compatibility may be removed before this | ||
| 847 | * time, at the discretion of the ext4 developers.) | ||
| 848 | */ | 846 | */ |
| 849 | u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK; | 847 | u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK; |
| 850 | if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0) | 848 | if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0) |
| @@ -1567,6 +1565,7 @@ enum { · 716 unmodified lines | |||
| 1567 | nolocking */ | 1565 | nolocking */ |
| 1568 | EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */ | 1566 | EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */ |
| 1569 | EXT4_STATE_EXT_PRECACHED, /* extents have been precached */ | 1567 | EXT4_STATE_EXT_PRECACHED, /* extents have been precached */ |
| 1568 | EXT4_STATE_LUSTRE_EA_INODE, /* Lustre-style ea_inode */ | ||
| 1570 | }; | 1569 | }; |
| 1571 | 1570 | ||
| 1572 | #define EXT4_INODE_BIT_FNS(name, field, offset) \ | 1571 | #define EXT4_INODE_BIT_FNS(name, field, offset) \ |
| @@ -279,7 +279,20 @@ static int ext4_dax_huge_fault(struct vm_fault *vmf, · 278 unmodified lines | |||
| 279 | handle_t *handle = NULL; | 279 | handle_t *handle = NULL; |
| 280 | struct inode *inode = file_inode(vmf->vma->vm_file); | 280 | struct inode *inode = file_inode(vmf->vma->vm_file); |
| 281 | struct super_block *sb = inode->i_sb; | 281 | struct super_block *sb = inode->i_sb; |
| 282 | bool write = vmf->flags & FAULT_FLAG_WRITE; | 282 | |
| 283 | /* | ||
| 284 | * We have to distinguish real writes from writes which will result in a | ||
| 285 | * COW page; COW writes should *not* poke the journal (the file will not | ||
| 286 | * be changed). Doing so would cause unintended failures when mounted | ||
| 287 | * read-only. | ||
| 288 | * | ||
| 289 | * We check for VM_SHARED rather than vmf->cow_page since the latter is | ||
| 290 | * unset for pe_size != PE_SIZE_PTE (i.e. only in do_cow_fault); for | ||
| 291 | * other sizes, dax_iomap_fault will handle splitting / fallback so that | ||
| 292 | * we eventually come back with a COW page. | ||
| 293 | */ | ||
| 294 | bool write = (vmf->flags & FAULT_FLAG_WRITE) && | ||
| 295 | (vmf->vma->vm_flags & VM_SHARED); | ||
| 283 | 296 | ||
| 284 | if (write) { | 297 | if (write) { |
| 285 | sb_start_pagefault(sb); | 298 | sb_start_pagefault(sb); |
| @@ -595,7 +608,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) · 309 unmodified lines | |||
| 595 | inode_lock(inode); | 608 | inode_lock(inode); |
| 596 | 609 | ||
| 597 | isize = i_size_read(inode); | 610 | isize = i_size_read(inode); |
| 598 | if (offset >= isize) { | 611 | if (offset < 0 || offset >= isize) { |
| 599 | inode_unlock(inode); | 612 | inode_unlock(inode); |
| 600 | return -ENXIO; | 613 | return -ENXIO; |
| 601 | } | 614 | } |
| @@ -658,7 +671,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) · 56 unmodified lines | |||
| 658 | inode_lock(inode); | 671 | inode_lock(inode); |
| 659 | 672 | ||
| 660 | isize = i_size_read(inode); | 673 | isize = i_size_read(inode); |
| 661 | if (offset >= isize) { | 674 | if (offset < 0 || offset >= isize) { |
| 662 | inode_unlock(inode); | 675 | inode_unlock(inode); |
| 663 | return -ENXIO; | 676 | return -ENXIO; |
| 664 | } | 677 | } |
| @@ -148,8 +148,6 @@ static void str2hashbuf_signed(const char *msg, int len, __u32 *buf, int num) · 147 unmodified lines | |||
| 148 | if (len > num*4) | 148 | if (len > num*4) |
| 149 | len = num * 4; | 149 | len = num * 4; |
| 150 | for (i = 0; i < len; i++) { | 150 | for (i = 0; i < len; i++) { |
| 151 | if ((i % 4) == 0) | ||
| 152 | val = pad; | ||
| 153 | val = ((int) scp[i]) + (val << 8); | 151 | val = ((int) scp[i]) + (val << 8); |
| 154 | if ((i % 4) == 3) { | 152 | if ((i % 4) == 3) { |
| 155 | *buf++ = val; | 153 | *buf++ = val; |
| @@ -176,8 +174,6 @@ static void str2hashbuf_unsigned(const char *msg, int len, __u32 *buf, int num) · 20 unmodified lines | |||
| 176 | if (len > num*4) | 174 | if (len > num*4) |
| 177 | len = num * 4; | 175 | len = num * 4; |
| 178 | for (i = 0; i < len; i++) { | 176 | for (i = 0; i < len; i++) { |
| 179 | if ((i % 4) == 0) | ||
| 180 | val = pad; | ||
| 181 | val = ((int) ucp[i]) + (val << 8); | 177 | val = ((int) ucp[i]) + (val << 8); |
| 182 | if ((i % 4) == 3) { | 178 | if ((i % 4) == 3) { |
| 183 | *buf++ = val; | 179 | *buf++ = val; |
| @@ -692,24 +692,25 @@ static int find_group_other(struct super_block *sb, struct inode *parent, · 691 unmodified lines | |||
| 692 | * somewhat arbitrary...) | 692 | * somewhat arbitrary...) |
| 693 | */ | 693 | */ |
| 694 | #define RECENTCY_MIN 5 | 694 | #define RECENTCY_MIN 5 |
| 695 | #define RECENTCY_DIRTY 30 | 695 | #define RECENTCY_DIRTY 300 |
| 696 | 696 | ||
| 697 | static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino) | 697 | static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino) |
| 698 | { | 698 | { |
| 699 | struct ext4_group_desc *gdp; | 699 | struct ext4_group_desc *gdp; |
| 700 | struct ext4_inode *raw_inode; | 700 | struct ext4_inode *raw_inode; |
| 701 | struct buffer_head *bh; | 701 | struct buffer_head *bh; |
| 702 | unsigned long dtime, now; | 702 | int inodes_per_block = EXT4_SB(sb)->s_inodes_per_block; |
| 703 | int inodes_per_block = EXT4_SB(sb)->s_inodes_per_block; | 703 | int offset, ret = 0; |
| 704 | int offset, ret = 0, recentcy = RECENTCY_MIN; | 704 | int recentcy = RECENTCY_MIN; |
| 705 | u32 dtime, now; | ||
| 705 | 706 | ||
| 706 | gdp = ext4_get_group_desc(sb, group, NULL); | 707 | gdp = ext4_get_group_desc(sb, group, NULL); |
| 707 | if (unlikely(!gdp)) | 708 | if (unlikely(!gdp)) |
| 708 | return 0; | 709 | return 0; |
| 709 | 710 | ||
| 710 | bh = sb_getblk(sb, ext4_inode_table(sb, gdp) + | 711 | bh = sb_find_get_block(sb, ext4_inode_table(sb, gdp) + |
| 711 | (ino / inodes_per_block)); | 712 | (ino / inodes_per_block)); |
| 712 | if (unlikely(!bh) || !buffer_uptodate(bh)) | 713 | if (!bh || !buffer_uptodate(bh)) |
| 713 | /* | 714 | /* |
| 714 | * If the block is not in the buffer cache, then it | 715 | * If the block is not in the buffer cache, then it |
| 715 | * must have been written out. | 716 | * must have been written out. |
| @@ -718,18 +719,45 @@ static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino) · 2 unmodified lines | |||
| 718 | 719 | ||
| 719 | offset = (ino % inodes_per_block) * EXT4_INODE_SIZE(sb); | 720 | offset = (ino % inodes_per_block) * EXT4_INODE_SIZE(sb); |
| 720 | raw_inode = (struct ext4_inode *) (bh->b_data + offset); | 721 | raw_inode = (struct ext4_inode *) (bh->b_data + offset); |
| 722 | |||
| 723 | /* i_dtime is only 32 bits on disk, but we only care about relative | ||
| 724 | * times in the range of a few minutes (i.e. long enough to sync a | ||
| 725 | * recently-deleted inode to disk), so using the low 32 bits of the | ||
| 726 | * clock (a 68 year range) is enough, see time_before32() */ | ||
| 721 | dtime = le32_to_cpu(raw_inode->i_dtime); | 727 | dtime = le32_to_cpu(raw_inode->i_dtime); |
| 722 | now = get_seconds(); | 728 | now = ktime_get_real_seconds(); |
| 723 | if (buffer_dirty(bh)) | 729 | if (buffer_dirty(bh)) |
| 724 | recentcy += RECENTCY_DIRTY; | 730 | recentcy += RECENTCY_DIRTY; |
| 725 | 731 | ||
| 726 | if (dtime && (dtime < now) && (now < dtime + recentcy)) | 732 | if (dtime && time_before32(dtime, now) && |
| 733 | time_before32(now, dtime + recentcy)) | ||
| 727 | ret = 1; | 734 | ret = 1; |
| 728 | out: | 735 | out: |
| 729 | brelse(bh); | 736 | brelse(bh); |
| 730 | return ret; | 737 | return ret; |
| 731 | } | 738 | } |
| 732 | 739 | ||
| 740 | static int find_inode_bit(struct super_block *sb, ext4_group_t group, | ||
| 741 | struct buffer_head *bitmap, unsigned long *ino) | ||
| 742 | { | ||
| 743 | next: | ||
| 744 | *ino = ext4_find_next_zero_bit((unsigned long *) | ||
| 745 | bitmap->b_data, | ||
| 746 | EXT4_INODES_PER_GROUP(sb), *ino); | ||
| 747 | if (*ino >= EXT4_INODES_PER_GROUP(sb)) | ||
| 748 | return 0; | ||
| 749 | |||
| 750 | if ((EXT4_SB(sb)->s_journal == NULL) && | ||
| 751 | recently_deleted(sb, group, *ino)) { | ||
| 752 | *ino = *ino + 1; | ||
| 753 | if (*ino < EXT4_INODES_PER_GROUP(sb)) | ||
| 754 | goto next; | ||
| 755 | return 0; | ||
| 756 | } | ||
| 757 | |||
| 758 | return 1; | ||
| 759 | } | ||
| 760 | |||
| 733 | /* | 761 | /* |
| 734 | * There are two policies for allocating an inode. If the new inode is | 762 | * There are two policies for allocating an inode. If the new inode is |
| 735 | * a directory, then a forward search is made for a block group with both | 763 | * a directory, then a forward search is made for a block group with both |
| @@ -892,19 +920,13 @@ got_group: · 156 unmodified lines | |||
| 892 | /* | 920 | /* |
| 893 | * Check free inodes count before loading bitmap. | 921 | * Check free inodes count before loading bitmap. |
| 894 | */ | 922 | */ |
| 895 | if (ext4_free_inodes_count(sb, gdp) == 0) { | 923 | if (ext4_free_inodes_count(sb, gdp) == 0) |
| 896 | if (++group == ngroups) | 924 | goto next_group; |
| 897 | group = 0; | ||
| 898 | continue; | ||
| 899 | } | ||
| 900 | 925 | ||
| 901 | grp = ext4_get_group_info(sb, group); | 926 | grp = ext4_get_group_info(sb, group); |
| 902 | /* Skip groups with already-known suspicious inode tables */ | 927 | /* Skip groups with already-known suspicious inode tables */ |
| 903 | if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { | 928 | if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) |
| 904 | if (++group == ngroups) | 929 | goto next_group; |
| 905 | group = 0; | ||
| 906 | continue; | ||
| 907 | } | ||
| 908 | 930 | ||
| 909 | brelse(inode_bitmap_bh); | 931 | brelse(inode_bitmap_bh); |
| 910 | inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); | 932 | inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); |
| @@ -912,27 +934,20 @@ got_group: · 1 unmodified line | |||
| 912 | if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || | 934 | if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || |
| 913 | IS_ERR(inode_bitmap_bh)) { | 935 | IS_ERR(inode_bitmap_bh)) { |
| 914 | inode_bitmap_bh = NULL; | 936 | inode_bitmap_bh = NULL; |
| 915 | if (++group == ngroups) | 937 | goto next_group; |
| 916 | group = 0; | ||
| 917 | continue; | ||
| 918 | } | 938 | } |
| 919 | 939 | ||
| 920 | repeat_in_this_group: | 940 | repeat_in_this_group: |
| 921 | ino = ext4_find_next_zero_bit((unsigned long *) | 941 | ret2 = find_inode_bit(sb, group, inode_bitmap_bh, &ino); |
| 922 | inode_bitmap_bh->b_data, | 942 | if (!ret2) |
| 923 | EXT4_INODES_PER_GROUP(sb), ino); | ||
| 924 | if (ino >= EXT4_INODES_PER_GROUP(sb)) | ||
| 925 | goto next_group; | 943 | goto next_group; |
| 926 | if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) { | 944 | |
| 945 | if (group == 0 && (ino + 1) < EXT4_FIRST_INO(sb)) { | ||
| 927 | ext4_error(sb, "reserved inode found cleared - " | 946 | ext4_error(sb, "reserved inode found cleared - " |
| 928 | "inode=%lu", ino + 1); | 947 | "inode=%lu", ino + 1); |
| 929 | continue; | 948 | goto next_group; |
| 930 | } | ||
| 931 | if ((EXT4_SB(sb)->s_journal == NULL) && | ||
| 932 | recently_deleted(sb, group, ino)) { | ||
| 933 | ino++; | ||
| 934 | goto next_inode; | ||
| 935 | } | 949 | } |
| 950 | |||
| 936 | if (!handle) { | 951 | if (!handle) { |
| 937 | BUG_ON(nblocks <= 0); | 952 | BUG_ON(nblocks <= 0); |
| 938 | handle = __ext4_journal_start_sb(dir->i_sb, line_no, | 953 | handle = __ext4_journal_start_sb(dir->i_sb, line_no, |
| @@ -952,11 +967,23 @@ repeat_in_this_group: · 13 unmodified lines | |||
| 952 | } | 967 | } |
| 953 | ext4_lock_group(sb, group); | 968 | ext4_lock_group(sb, group); |
| 954 | ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); | 969 | ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); |
| 970 | if (ret2) { | ||
| 971 | /* Someone already took the bit. Repeat the search | ||
| 972 | * with lock held. | ||
| 973 | */ | ||
| 974 | ret2 = find_inode_bit(sb, group, inode_bitmap_bh, &ino); | ||
| 975 | if (ret2) { | ||
| 976 | ext4_set_bit(ino, inode_bitmap_bh->b_data); | ||
| 977 | ret2 = 0; | ||
| 978 | } else { | ||
| 979 | ret2 = 1; /* we didn't grab the inode */ | ||
| 980 | } | ||
| 981 | } | ||
| 955 | ext4_unlock_group(sb, group); | 982 | ext4_unlock_group(sb, group); |
| 956 | ino++; /* the inode bitmap is zero-based */ | 983 | ino++; /* the inode bitmap is zero-based */ |
| 957 | if (!ret2) | 984 | if (!ret2) |
| 958 | goto got; /* we grabbed the inode! */ | 985 | goto got; /* we grabbed the inode! */ |
| 959 | next_inode: | 986 | |
| 960 | if (ino < EXT4_INODES_PER_GROUP(sb)) | 987 | if (ino < EXT4_INODES_PER_GROUP(sb)) |
| 961 | goto repeat_in_this_group; | 988 | goto repeat_in_this_group; |
| 962 | next_group: | 989 | next_group: |
| @@ -4897,14 +4897,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) · 4896 unmodified lines | |||
| 4897 | brelse(iloc.bh); | 4897 | brelse(iloc.bh); |
| 4898 | ext4_set_inode_flags(inode); | 4898 | ext4_set_inode_flags(inode); |
| 4899 | 4899 | ||
| 4900 | if (ei->i_flags & EXT4_EA_INODE_FL) { | ||
| 4901 | ext4_xattr_inode_set_class(inode); | ||
| 4902 | |||
| 4903 | inode_lock(inode); | ||
| 4904 | inode->i_flags |= S_NOQUOTA; | ||
| 4905 | inode_unlock(inode); | ||
| 4906 | } | ||
| 4907 | |||
| 4908 | unlock_new_inode(inode); | 4900 | unlock_new_inode(inode); |
| 4909 | return inode; | 4901 | return inode; |
| 4910 | 4902 | ||
| @@ -367,7 +367,7 @@ skip: · 366 unmodified lines | |||
| 367 | goto failed; | 367 | goto failed; |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | mmpd_data = kmalloc(sizeof(struct mmpd_data), GFP_KERNEL); | 370 | mmpd_data = kmalloc(sizeof(*mmpd_data), GFP_KERNEL); |
| 371 | if (!mmpd_data) { | 371 | if (!mmpd_data) { |
| 372 | ext4_warning(sb, "not enough memory for mmpd_data"); | 372 | ext4_warning(sb, "not enough memory for mmpd_data"); |
| 373 | goto failed; | 373 | goto failed; |
| @@ -2404,6 +2404,7 @@ static void ext4_orphan_cleanup(struct super_block *sb, · 2403 unmodified lines | |||
| 2404 | unsigned int s_flags = sb->s_flags; | 2404 | unsigned int s_flags = sb->s_flags; |
| 2405 | int ret, nr_orphans = 0, nr_truncates = 0; | 2405 | int ret, nr_orphans = 0, nr_truncates = 0; |
| 2406 | #ifdef CONFIG_QUOTA | 2406 | #ifdef CONFIG_QUOTA |
| 2407 | int quota_update = 0; | ||
| 2407 | int i; | 2408 | int i; |
| 2408 | #endif | 2409 | #endif |
| 2409 | if (!es->s_last_orphan) { | 2410 | if (!es->s_last_orphan) { |
| @@ -2442,14 +2443,32 @@ static void ext4_orphan_cleanup(struct super_block *sb, · 32 unmodified lines | |||
| 2442 | #ifdef CONFIG_QUOTA | 2443 | #ifdef CONFIG_QUOTA |
| 2443 | /* Needed for iput() to work correctly and not trash data */ | 2444 | /* Needed for iput() to work correctly and not trash data */ |
| 2444 | sb->s_flags |= MS_ACTIVE; | 2445 | sb->s_flags |= MS_ACTIVE; |
| 2445 | /* Turn on quotas so that they are updated correctly */ | 2446 | |
| 2447 | /* | ||
| 2448 | * Turn on quotas which were not enabled for read-only mounts if | ||
| 2449 | * filesystem has quota feature, so that they are updated correctly. | ||
| 2450 | */ | ||
| 2451 | if (ext4_has_feature_quota(sb) && (s_flags & MS_RDONLY)) { | ||
| 2452 | int ret = ext4_enable_quotas(sb); | ||
| 2453 | |||
| 2454 | if (!ret) | ||
| 2455 | quota_update = 1; | ||
| 2456 | else | ||
| 2457 | ext4_msg(sb, KERN_ERR, | ||
| 2458 | "Cannot turn on quotas: error %d", ret); | ||
| 2459 | } | ||
| 2460 | |||
| 2461 | /* Turn on journaled quotas used for old sytle */ | ||
| 2446 | for (i = 0; i < EXT4_MAXQUOTAS; i++) { | 2462 | for (i = 0; i < EXT4_MAXQUOTAS; i++) { |
| 2447 | if (EXT4_SB(sb)->s_qf_names[i]) { | 2463 | if (EXT4_SB(sb)->s_qf_names[i]) { |
| 2448 | int ret = ext4_quota_on_mount(sb, i); | 2464 | int ret = ext4_quota_on_mount(sb, i); |
| 2449 | if (ret < 0) | 2465 | |
| 2466 | if (!ret) | ||
| 2467 | quota_update = 1; | ||
| 2468 | else | ||
| 2450 | ext4_msg(sb, KERN_ERR, | 2469 | ext4_msg(sb, KERN_ERR, |
| 2451 | "Cannot turn on journaled " | 2470 | "Cannot turn on journaled " |
| 2452 | "quota: error %d", ret); | 2471 | "quota: type %d: error %d", i, ret); |
| 2453 | } | 2472 | } |
| 2454 | } | 2473 | } |
| 2455 | #endif | 2474 | #endif |
| @@ -2510,10 +2529,12 @@ static void ext4_orphan_cleanup(struct super_block *sb, · 54 unmodified lines | |||
| 2510 | ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up", | 2529 | ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up", |
| 2511 | PLURAL(nr_truncates)); | 2530 | PLURAL(nr_truncates)); |
| 2512 | #ifdef CONFIG_QUOTA | 2531 | #ifdef CONFIG_QUOTA |
| 2513 | /* Turn quotas off */ | 2532 | /* Turn off quotas if they were enabled for orphan cleanup */ |
| 2514 | for (i = 0; i < EXT4_MAXQUOTAS; i++) { | 2533 | if (quota_update) { |
| 2515 | if (sb_dqopt(sb)->files[i]) | 2534 | for (i = 0; i < EXT4_MAXQUOTAS; i++) { |
| 2516 | dquot_quota_off(sb, i); | 2535 | if (sb_dqopt(sb)->files[i]) |
| 2536 | dquot_quota_off(sb, i); | ||
| 2537 | } | ||
| 2517 | } | 2538 | } |
| 2518 | #endif | 2539 | #endif |
| 2519 | sb->s_flags = s_flags; /* Restore MS_RDONLY status */ | 2540 | sb->s_flags = s_flags; /* Restore MS_RDONLY status */ |
| @@ -5512,6 +5533,9 @@ static int ext4_enable_quotas(struct super_block *sb) · 2992 unmodified lines | |||
| 5512 | DQUOT_USAGE_ENABLED | | 5533 | DQUOT_USAGE_ENABLED | |
| 5513 | (quota_mopt[type] ? DQUOT_LIMITS_ENABLED : 0)); | 5534 | (quota_mopt[type] ? DQUOT_LIMITS_ENABLED : 0)); |
| 5514 | if (err) { | 5535 | if (err) { |
| 5536 | for (type--; type >= 0; type--) | ||
| 5537 | dquot_quota_off(sb, type); | ||
| 5538 | |||
| 5515 | ext4_warning(sb, | 5539 | ext4_warning(sb, |
| 5516 | "Failed to enable quota tracking " | 5540 | "Failed to enable quota tracking " |
| 5517 | "(type=%d, err=%d). Please run " | 5541 | "(type=%d, err=%d). Please run " |
| @@ -354,8 +354,10 @@ free_bhs: · 353 unmodified lines | |||
| 354 | return ret; | 354 | return ret; |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | #define EXT4_XATTR_INODE_GET_PARENT(inode) ((__u32)(inode)->i_mtime.tv_sec) | ||
| 358 | |||
| 357 | static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino, | 359 | static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino, |
| 358 | struct inode **ea_inode) | 360 | u32 ea_inode_hash, struct inode **ea_inode) |
| 359 | { | 361 | { |
| 360 | struct inode *inode; | 362 | struct inode *inode; |
| 361 | int err; | 363 | int err; |
| @@ -385,6 +387,24 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino, · 23 unmodified lines | |||
| 385 | goto error; | 387 | goto error; |
| 386 | } | 388 | } |
| 387 | 389 | ||
| 390 | ext4_xattr_inode_set_class(inode); | ||
| 391 | |||
| 392 | /* | ||
| 393 | * Check whether this is an old Lustre-style xattr inode. Lustre | ||
| 394 | * implementation does not have hash validation, rather it has a | ||
| 395 | * backpointer from ea_inode to the parent inode. | ||
| 396 | */ | ||
| 397 | if (ea_inode_hash != ext4_xattr_inode_get_hash(inode) && | ||
| 398 | EXT4_XATTR_INODE_GET_PARENT(inode) == parent->i_ino && | ||
| 399 | inode->i_generation == parent->i_generation) { | ||
| 400 | ext4_set_inode_state(inode, EXT4_STATE_LUSTRE_EA_INODE); | ||
| 401 | ext4_xattr_inode_set_ref(inode, 1); | ||
| 402 | } else { | ||
| 403 | inode_lock(inode); | ||
| 404 | inode->i_flags |= S_NOQUOTA; | ||
| 405 | inode_unlock(inode); | ||
| 406 | } | ||
| 407 | |||
| 388 | *ea_inode = inode; | 408 | *ea_inode = inode; |
| 389 | return 0; | 409 | return 0; |
| 390 | error: | 410 | error: |
| @@ -417,8 +437,6 @@ ext4_xattr_inode_verify_hashes(struct inode *ea_inode, · 26 unmodified lines | |||
| 417 | return 0; | 437 | return 0; |
| 418 | } | 438 | } |
| 419 | 439 | ||
| 420 | #define EXT4_XATTR_INODE_GET_PARENT(inode) ((__u32)(inode)->i_mtime.tv_sec) | ||
| 421 | |||
| 422 | /* | 440 | /* |
| 423 | * Read xattr value from the EA inode. | 441 | * Read xattr value from the EA inode. |
| 424 | */ | 442 | */ |
| @@ -431,7 +449,7 @@ ext4_xattr_inode_get(struct inode *inode, struct ext4_xattr_entry *entry, · 6 unmodified lines | |||
| 431 | int err; | 449 | int err; |
| 432 | 450 | ||
| 433 | err = ext4_xattr_inode_iget(inode, le32_to_cpu(entry->e_value_inum), | 451 | err = ext4_xattr_inode_iget(inode, le32_to_cpu(entry->e_value_inum), |
| 434 | &ea_inode); | 452 | le32_to_cpu(entry->e_hash), &ea_inode); |
| 435 | if (err) { | 453 | if (err) { |
| 436 | ea_inode = NULL; | 454 | ea_inode = NULL; |
| 437 | goto out; | 455 | goto out; |
| @@ -449,29 +467,20 @@ ext4_xattr_inode_get(struct inode *inode, struct ext4_xattr_entry *entry, · 11 unmodified lines | |||
| 449 | if (err) | 467 | if (err) |
| 450 | goto out; | 468 | goto out; |
| 451 | 469 | ||
| 452 | err = ext4_xattr_inode_verify_hashes(ea_inode, entry, buffer, size); | 470 | if (!ext4_test_inode_state(ea_inode, EXT4_STATE_LUSTRE_EA_INODE)) { |
| 453 | /* | 471 | err = ext4_xattr_inode_verify_hashes(ea_inode, entry, buffer, |
| 454 | * Compatibility check for old Lustre ea_inode implementation. Old | 472 | size); |
| 455 | * version does not have hash validation, but it has a backpointer | 473 | if (err) { |
| 456 | * from ea_inode to the parent inode. | ||
| 457 | */ | ||
| 458 | if (err == -EFSCORRUPTED) { | ||
| 459 | if (EXT4_XATTR_INODE_GET_PARENT(ea_inode) != inode->i_ino || | ||
| 460 | ea_inode->i_generation != inode->i_generation) { | ||
| 461 | ext4_warning_inode(ea_inode, | 474 | ext4_warning_inode(ea_inode, |
| 462 | "EA inode hash validation failed"); | 475 | "EA inode hash validation failed"); |
| 463 | goto out; | 476 | goto out; |
| 464 | } | 477 | } |
| 465 | /* Do not add ea_inode to the cache. */ | ||
| 466 | ea_inode_cache = NULL; | ||
| 467 | err = 0; | ||
| 468 | } else if (err) | ||
| 469 | goto out; | ||
| 470 | 478 | ||
| 471 | if (ea_inode_cache) | 479 | if (ea_inode_cache) |
| 472 | mb_cache_entry_create(ea_inode_cache, GFP_NOFS, | 480 | mb_cache_entry_create(ea_inode_cache, GFP_NOFS, |
| 473 | ext4_xattr_inode_get_hash(ea_inode), | 481 | ext4_xattr_inode_get_hash(ea_inode), |
| 474 | ea_inode->i_ino, true /* reusable */); | 482 | ea_inode->i_ino, true /* reusable */); |
| 483 | } | ||
| 475 | out: | 484 | out: |
| 476 | iput(ea_inode); | 485 | iput(ea_inode); |
| 477 | return err; | 486 | return err; |
| @@ -838,10 +847,15 @@ static int ext4_xattr_inode_alloc_quota(struct inode *inode, size_t len) · 360 unmodified lines | |||
| 838 | return err; | 847 | return err; |
| 839 | } | 848 | } |
| 840 | 849 | ||
| 841 | static void ext4_xattr_inode_free_quota(struct inode *inode, size_t len) | 850 | static void ext4_xattr_inode_free_quota(struct inode *parent, |
| 851 | struct inode *ea_inode, | ||
| 852 | size_t len) | ||
| 842 | { | 853 | { |
| 843 | dquot_free_space_nodirty(inode, round_up_cluster(inode, len)); | 854 | if (ea_inode && |
| 844 | dquot_free_inode(inode); | 855 | ext4_test_inode_state(ea_inode, EXT4_STATE_LUSTRE_EA_INODE)) |
| 856 | return; | ||
| 857 | dquot_free_space_nodirty(parent, round_up_cluster(parent, len)); | ||
| 858 | dquot_free_inode(parent); | ||
| 845 | } | 859 | } |
| 846 | 860 | ||
| 847 | int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode, | 861 | int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode, |
| @@ -1071,7 +1085,9 @@ static int ext4_xattr_inode_inc_ref_all(handle_t *handle, struct inode *parent, · 223 unmodified lines | |||
| 1071 | if (!entry->e_value_inum) | 1085 | if (!entry->e_value_inum) |
| 1072 | continue; | 1086 | continue; |
| 1073 | ea_ino = le32_to_cpu(entry->e_value_inum); | 1087 | ea_ino = le32_to_cpu(entry->e_value_inum); |
| 1074 | err = ext4_xattr_inode_iget(parent, ea_ino, &ea_inode); | 1088 | err = ext4_xattr_inode_iget(parent, ea_ino, |
| 1089 | le32_to_cpu(entry->e_hash), | ||
| 1090 | &ea_inode); | ||
| 1075 | if (err) | 1091 | if (err) |
| 1076 | goto cleanup; | 1092 | goto cleanup; |
| 1077 | err = ext4_xattr_inode_inc_ref(handle, ea_inode); | 1093 | err = ext4_xattr_inode_inc_ref(handle, ea_inode); |
| @@ -1093,7 +1109,9 @@ cleanup: · 15 unmodified lines | |||
| 1093 | if (!entry->e_value_inum) | 1109 | if (!entry->e_value_inum) |
| 1094 | continue; | 1110 | continue; |
| 1095 | ea_ino = le32_to_cpu(entry->e_value_inum); | 1111 | ea_ino = le32_to_cpu(entry->e_value_inum); |
| 1096 | err = ext4_xattr_inode_iget(parent, ea_ino, &ea_inode); | 1112 | err = ext4_xattr_inode_iget(parent, ea_ino, |
| 1113 | le32_to_cpu(entry->e_hash), | ||
| 1114 | &ea_inode); | ||
| 1097 | if (err) { | 1115 | if (err) { |
| 1098 | ext4_warning(parent->i_sb, | 1116 | ext4_warning(parent->i_sb, |
| 1099 | "cleanup ea_ino %u iget error %d", ea_ino, | 1117 | "cleanup ea_ino %u iget error %d", ea_ino, |
| @@ -1131,7 +1149,9 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent, · 31 unmodified lines | |||
| 1131 | if (!entry->e_value_inum) | 1149 | if (!entry->e_value_inum) |
| 1132 | continue; | 1150 | continue; |
| 1133 | ea_ino = le32_to_cpu(entry->e_value_inum); | 1151 | ea_ino = le32_to_cpu(entry->e_value_inum); |
| 1134 | err = ext4_xattr_inode_iget(parent, ea_ino, &ea_inode); | 1152 | err = ext4_xattr_inode_iget(parent, ea_ino, |
| 1153 | le32_to_cpu(entry->e_hash), | ||
| 1154 | &ea_inode); | ||
| 1135 | if (err) | 1155 | if (err) |
| 1136 | continue; | 1156 | continue; |
| 1137 | 1157 | ||
| @@ -1159,7 +1179,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent, · 21 unmodified lines | |||
| 1159 | } | 1179 | } |
| 1160 | 1180 | ||
| 1161 | if (!skip_quota) | 1181 | if (!skip_quota) |
| 1162 | ext4_xattr_inode_free_quota(parent, | 1182 | ext4_xattr_inode_free_quota(parent, ea_inode, |
| 1163 | le32_to_cpu(entry->e_value_size)); | 1183 | le32_to_cpu(entry->e_value_size)); |
| 1164 | 1184 | ||
| 1165 | /* | 1185 | /* |
| @@ -1591,6 +1611,7 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, · 425 unmodified lines | |||
| 1591 | if (!s->not_found && here->e_value_inum) { | 1611 | if (!s->not_found && here->e_value_inum) { |
| 1592 | ret = ext4_xattr_inode_iget(inode, | 1612 | ret = ext4_xattr_inode_iget(inode, |
| 1593 | le32_to_cpu(here->e_value_inum), | 1613 | le32_to_cpu(here->e_value_inum), |
| 1614 | le32_to_cpu(here->e_hash), | ||
| 1594 | &old_ea_inode); | 1615 | &old_ea_inode); |
| 1595 | if (ret) { | 1616 | if (ret) { |
| 1596 | old_ea_inode = NULL; | 1617 | old_ea_inode = NULL; |
| @@ -1609,7 +1630,7 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, · 12 unmodified lines | |||
| 1609 | &new_ea_inode); | 1630 | &new_ea_inode); |
| 1610 | if (ret) { | 1631 | if (ret) { |
| 1611 | new_ea_inode = NULL; | 1632 | new_ea_inode = NULL; |
| 1612 | ext4_xattr_inode_free_quota(inode, i->value_len); | 1633 | ext4_xattr_inode_free_quota(inode, NULL, i->value_len); |
| 1613 | goto out; | 1634 | goto out; |
| 1614 | } | 1635 | } |
| 1615 | } | 1636 | } |
| @@ -1628,13 +1649,13 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, · 12 unmodified lines | |||
| 1628 | ext4_warning_inode(new_ea_inode, | 1649 | ext4_warning_inode(new_ea_inode, |
| 1629 | "dec ref new_ea_inode err=%d", | 1650 | "dec ref new_ea_inode err=%d", |
| 1630 | err); | 1651 | err); |
| 1631 | ext4_xattr_inode_free_quota(inode, | 1652 | ext4_xattr_inode_free_quota(inode, new_ea_inode, |
| 1632 | i->value_len); | 1653 | i->value_len); |
| 1633 | } | 1654 | } |
| 1634 | goto out; | 1655 | goto out; |
| 1635 | } | 1656 | } |
| 1636 | 1657 | ||
| 1637 | ext4_xattr_inode_free_quota(inode, | 1658 | ext4_xattr_inode_free_quota(inode, old_ea_inode, |
| 1638 | le32_to_cpu(here->e_value_size)); | 1659 | le32_to_cpu(here->e_value_size)); |
| 1639 | } | 1660 | } |
| 1640 | 1661 | ||
| @@ -1805,8 +1826,10 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, · 164 unmodified lines | |||
| 1805 | struct mb_cache_entry *ce = NULL; | 1826 | struct mb_cache_entry *ce = NULL; |
| 1806 | int error = 0; | 1827 | int error = 0; |
| 1807 | struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode); | 1828 | struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode); |
| 1808 | struct inode *ea_inode = NULL; | 1829 | struct inode *ea_inode = NULL, *tmp_inode; |
| 1809 | size_t old_ea_inode_size = 0; | 1830 | size_t old_ea_inode_quota = 0; |
| 1831 | unsigned int ea_ino; | ||
| 1832 | |||
| 1810 | 1833 | ||
| 1811 | #define header(x) ((struct ext4_xattr_header *)(x)) | 1834 | #define header(x) ((struct ext4_xattr_header *)(x)) |
| 1812 | 1835 | ||
| @@ -1865,12 +1888,24 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, · 52 unmodified lines | |||
| 1865 | * like it has an empty value. | 1888 | * like it has an empty value. |
| 1866 | */ | 1889 | */ |
| 1867 | if (!s->not_found && s->here->e_value_inum) { | 1890 | if (!s->not_found && s->here->e_value_inum) { |
| 1868 | /* | 1891 | ea_ino = le32_to_cpu(s->here->e_value_inum); |
| 1869 | * Defer quota free call for previous inode | 1892 | error = ext4_xattr_inode_iget(inode, ea_ino, |
| 1870 | * until success is guaranteed. | 1893 | le32_to_cpu(s->here->e_hash), |
| 1871 | */ | 1894 | &tmp_inode); |
| 1872 | old_ea_inode_size = le32_to_cpu( | 1895 | if (error) |
| 1896 | goto cleanup; | ||
| 1897 | |||
| 1898 | if (!ext4_test_inode_state(tmp_inode, | ||
| 1899 | EXT4_STATE_LUSTRE_EA_INODE)) { | ||
| 1900 | /* | ||
| 1901 | * Defer quota free call for previous | ||
| 1902 | * inode until success is guaranteed. | ||
| 1903 | */ | ||
| 1904 | old_ea_inode_quota = le32_to_cpu( | ||
| 1873 | s->here->e_value_size); | 1905 | s->here->e_value_size); |
| 1906 | } | ||
| 1907 | iput(tmp_inode); | ||
| 1908 | |||
| 1874 | s->here->e_value_inum = 0; | 1909 | s->here->e_value_inum = 0; |
| 1875 | s->here->e_value_size = 0; | 1910 | s->here->e_value_size = 0; |
| 1876 | } | 1911 | } |
| @@ -1897,8 +1932,6 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, · 20 unmodified lines | |||
| 1897 | goto cleanup; | 1932 | goto cleanup; |
| 1898 | 1933 | ||
| 1899 | if (i->value && s->here->e_value_inum) { | 1934 | if (i->value && s->here->e_value_inum) { |
| 1900 | unsigned int ea_ino; | ||
| 1901 | |||
| 1902 | /* | 1935 | /* |
| 1903 | * A ref count on ea_inode has been taken as part of the call to | 1936 | * A ref count on ea_inode has been taken as part of the call to |
| 1904 | * ext4_xattr_set_entry() above. We would like to drop this | 1937 | * ext4_xattr_set_entry() above. We would like to drop this |
| @@ -1906,7 +1939,9 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, · 1 unmodified line | |||
| 1906 | * initialized and has its own ref count on the ea_inode. | 1939 | * initialized and has its own ref count on the ea_inode. |
| 1907 | */ | 1940 | */ |
| 1908 | ea_ino = le32_to_cpu(s->here->e_value_inum); | 1941 | ea_ino = le32_to_cpu(s->here->e_value_inum); |
| 1909 | error = ext4_xattr_inode_iget(inode, ea_ino, &ea_inode); | 1942 | error = ext4_xattr_inode_iget(inode, ea_ino, |
| 1943 | le32_to_cpu(s->here->e_hash), | ||
| 1944 | &ea_inode); | ||
| 1910 | if (error) { | 1945 | if (error) { |
| 1911 | ea_inode = NULL; | 1946 | ea_inode = NULL; |
| 1912 | goto cleanup; | 1947 | goto cleanup; |
| @@ -2056,8 +2091,8 @@ getblk_failed: · 143 unmodified lines | |||
| 2056 | } | 2091 | } |
| 2057 | } | 2092 | } |
| 2058 | 2093 | ||
| 2059 | if (old_ea_inode_size) | 2094 | if (old_ea_inode_quota) |
| 2060 | ext4_xattr_inode_free_quota(inode, old_ea_inode_size); | 2095 | ext4_xattr_inode_free_quota(inode, NULL, old_ea_inode_quota); |
| 2061 | 2096 | ||
| 2062 | /* Update the inode. */ | 2097 | /* Update the inode. */ |
| 2063 | EXT4_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; | 2098 | EXT4_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; |
| @@ -2084,7 +2119,7 @@ cleanup: · 20 unmodified lines | |||
| 2084 | 2119 | ||
| 2085 | /* If there was an error, revert the quota charge. */ | 2120 | /* If there was an error, revert the quota charge. */ |
| 2086 | if (error) | 2121 | if (error) |
| 2087 | ext4_xattr_inode_free_quota(inode, | 2122 | ext4_xattr_inode_free_quota(inode, ea_inode, |
| 2088 | i_size_read(ea_inode)); | 2123 | i_size_read(ea_inode)); |
| 2089 | iput(ea_inode); | 2124 | iput(ea_inode); |
| 2090 | } | 2125 | } |
| @@ -2800,6 +2835,7 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, · 709 unmodified lines | |||
| 2800 | struct ext4_xattr_ibody_header *header; | 2835 | struct ext4_xattr_ibody_header *header; |
| 2801 | struct ext4_iloc iloc = { .bh = NULL }; | 2836 | struct ext4_iloc iloc = { .bh = NULL }; |
| 2802 | struct ext4_xattr_entry *entry; | 2837 | struct ext4_xattr_entry *entry; |
| 2838 | struct inode *ea_inode; | ||
| 2803 | int error; | 2839 | int error; |
| 2804 | 2840 | ||
| 2805 | error = ext4_xattr_ensure_credits(handle, inode, extra_credits, | 2841 | error = ext4_xattr_ensure_credits(handle, inode, extra_credits, |
| @@ -2854,10 +2890,19 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, · 48 unmodified lines | |||
| 2854 | 2890 | ||
| 2855 | if (ext4_has_feature_ea_inode(inode->i_sb)) { | 2891 | if (ext4_has_feature_ea_inode(inode->i_sb)) { |
| 2856 | for (entry = BFIRST(bh); !IS_LAST_ENTRY(entry); | 2892 | for (entry = BFIRST(bh); !IS_LAST_ENTRY(entry); |
| 2857 | entry = EXT4_XATTR_NEXT(entry)) | 2893 | entry = EXT4_XATTR_NEXT(entry)) { |
| 2858 | if (entry->e_value_inum) | 2894 | if (!entry->e_value_inum) |
| 2859 | ext4_xattr_inode_free_quota(inode, | 2895 | continue; |
| 2896 | error = ext4_xattr_inode_iget(inode, | ||
| 2897 | le32_to_cpu(entry->e_value_inum), | ||
| 2898 | le32_to_cpu(entry->e_hash), | ||
| 2899 | &ea_inode); | ||
| 2900 | if (error) | ||
| 2901 | continue; | ||
| 2902 | ext4_xattr_inode_free_quota(inode, ea_inode, | ||
| 2860 | le32_to_cpu(entry->e_value_size)); | 2903 | le32_to_cpu(entry->e_value_size)); |
| 2904 | iput(ea_inode); | ||
| 2905 | } | ||
| 2861 | 2906 | ||
| 2862 | } | 2907 | } |
| 2863 | 2908 | ||
| @@ -285,4 +285,19 @@ static inline bool itimerspec64_valid(const struct itimerspec64 *its) · 284 unmodified lines | |||
| 285 | return true; | 285 | return true; |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | /** | ||
| 289 | * time_after32 - compare two 32-bit relative times | ||
| 290 | * @a: the time which may be after @b | ||
| 291 | * @b: the time which may be before @a | ||
| 292 | * | ||
| 293 | * time_after32(a, b) returns true if the time @a is after time @b. | ||
| 294 | * time_before32(b, a) returns true if the time @b is before time @a. | ||
| 295 | * | ||
| 296 | * Similar to time_after(), compare two 32-bit timestamps for relative | ||
| 297 | * times. This is useful for comparing 32-bit seconds values that can't | ||
| 298 | * be converted to 64-bit values (e.g. due to disk format or wire protocol | ||
| 299 | * issues) when it is known that the times are less than 68 years apart. | ||
| 300 | */ | ||
| 301 | #define time_after32(a, b) ((s32)((u32)(b) - (u32)(a)) < 0) | ||
| 302 | #define time_before32(b, a) time_after32(a, b) | ||
| 288 | #endif | 303 | #endif |