Skip to content

Commit 8e4473b

Browse files
lxbszidryomov
authored andcommitted
ceph: do not execute direct write in parallel if O_APPEND is specified
In O_APPEND & O_DIRECT mode, the data from different writers will be possibly overlapping each other since they take the shared lock. For example, both Writer1 and Writer2 are in O_APPEND and O_DIRECT mode: Writer1 Writer2 shared_lock() shared_lock() getattr(CAP_SIZE) getattr(CAP_SIZE) iocb->ki_pos = EOF iocb->ki_pos = EOF write(data1) write(data2) shared_unlock() shared_unlock() The data2 will overlap the data1 from the same file offset, the old EOF. Switch to exclusive lock instead when O_APPEND is specified. Signed-off-by: Xiubo Li <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent bb6d3fb commit 8e4473b

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

fs/ceph/file.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
14181418
struct ceph_cap_flush *prealloc_cf;
14191419
ssize_t count, written = 0;
14201420
int err, want, got;
1421+
bool direct_lock = false;
14211422
loff_t pos;
14221423
loff_t limit = max(i_size_read(inode), fsc->max_file_size);
14231424

@@ -1428,8 +1429,11 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
14281429
if (!prealloc_cf)
14291430
return -ENOMEM;
14301431

1432+
if ((iocb->ki_flags & (IOCB_DIRECT | IOCB_APPEND)) == IOCB_DIRECT)
1433+
direct_lock = true;
1434+
14311435
retry_snap:
1432-
if (iocb->ki_flags & IOCB_DIRECT)
1436+
if (direct_lock)
14331437
ceph_start_io_direct(inode);
14341438
else
14351439
ceph_start_io_write(inode);
@@ -1519,14 +1523,15 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
15191523

15201524
/* we might need to revert back to that point */
15211525
data = *from;
1522-
if (iocb->ki_flags & IOCB_DIRECT) {
1526+
if (iocb->ki_flags & IOCB_DIRECT)
15231527
written = ceph_direct_read_write(iocb, &data, snapc,
15241528
&prealloc_cf);
1525-
ceph_end_io_direct(inode);
1526-
} else {
1529+
else
15271530
written = ceph_sync_write(iocb, &data, pos, snapc);
1531+
if (direct_lock)
1532+
ceph_end_io_direct(inode);
1533+
else
15281534
ceph_end_io_write(inode);
1529-
}
15301535
if (written > 0)
15311536
iov_iter_advance(from, written);
15321537
ceph_put_snap_context(snapc);
@@ -1577,7 +1582,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
15771582

15781583
goto out_unlocked;
15791584
out:
1580-
if (iocb->ki_flags & IOCB_DIRECT)
1585+
if (direct_lock)
15811586
ceph_end_io_direct(inode);
15821587
else
15831588
ceph_end_io_write(inode);

0 commit comments

Comments
 (0)