diff --git a/fs/hmdfs/file_cloud.c b/fs/hmdfs/file_cloud.c index b7386be449d4b85f43f280a3bd95b65982970327..b633433e4ed6d2051c538fab2c74a02791a3490a 100644 --- a/fs/hmdfs/file_cloud.c +++ b/fs/hmdfs/file_cloud.c @@ -35,29 +35,11 @@ struct cloud_readpages_work { struct file *filp; loff_t pos; int cnt; + struct cred *cred; struct work_struct work; struct page *pages[0]; }; -static ssize_t hmdfs_file_read_iter_cloud(struct kiocb *iocb, - struct iov_iter *iter) -{ - ssize_t ret = -ENOENT; - struct file *filp = iocb->ki_filp; - struct hmdfs_file_info *gfi = filp->private_data; - struct file *lower_file = NULL; - - if (gfi) - lower_file = gfi->lower_file; - - if (lower_file) { - kiocb_clone(iocb, iocb, lower_file); - ret = vfs_iter_read(lower_file, iter, &iocb->ki_pos, 0); - } - - return ret; -} - int hmdfs_file_open_cloud(struct inode *inode, struct file *file) { const char *dir_path; @@ -91,7 +73,7 @@ int hmdfs_file_open_cloud(struct inode *inode, struct file *file) } lower_file = file_open_root(&root_path, dir_path, - file->f_flags, file->f_mode); + file->f_flags | O_DIRECT, file->f_mode); path_put(&root_path); if (IS_ERR(lower_file)) { hmdfs_info("file_open_root failed: %ld", PTR_ERR(lower_file)); @@ -163,16 +145,20 @@ static void cloud_readpages_work_func(struct work_struct *work) void *pages_buf; int idx, ret; ssize_t read_len; + const struct cred *old_cred; struct cloud_readpages_work *cr_work; cr_work = container_of(work, struct cloud_readpages_work, work); read_len = cr_work->cnt * HMDFS_PAGE_SIZE; + old_cred = override_creds(cr_work->cred); pages_buf = vmap(cr_work->pages, cr_work->cnt, VM_MAP, PAGE_KERNEL); if (!pages_buf) goto out; + trace_hmdfs_readpages_cloud_work_begin(cr_work->cnt, cr_work->pos); ret = kernel_read(cr_work->filp, pages_buf, read_len, &cr_work->pos); + trace_hmdfs_readpages_cloud_work_end(cr_work->cnt, cr_work->pos); if (ret < 0) goto out_vunmap; @@ -186,6 +172,8 @@ static void cloud_readpages_work_func(struct work_struct *work) SetPageUptodate(cr_work->pages[idx]); unlock_page(cr_work->pages[idx]); } + revert_creds(old_cred); + put_cred(cr_work->cred); kfree(cr_work); } @@ -194,19 +182,26 @@ static int prepare_cloud_readpage_work(struct file *filp, int cnt, { struct cloud_readpages_work *cr_work; struct hmdfs_file_info *gfi = filp->private_data; + struct cred *cred = NULL; + int idx = 0; cr_work = kzalloc(sizeof(*cr_work) + sizeof(cr_work->pages[0]) * cnt, GFP_KERNEL); if (!cr_work) { hmdfs_warning("cannot alloc work"); - return -ENOMEM; + goto unlock; } if (gfi) cr_work->filp = gfi->lower_file; else - cr_work->filp = filp; + goto out; + + cred = prepare_creds(); + if (!cred) + goto out; + cr_work->cred = cred; cr_work->pos = (loff_t)(vec[0]->index) << HMDFS_PAGE_OFFSET; cr_work->cnt = cnt; memcpy(cr_work->pages, vec, cnt * sizeof(*vec)); @@ -214,6 +209,12 @@ static int prepare_cloud_readpage_work(struct file *filp, int cnt, INIT_WORK(&cr_work->work, cloud_readpages_work_func); schedule_work(&cr_work->work); return 0; +out: + kfree(cr_work); +unlock: + for (idx = 0; idx < cnt; ++idx) + unlock_page(vec[idx]); + return -ENOMEM; } static int hmdfs_readpages_cloud(struct file *filp, @@ -266,7 +267,7 @@ static int hmdfs_readpages_cloud(struct file *filp, const struct file_operations hmdfs_dev_file_fops_cloud = { .owner = THIS_MODULE, .llseek = generic_file_llseek, - .read_iter = hmdfs_file_read_iter_cloud, + .read_iter = generic_file_read_iter, .write_iter = NULL, .mmap = hmdfs_file_mmap_cloud, .open = hmdfs_file_open_cloud, diff --git a/fs/hmdfs/file_local.c b/fs/hmdfs/file_local.c index c9aaaaa9ebc9d06916015750e577a8fceab5513b..c563ea44ade1a60713d312b434f39c8c98e3ec59 100644 --- a/fs/hmdfs/file_local.c +++ b/fs/hmdfs/file_local.c @@ -36,7 +36,12 @@ int hmdfs_file_open_local(struct inode *inode, struct file *file) } hmdfs_get_lower_path(file->f_path.dentry, &lower_path); - lower_file = dentry_open(&lower_path, file->f_flags, cred); + if (inode->i_mapping != NULL && + inode->i_mapping->a_ops == &hmdfs_aops_cloud) + lower_file = dentry_open(&lower_path, file->f_flags | O_DIRECT, + cred); + else + lower_file = dentry_open(&lower_path, file->f_flags, cred); hmdfs_put_lower_path(&lower_path); if (IS_ERR(lower_file)) { err = PTR_ERR(lower_file); @@ -86,11 +91,13 @@ ssize_t hmdfs_do_read_iter(struct file *file, struct iov_iter *iter, if (!iov_iter_count(iter)) return 0; - if (file->f_inode->i_mapping->a_ops == &hmdfs_aops_cloud) { + if (file->f_inode->i_mapping != NULL && + file->f_inode->i_mapping->a_ops == &hmdfs_aops_cloud) { iocb = container_of(ppos, struct kiocb, ki_pos); ret = generic_file_read_iter(iocb, iter); - } else + } else { ret = vfs_iter_read(lower_file, iter, ppos, 0); + } hmdfs_file_accessed(file); return ret; diff --git a/fs/hmdfs/hmdfs_trace.h b/fs/hmdfs/hmdfs_trace.h index 15bedbaa5cfaf938a31d4bd2d00f85f37d694d5b..6b26662ccd2ef8b6892ba28b0b670a2cc577e62d 100644 --- a/fs/hmdfs/hmdfs_trace.h +++ b/fs/hmdfs/hmdfs_trace.h @@ -546,6 +546,46 @@ TRACE_EVENT(hmdfs_readpages_cloud, __entry->nr_pages, __entry->err) ); +TRACE_EVENT(hmdfs_readpages_cloud_work_begin, + + TP_PROTO(int cnt, loff_t pos), + + TP_ARGS(cnt, pos), + + TP_STRUCT__entry( + __field(int, cnt) + __field(loff_t, pos) + ), + + TP_fast_assign( + __entry->cnt = cnt; + __entry->pos = pos; + ), + + TP_printk("cnt:%d, pos:%llx", + __entry->cnt, __entry->pos) +); + +TRACE_EVENT(hmdfs_readpages_cloud_work_end, + + TP_PROTO(int cnt, loff_t pos), + + TP_ARGS(cnt, pos), + + TP_STRUCT__entry( + __field(int, cnt) + __field(loff_t, pos) + ), + + TP_fast_assign( + __entry->cnt = cnt; + __entry->pos = pos; + ), + + TP_printk("cnt:%d, pos:%llx", + __entry->cnt, __entry->pos) +); + TRACE_EVENT(hmdfs_client_recv_readpage, TP_PROTO(struct hmdfs_peer *con, unsigned long long remote_ino,