From f1af92e7fc249fd4ce54f0c61b04388a3b0da6bb Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Mon, 21 Nov 2016 09:22:52 -0600 Subject: [PATCH] LU-8855 llite: return small device numbers for compat stat() The compat_sys_*stat*() syscalls will fail unless the devices majors and minors are both less than 256. So in ll_getattr_it(), if we are in 32 bit compat mode then coerce the device numbers in to the expected format. Signed-off-by: John L. Hammond Change-Id: I1bf13258902e13c76b9ebf3476fd1767712de0b3 Reviewed-on: https://review.whamcloud.com/23877 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin Reviewed-by: Andreas Dilger --- lustre/llite/file.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 6f2fe92..95d1598 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -3557,6 +3557,18 @@ ll_inode_revalidate(struct dentry *dentry, __u64 ibits) RETURN(rc); } +static inline dev_t ll_compat_encode_dev(dev_t dev) +{ + /* The compat_sys_*stat*() syscalls will fail unless the + * device majors and minors are both less than 256. Note that + * the value returned here will be passed through + * old_encode_dev() in cp_compat_stat(). And so we are not + * trying to return a valid compat (u16) device number, just + * one that will pass the old_valid_dev() check. */ + + return MKDEV(MAJOR(dev) & 0xff, MINOR(dev) & 0xff); +} + int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) { struct inode *inode = de->d_inode; @@ -3573,15 +3585,19 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) OBD_FAIL_TIMEOUT(OBD_FAIL_GETATTR_DELAY, 30); - stat->dev = inode->i_sb->s_dev; - if (ll_need_32bit_api(sbi)) + if (ll_need_32bit_api(sbi)) { stat->ino = cl_fid_build_ino(&lli->lli_fid, 1); - else + stat->dev = ll_compat_encode_dev(inode->i_sb->s_dev); + stat->rdev = ll_compat_encode_dev(inode->i_rdev); + } else { stat->ino = inode->i_ino; + stat->dev = inode->i_sb->s_dev; + stat->rdev = inode->i_rdev; + } + stat->mode = inode->i_mode; stat->uid = inode->i_uid; stat->gid = inode->i_gid; - stat->rdev = inode->i_rdev; stat->atime = inode->i_atime; stat->mtime = inode->i_mtime; stat->ctime = inode->i_ctime; -- 1.8.3.1