[RFC PATCH] vfs: Use 12:20 bit major:minor in stat everywhere

From: Dan Ehrenberg
Date: Tue Mar 03 2015 - 19:38:01 EST


Previously, stat on 32-bit platforms used old-style encoding and
validation of major-minor pairs, with 8:8 bits. However, dev_t is
32-bits on these platforms, and coreutils seems to be treating the
values as 12:20 new-style values. The only reason to use the old
version is in the implementation of a legacy filesystem format which
only has 16 bits of space. Communicating a 12:20 value to userspace
when sizeof dev_t == 4 can be done on either a 32-bit or 64-bit
platform.

This patch removes the artificial restriction in major:minor size.
The only backwards incompatibility which results is sometimes stat
succeeds if -EOVERFLOW would be returned otherwise. The legacy
old-style stat call is retained as-is.

Signed-off-by: Dan Ehrenberg <dehrenberg@xxxxxxxxxxxx>
---
fs/stat.c | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/fs/stat.c b/fs/stat.c
index ae0c3ce..0a08e83 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -213,15 +213,6 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat

#endif /* __ARCH_WANT_OLD_STAT */

-#if BITS_PER_LONG == 32
-# define choose_32_64(a,b) a
-#else
-# define choose_32_64(a,b) b
-#endif
-
-#define valid_dev(x) choose_32_64(old_valid_dev,new_valid_dev)(x)
-#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)
-
#ifndef INIT_STRUCT_STAT_PADDING
# define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
#endif
@@ -230,7 +221,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
{
struct stat tmp;

- if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
+ if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
return -EOVERFLOW;
#if BITS_PER_LONG == 32
if (stat->size > MAX_NON_LFS)
@@ -238,7 +229,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
#endif

INIT_STRUCT_STAT_PADDING(tmp);
- tmp.st_dev = encode_dev(stat->dev);
+ tmp.st_dev = new_encode_dev(stat->dev);
tmp.st_ino = stat->ino;
if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
return -EOVERFLOW;
@@ -248,7 +239,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
return -EOVERFLOW;
SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
- tmp.st_rdev = encode_dev(stat->rdev);
+ tmp.st_rdev = new_encode_dev(stat->rdev);
tmp.st_size = stat->size;
tmp.st_atime = stat->atime.tv_sec;
tmp.st_mtime = stat->mtime.tv_sec;
--
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/