On Tue, 12 Apr 2022, Linus Torvalds wrote: > On Mon, Apr 11, 2022 at 11:41 PM Mikulas Patocka <mpatocka@xxxxxxxxxx> wrote: > > > > Also, if the st_dev and st_rdev values are 32-bit, we don't have to use > > old_valid_dev to test if the value fits into them. This fixes -EOVERFLOW > > on filesystems that are on NVMe because NVMe uses the major number 259. > > The problem with this part of the patch is that this: > > > @@ -353,7 +352,7 @@ static int cp_new_stat(struct kstat *sta > > #endif > > > > INIT_STRUCT_STAT_PADDING(tmp); > > - tmp.st_dev = encode_dev(stat->dev); > > + tmp.st_dev = new_encode_dev(stat->dev); > > completely changes the format of that st_dev field. we have these definitions: static __always_inline u16 old_encode_dev(dev_t dev) { return (MAJOR(dev) << 8) | MINOR(dev); } static __always_inline u32 new_encode_dev(dev_t dev) { unsigned major = MAJOR(dev); unsigned minor = MINOR(dev); return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); } As long as both major and minor numbers are less than 256, these functions return equivalent results. So, I think it's safe to replace old_encode_dev with new_encode_dev. old_encode_dev shouldn't be called with minor >= 256, because it blends the upper minor bits into the major field - the kernel doesn't do this and checks the value with old_valid_dev before calling old_encode_dev. But when old_valid_dev returns true, it doesn't matter if you use old_encode_dev or new_encode_dev - both give equivalent results. When I tested it, both gcc and openwatcom return st_dev 0x10301, which is the expected value (the NVMe device has major 259 and minor 1). > (b) we could just hide the bits in upper bits instead. > > So what I suggest we do is to make old_encode_dev() put the minor bits > in bits 0..7 _and_ 16..23, and the major bits in 8..15 _and_ 24..32. new_encode_dev puts the minor value into bits 0..7, 20..31 and the major value into bits 8..19 So, we can use this instead of inventing a new format. Mikulas