summaryrefslogtreecommitdiffstats
path: root/fs/ceph/file.c
diff options
context:
space:
mode:
authorChengguang Xu <cgxu519@gmx.com>2018-07-19 10:15:26 -0400
committerIlya Dryomov <idryomov@gmail.com>2018-08-02 15:33:28 -0400
commit8687a3e2c7a026c173ac2e0d65d869c98c154a3a (patch)
tree22a099b8e861972165e9e736c335c2ed42bfb817 /fs/ceph/file.c
parent0671e9968dfb3f99a366df816c361b8e871dba1b (diff)
ceph: add additional offset check in ceph_write_iter()
If the offset is larger or equal to both real file size and max file size, then return -EFBIG. Signed-off-by: Chengguang Xu <cgxu519@gmx.com> Reviewed-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r--fs/ceph/file.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 2c54d2674db6..b9cd9d271dcb 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1384,12 +1384,12 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
1384 struct ceph_file_info *fi = file->private_data; 1384 struct ceph_file_info *fi = file->private_data;
1385 struct inode *inode = file_inode(file); 1385 struct inode *inode = file_inode(file);
1386 struct ceph_inode_info *ci = ceph_inode(inode); 1386 struct ceph_inode_info *ci = ceph_inode(inode);
1387 struct ceph_osd_client *osdc = 1387 struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
1388 &ceph_sb_to_client(inode->i_sb)->client->osdc;
1389 struct ceph_cap_flush *prealloc_cf; 1388 struct ceph_cap_flush *prealloc_cf;
1390 ssize_t count, written = 0; 1389 ssize_t count, written = 0;
1391 int err, want, got; 1390 int err, want, got;
1392 loff_t pos; 1391 loff_t pos;
1392 loff_t limit = max(i_size_read(inode), fsc->max_file_size);
1393 1393
1394 if (ceph_snap(inode) != CEPH_NOSNAP) 1394 if (ceph_snap(inode) != CEPH_NOSNAP)
1395 return -EROFS; 1395 return -EROFS;
@@ -1415,6 +1415,13 @@ retry_snap:
1415 goto out; 1415 goto out;
1416 1416
1417 pos = iocb->ki_pos; 1417 pos = iocb->ki_pos;
1418 if (unlikely(pos >= limit)) {
1419 err = -EFBIG;
1420 goto out;
1421 } else {
1422 iov_iter_truncate(from, limit - pos);
1423 }
1424
1418 count = iov_iter_count(from); 1425 count = iov_iter_count(from);
1419 if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) { 1426 if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) {
1420 err = -EDQUOT; 1427 err = -EDQUOT;
@@ -1436,7 +1443,7 @@ retry_snap:
1436 } 1443 }
1437 1444
1438 /* FIXME: not complete since it doesn't account for being at quota */ 1445 /* FIXME: not complete since it doesn't account for being at quota */
1439 if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) { 1446 if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_FULL)) {
1440 err = -ENOSPC; 1447 err = -ENOSPC;
1441 goto out; 1448 goto out;
1442 } 1449 }
@@ -1526,7 +1533,7 @@ retry_snap:
1526 } 1533 }
1527 1534
1528 if (written >= 0) { 1535 if (written >= 0) {
1529 if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_NEARFULL)) 1536 if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_NEARFULL))
1530 iocb->ki_flags |= IOCB_DSYNC; 1537 iocb->ki_flags |= IOCB_DSYNC;
1531 written = generic_write_sync(iocb, written); 1538 written = generic_write_sync(iocb, written);
1532 } 1539 }