Test bit before clear close_on_exec and open_fds, by trace __clear_bit(), these 2 place are false in most times, we test it so that we don't need clear_bit, and we can win in most time. Add *_if_need bitop non-atomic version. Signed-off-by: Yalin Wang <yalin.wang@xxxxxxxxxxxxxx> --- fs/file.c | 9 +++++++-- include/asm-generic/bitops/non-atomic.h | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/fs/file.c b/fs/file.c index ee738ea..2e08e6f 100644 --- a/fs/file.c +++ b/fs/file.c @@ -209,7 +209,7 @@ static inline void __set_close_on_exec(int fd, struct fdtable *fdt) static inline void __clear_close_on_exec(int fd, struct fdtable *fdt) { - __clear_bit(fd, fdt->close_on_exec); + __clear_bit_if_need(fd, fdt->close_on_exec); } static inline void __set_open_fd(int fd, struct fdtable *fdt) @@ -222,6 +222,11 @@ static inline void __clear_open_fd(int fd, struct fdtable *fdt) __clear_bit(fd, fdt->open_fds); } +static inline void __clear_open_fd_if_need(int fd, struct fdtable *fdt) +{ + __clear_bit_if_need(fd, fdt->open_fds); +} + static int count_open_files(struct fdtable *fdt) { int size = fdt->max_fds; @@ -316,7 +321,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) * is partway through open(). So make sure that this * fd is available to the new process. */ - __clear_open_fd(open_files - i, new_fdt); + __clear_open_fd_if_need(open_files - i, new_fdt); } rcu_assign_pointer(*new_fds++, f); } diff --git a/include/asm-generic/bitops/non-atomic.h b/include/asm-generic/bitops/non-atomic.h index 697cc2b..0713e3b 100644 --- a/include/asm-generic/bitops/non-atomic.h +++ b/include/asm-generic/bitops/non-atomic.h @@ -105,4 +105,39 @@ static inline int test_bit(int nr, const volatile unsigned long *addr) return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); } +/* + * __*_if_need version is used in cases that you don't want write a bit which + * have been set / clear, to avoid dirty cacheline. + */ +static inline void __set_bit_if_need(int nr, volatile unsigned long *addr) +{ + if (!test_bit(nr, addr)) + __set_bit(nr, addr); +} + +static inline void __clear_bit_if_need(int nr, volatile unsigned long *addr) +{ + if (test_bit(nr, addr)) + __clear_bit(nr, addr); +} + +static inline int __test_and_set_bit_if_need(int nr, volatile unsigned long *addr) +{ + if (!test_bit(nr, addr)) { + __set_bit(nr, addr); + return false; + } else { + return true; + } +} + +static inline int __test_and_clear_bit_if_need(int nr, volatile unsigned long *addr) +{ + if (test_bit(nr, addr)) { + __clear_bit(nr, addr); + return true; + } else { + return false; + } +} #endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */ -- 2.2.2 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html