On Mon, Aug 26, 2019 at 08:28:19PM +0100, Al Viro wrote: > On Mon, Aug 26, 2019 at 11:20:17AM -0700, Matthew Wilcox wrote: > > On Mon, Aug 26, 2019 at 05:29:49PM +0100, Al Viro wrote: > > > On Mon, Aug 26, 2019 at 03:48:38AM +0100, Al Viro wrote: > > > > > > > We might be able to paper over that mess by doing what /dev/st does - > > > > checking that file_count(file) == 1 in ->flush() instance and doing commit > > > > there in such case. It's not entirely reliable, though, and it's definitely > > > > not something I'd like to see spreading. > > > > > > This "not entirely reliable" turns out to be an understatement. > > > If you have /proc/*/fdinfo/* being read from at the time of final close(2), > > > you'll get file_count(file) > 1 the last time ->flush() is called. In other > > > words, we'd get the data not committed at all. How about something like this: #if BITS_PER_LONG == 32 #define F_COUNT_SHORTTERM ((1UL << 24) + 1) #else #define F_COUNT_SHORTTERM ((1UL << 48) + 1) #endif static inline void get_file_shortterm(struct file *f) { atomic_long_add(F_COUNT_SHORTTERM, &f->f_count); } static inline void put_file_shortterm(struct file *f) { fput_many(f, F_COUNT_SHORTTERM); } static inline bool file_is_last_longterm(struct file *f) { return atomic_long_read(&f->f_count) % F_COUNT_SHORTTERM == 1; } Thanks, Miklos