On Thu, Jan 12, 2023 at 06:09:16AM -0800, Christoph Hellwig wrote: > On Thu, Jan 12, 2023 at 10:28:41AM +0000, David Howells wrote: > > Christoph Hellwig <hch@xxxxxxxxxxxxx> wrote: > > > > > if (cleanup_mode & FOLL_GET) { > > > WARN_ON_ONCE(bio_test_flag(bio, BIO_PAGE_PINNED)); > > > bio_set_flag(bio, BIO_PAGE_REFFED); > > > } > > > if (cleanup_mode & FOLL_PIN) { > > > WARN_ON_ONCE(bio_test_flag(bio, BIO_PAGE_REFFED)); > > > bio_set_flag(bio, BIO_PAGE_PINNED); > > > } > > > > That won't necessarily work as you might get back cleanup_mode == 0, in which > > case both flags are cleared - and neither warning will trip on the next > > addition. > > Well, it will work for the intended use case even with > cleanup_mode == 0, we just won't get the debug check. Or am I missing > something fundamental? In fact looking at the code we can debug check that case too by doing: if (cleanup_mode & FOLL_GET) { WARN_ON_ONCE(bio_test_flag(bio, BIO_PAGE_PINNED)); bio_set_flag(bio, BIO_PAGE_REFFED); } else if (cleanup_mode & FOLL_PIN) { WARN_ON_ONCE(bio_test_flag(bio, BIO_PAGE_REFFED)); bio_set_flag(bio, BIO_PAGE_PINNED); } else { WARN_ON_ONCE(bio_test_flag(bio, BIO_PAGE_PINNED) || bio_test_flag(bio, BIO_PAGE_REFFED)); } But given that all calls for the same iter type return the same cleanup_mode by defintion I'm not even sure we need any of this debug checking, and might as well just do: if (cleanup_mode & FOLL_GET) bio_set_flag(bio, BIO_PAGE_REFFED); else if (cleanup_mode & FOLL_PIN) bio_set_flag(bio, BIO_PAGE_PINNED);