From: Andreas Dilger Date: Mon, 31 Oct 2011 20:14:27 +0000 (-0600) Subject: LU-808 llite: deny truncate beyond user rlimit X-Git-Tag: 2.2.51~32 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=a44174684d800d74d35d9eb0b1b65bcfd0dd8163 LU-808 llite: deny truncate beyond user rlimit Add a call to inode_newsize_ok() in ll_setattr_raw() to ensure that the file is not truncated beyond the VFS/VM maximum limits or the user maximum file size, as set by rlimit. Replace the PAGE_CACHE_MAXBYTES constant with MAX_LFS_FILESIZE, which is already defined by the VFS. Signed-off-by: Andreas Dilger Change-Id: I6b4f03820dd59d6b1c3429e9bbfea62c50206cc9 Reviewed-on: http://review.whamcloud.com/1635 Reviewed-by: Jinshan Xiong Tested-by: Hudson Reviewed-by: Bobi Jam Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lustre_lite.h b/lustre/include/lustre_lite.h index 4309c87..6b17d26 100644 --- a/lustre/include/lustre_lite.h +++ b/lustre/include/lustre_lite.h @@ -60,13 +60,6 @@ #include #include -#ifdef __KERNEL__ - -/* careful, this is easy to screw up */ -#define PAGE_CACHE_MAXBYTES ((__u64)(~0UL) << CFS_PAGE_SHIFT) - -#endif - /* 4UL * 1024 * 1024 */ #define LL_MAX_BLKSIZE_BITS (22) #define LL_MAX_BLKSIZE (1UL<index is a long and * 32-bit systems are therefore limited to 16TB in a mapping */ -#define PAGE_CACHE_MAXBYTES ((__u64)(~0UL) << CFS_PAGE_SHIFT) +#define MAX_LFS_FILESIZE ((__u64)(~0UL) << CFS_PAGE_SHIFT) struct ll_file_data { struct obd_client_handle fd_mds_och; __u32 fd_flags; diff --git a/lustre/liblustre/super.c b/lustre/liblustre/super.c index 6b738f4..8d03a8e 100644 --- a/lustre/liblustre/super.c +++ b/lustre/liblustre/super.c @@ -153,8 +153,8 @@ void llu_update_inode(struct inode *inode, struct lustre_md *md) cl_file_inode_init(inode, md); lli->lli_smd = lsm; lli->lli_maxbytes = lsm->lsm_maxbytes; - if (lli->lli_maxbytes > PAGE_CACHE_MAXBYTES) - lli->lli_maxbytes = PAGE_CACHE_MAXBYTES; + if (lli->lli_maxbytes > MAX_LFS_FILESIZE) + lli->lli_maxbytes = MAX_LFS_FILESIZE; } else { if (lov_stripe_md_cmp(lli->lli_smd, lsm)) { CERROR("lsm mismatch for inode %lld\n", diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 48c5097..8a2d3fb 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -316,20 +316,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sb->s_blocksize = osfs->os_bsize; sb->s_blocksize_bits = log2(osfs->os_bsize); sb->s_magic = LL_SUPER_MAGIC; - - /* for bug 11559. in $LINUX/fs/read_write.c, function do_sendfile(): - * retval = in_file->f_op->sendfile(...); - * if (*ppos > max) - * retval = -EOVERFLOW; - * - * it will check if *ppos is greater than max. However, max equals to - * s_maxbytes, which is a negative integer in a x86_64 box since loff_t - * has been defined as a signed long long integer in linux kernel. */ -#if BITS_PER_LONG == 64 - sb->s_maxbytes = PAGE_CACHE_MAXBYTES >> 1; -#else - sb->s_maxbytes = PAGE_CACHE_MAXBYTES; -#endif + sb->s_maxbytes = MAX_LFS_FILESIZE; sbi->ll_namelen = osfs->os_namelen; sbi->ll_max_rw_chunk = LL_DEFAULT_MAX_RW_CHUNK; @@ -857,6 +844,7 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_inode_magic = LLI_INODE_MAGIC; lli->lli_flags = 0; lli->lli_ioepoch = 0; + lli->lli_maxbytes = MAX_LFS_FILESIZE; cfs_spin_lock_init(&lli->lli_lock); lli->lli_posix_acl = NULL; lli->lli_remote_perms = NULL; @@ -893,7 +881,6 @@ void ll_lli_init(struct ll_inode_info *lli) cfs_sema_init(&lli->lli_size_sem, 1); lli->lli_size_sem_owner = NULL; lli->lli_symlink_name = NULL; - lli->lli_maxbytes = PAGE_CACHE_MAXBYTES; cfs_init_rwsem(&lli->lli_trunc_sem); cfs_mutex_init(&lli->lli_write_mutex); lli->lli_async_rc = 0; @@ -1337,9 +1324,18 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETATTR, 1); if (ia_valid & ATTR_SIZE) { + /* Check new size against VFS/VM file size limit and rlimit */ + rc = inode_newsize_ok(inode, attr->ia_size); + if (rc) + RETURN(rc); + + /* The maximum Lustre file size is variable, based on the + * OST maximum object size and number of stripes. This + * needs another check in addition to the VFS check above. */ if (attr->ia_size > ll_file_maxbytes(inode)) { - CDEBUG(D_INODE, "file too large %llu > "LPU64"\n", - attr->ia_size, ll_file_maxbytes(inode)); + CDEBUG(D_INODE,"file "DFID" too large %llu > "LPU64"\n", + PFID(&lli->lli_fid), attr->ia_size, + ll_file_maxbytes(inode)); RETURN(-EFBIG); } @@ -1416,12 +1412,12 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) if (ia_valid & (ATTR_SIZE | ATTR_ATIME | ATTR_ATIME_SET | ATTR_MTIME | ATTR_MTIME_SET)) - /* on truncate and utimes send attributes to osts, setting - * mtime/atime to past will be performed under PW 0:EOF extent - * lock (new_size:EOF for truncate) - * it may seem excessive to send mtime/atime updates to osts - * when not setting times to past, but it is necessary due to - * possible time de-synchronization */ + /* For truncate and utimes sending attributes to OSTs, setting + * mtime/atime to the past will be performed under PW [0:EOF] + * extent lock (new_size:EOF for truncate). It may seem + * excessive to send mtime/atime updates to OSTs when not + * setting times to past, but it is necessary due to possible + * time de-synchronization between MDT inode and OST objects */ rc = ll_setattr_ost(inode, attr); EXIT; out: @@ -1622,8 +1618,8 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) cfs_spin_unlock(&lli->lli_lock); cfs_mutex_unlock(&lli->lli_och_mutex); lli->lli_maxbytes = lsm->lsm_maxbytes; - if (lli->lli_maxbytes > PAGE_CACHE_MAXBYTES) - lli->lli_maxbytes = PAGE_CACHE_MAXBYTES; + if (lli->lli_maxbytes > MAX_LFS_FILESIZE) + lli->lli_maxbytes = MAX_LFS_FILESIZE; } else { cfs_mutex_unlock(&lli->lli_och_mutex); LASSERT(lli->lli_smd->lsm_magic == lsm->lsm_magic && diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index 47efa64..fe9de98 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -1739,7 +1739,7 @@ static int server_fill_super_common(struct super_block *sb) sb->s_blocksize = 4096; sb->s_blocksize_bits = log2(sb->s_blocksize); sb->s_magic = LUSTRE_SUPER_MAGIC; - sb->s_maxbytes = 0; //PAGE_CACHE_MAXBYTES; + sb->s_maxbytes = 0; /* we don't allow file IO on server mountpoints */ sb->s_flags |= MS_RDONLY; sb->s_op = &server_ops;