Whamcloud - gitweb
LU-808 llite: deny truncate beyond user rlimit
authorAndreas Dilger <adilger@whamcloud.com>
Mon, 31 Oct 2011 20:14:27 +0000 (14:14 -0600)
committerOleg Drokin <green@whamcloud.com>
Thu, 29 Mar 2012 04:05:56 +0000 (00:05 -0400)
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 <adilger@whamcloud.com>
Change-Id: I6b4f03820dd59d6b1c3429e9bbfea62c50206cc9
Reviewed-on: http://review.whamcloud.com/1635
Reviewed-by: Jinshan Xiong <jinshan.xiong@whamcloud.com>
Tested-by: Hudson
Reviewed-by: Bobi Jam <bobijam@whamcloud.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lustre_lite.h
lustre/liblustre/llite_lib.h
lustre/liblustre/super.c
lustre/llite/llite_lib.c
lustre/obdclass/obd_mount.c

index 4309c87..6b17d26 100644 (file)
 #include <lustre_mds.h>
 #include <lustre_ha.h>
 
-#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<<LL_MAX_BLKSIZE_BITS)
index 193239e..780a3c3 100644 (file)
@@ -67,7 +67,7 @@
 
 /* This should not be "optimized" use ~0ULL because page->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;
index 6b738f4..8d03a8e 100644 (file)
@@ -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",
index 48c5097..8a2d3fb 100644 (file)
@@ -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 &&
index 47efa64..fe9de98 100644 (file)
@@ -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;