kernel ceph fs/ceph , ceph 。
fs/ceph/file.c ceph_file_fops ceph_write_iter
const struct file_operations ceph_file_fops = {
.open = ceph_open,
.release = ceph_release,
.llseek = ceph_llseek,
.read_iter = ceph_read_iter,
.write_iter = ceph_write_iter,
}
static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
(iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC) ||
(ci->i_ceph_flags & CEPH_I_ERROR_WRITE)) {
struct ceph_snap_context *snapc;
struct iov_iter data;
inode_unlock(inode);
# client direct io bufffer io
/* we might need to revert back to that point */
data = *from;
if (iocb->ki_flags & IOCB_DIRECT)
written = ceph_direct_read_write(iocb, &data, snapc,
&prealloc_cf);
else
written = ceph_sync_write(iocb, &data, pos, snapc);
if (written > 0)
iov_iter_advance(from, written);
ceph_put_snap_context(snapc);
}
}
direct io
request , ceph_osdc_new_request->ceph_osdc_start_request->ceph_osdc_wait_request
static ssize_t
ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
struct ceph_snap_context *snapc,
struct ceph_cap_flush **pcf)
{
while (iov_iter_count(iter) > 0) {
u64 size = dio_get_pagev_size(iter);
size_t start = 0;
ssize_t len;
vino = ceph_vino(inode);
#new request req, , req
req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
vino, pos, &size, 0,
1,
write ? CEPH_OSD_OP_WRITE :
CEPH_OSD_OP_READ,
flags, snapc,
ci->i_truncate_seq,
ci->i_truncate_size,
false);
#start request submiet_quest
ret = ceph_osdc_start_request(req->r_osdc, req, false);
if (!ret)
# req
ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
}
:
int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
struct ceph_osd_request *req)
{
return wait_request_timeout(req, 0);
}
wait_for_completion_killable_timeout , wait_for_completion_killable_timeout
cpu。
static int wait_request_timeout(struct ceph_osd_request *req,
unsigned long timeout)
{
long left;
dout("%s req %p tid %llu
", __func__, req, req->r_tid);
left = wait_for_completion_killable_timeout(&req->r_completion,
ceph_timeout_jiffies(timeout));
if (left <= 0) {
left = left ?: -ETIMEDOUT;
ceph_osdc_cancel_request(req);
} else {
left = req->r_result; /* completed */
}
return left;
}
client ,direct io , kernel cache ,
, 。 client , client