162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/hmdfs/file_cloud.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2023-2023 Huawei Device Co., Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/backing-dev.h> 962306a36Sopenharmony_ci#include <linux/file.h> 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/namei.h> 1262306a36Sopenharmony_ci#include <linux/page-flags.h> 1362306a36Sopenharmony_ci#include <linux/pagemap.h> 1462306a36Sopenharmony_ci#include <linux/pagevec.h> 1562306a36Sopenharmony_ci#include <linux/sched/signal.h> 1662306a36Sopenharmony_ci#include <linux/slab.h> 1762306a36Sopenharmony_ci#include <linux/wait.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "file_remote.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "comm/socket_adapter.h" 2262306a36Sopenharmony_ci#include "hmdfs.h" 2362306a36Sopenharmony_ci#include "hmdfs_client.h" 2462306a36Sopenharmony_ci#include "hmdfs_dentryfile.h" 2562306a36Sopenharmony_ci#include "hmdfs_dentryfile_cloud.h" 2662306a36Sopenharmony_ci#include "hmdfs_trace.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic const struct vm_operations_struct hmdfs_cloud_vm_ops = { 2962306a36Sopenharmony_ci .fault = filemap_fault, 3062306a36Sopenharmony_ci .map_pages = filemap_map_pages, 3162306a36Sopenharmony_ci .page_mkwrite = NULL, 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciint hmdfs_file_open_cloud(struct inode *inode, struct file *file) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci const char *dir_path; 3762306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = inode->i_sb->s_fs_info; 3862306a36Sopenharmony_ci struct path root_path; 3962306a36Sopenharmony_ci struct file *lower_file; 4062306a36Sopenharmony_ci int err = 0; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci struct hmdfs_file_info *gfi = kzalloc(sizeof(*gfi), GFP_KERNEL); 4362306a36Sopenharmony_ci if (!gfi) 4462306a36Sopenharmony_ci return -ENOMEM; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci if (!sbi->cloud_dir) { 4762306a36Sopenharmony_ci hmdfs_info("no cloud_dir"); 4862306a36Sopenharmony_ci kfree(gfi); 4962306a36Sopenharmony_ci return -EPERM; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci err = kern_path(sbi->cloud_dir, 0, &root_path); 5362306a36Sopenharmony_ci if (err) { 5462306a36Sopenharmony_ci hmdfs_info("kern_path failed: %d", err); 5562306a36Sopenharmony_ci kfree(gfi); 5662306a36Sopenharmony_ci return err; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci dir_path = hmdfs_get_dentry_relative_path(file->f_path.dentry); 6062306a36Sopenharmony_ci if(!dir_path) { 6162306a36Sopenharmony_ci hmdfs_err("get cloud path failed"); 6262306a36Sopenharmony_ci kfree(gfi); 6362306a36Sopenharmony_ci return -ENOENT; 6462306a36Sopenharmony_ci } 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci lower_file = file_open_root(&root_path, dir_path, 6762306a36Sopenharmony_ci file->f_flags | O_DIRECT, file->f_mode); 6862306a36Sopenharmony_ci path_put(&root_path); 6962306a36Sopenharmony_ci if (IS_ERR(lower_file)) { 7062306a36Sopenharmony_ci hmdfs_info("file_open_root failed: %ld", PTR_ERR(lower_file)); 7162306a36Sopenharmony_ci err = PTR_ERR(lower_file); 7262306a36Sopenharmony_ci kfree(gfi); 7362306a36Sopenharmony_ci } else { 7462306a36Sopenharmony_ci gfi->lower_file = lower_file; 7562306a36Sopenharmony_ci file->private_data = gfi; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci kfree(dir_path); 7862306a36Sopenharmony_ci return err; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciint hmdfs_file_release_cloud(struct inode *inode, struct file *file) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci struct hmdfs_file_info *gfi = hmdfs_f(file); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci file->private_data = NULL; 8662306a36Sopenharmony_ci fput(gfi->lower_file); 8762306a36Sopenharmony_ci kfree(gfi); 8862306a36Sopenharmony_ci return 0; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int hmdfs_file_flush_cloud(struct file *file, fl_owner_t id) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci struct hmdfs_file_info *gfi = hmdfs_f(file); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if(!gfi || !gfi->lower_file) 9662306a36Sopenharmony_ci return 0; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (gfi->lower_file->f_op->flush) 9962306a36Sopenharmony_ci return gfi->lower_file->f_op->flush(gfi->lower_file, id); 10062306a36Sopenharmony_ci return 0; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciint hmdfs_file_mmap_cloud(struct file *file, struct vm_area_struct *vma) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci struct hmdfs_file_info *private_data = file->private_data; 10662306a36Sopenharmony_ci struct file *realfile = NULL; 10762306a36Sopenharmony_ci int ret; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (!private_data) 11062306a36Sopenharmony_ci return -EINVAL; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci realfile = private_data->lower_file; 11362306a36Sopenharmony_ci if (!realfile) 11462306a36Sopenharmony_ci return -EINVAL; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (!realfile->f_op->mmap) 11762306a36Sopenharmony_ci return -ENODEV; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (WARN_ON(file != vma->vm_file)) 12062306a36Sopenharmony_ci return -EIO; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci vma->vm_file = get_file(realfile); 12362306a36Sopenharmony_ci ret = call_mmap(vma->vm_file, vma); 12462306a36Sopenharmony_ci if (ret) 12562306a36Sopenharmony_ci fput(realfile); 12662306a36Sopenharmony_ci else 12762306a36Sopenharmony_ci fput(file); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci file_accessed(file); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci return ret; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic int hmdfs_do_readpages_cloud(struct file *filp, int cnt, 13562306a36Sopenharmony_ci struct page **vec) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci struct hmdfs_file_info *gfi = filp->private_data; 13862306a36Sopenharmony_ci struct file *lower_filp; 13962306a36Sopenharmony_ci loff_t pos = (loff_t)(vec[0]->index) << HMDFS_PAGE_OFFSET; 14062306a36Sopenharmony_ci void *pages_buf = NULL; 14162306a36Sopenharmony_ci int idx, ret; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (gfi) { 14462306a36Sopenharmony_ci lower_filp = gfi->lower_file; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci else { 14762306a36Sopenharmony_ci ret = -EINVAL; 14862306a36Sopenharmony_ci goto out_err; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci pages_buf = vmap(vec, cnt, VM_MAP, PAGE_KERNEL); 15262306a36Sopenharmony_ci if (!pages_buf) { 15362306a36Sopenharmony_ci ret = -ENOMEM; 15462306a36Sopenharmony_ci goto out_err; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci trace_hmdfs_do_readpages_cloud_begin(cnt, pos); 15862306a36Sopenharmony_ci ret = kernel_read(lower_filp, pages_buf, cnt * HMDFS_PAGE_SIZE, &pos); 15962306a36Sopenharmony_ci trace_hmdfs_do_readpages_cloud_end(cnt, pos, ret); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (ret >= 0) 16262306a36Sopenharmony_ci memset(pages_buf + ret, 0, cnt * HMDFS_PAGE_SIZE - ret); 16362306a36Sopenharmony_ci else 16462306a36Sopenharmony_ci goto out_err; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci vunmap(pages_buf); 16762306a36Sopenharmony_ci for (idx = 0; idx < cnt; ++idx) { 16862306a36Sopenharmony_ci SetPageUptodate(vec[idx]); 16962306a36Sopenharmony_ci unlock_page(vec[idx]); 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci goto out; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciout_err: 17462306a36Sopenharmony_ci if (pages_buf) 17562306a36Sopenharmony_ci vunmap(pages_buf); 17662306a36Sopenharmony_ci for (idx = 0; idx < cnt; ++idx) { 17762306a36Sopenharmony_ci folio_clear_uptodate((struct folio *)vec[idx]); 17862306a36Sopenharmony_ci filemap_remove_folio((struct folio *)vec[idx]); 17962306a36Sopenharmony_ci unlock_page(vec[idx]); 18062306a36Sopenharmony_ci put_page(vec[idx]); 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ciout: 18362306a36Sopenharmony_ci return ret; 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic void hmdfs_readahead(struct readahead_control *ractl) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci struct file *filp = ractl->file; 18962306a36Sopenharmony_ci struct address_space *mapping = ractl->mapping; 19062306a36Sopenharmony_ci unsigned int nr_pages = readahead_count(ractl); 19162306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(file_inode(filp)->i_sb); 19262306a36Sopenharmony_ci unsigned int ret = 0, idx, cnt, limit; 19362306a36Sopenharmony_ci unsigned long next_index; 19462306a36Sopenharmony_ci gfp_t gfp = readahead_gfp_mask(mapping); 19562306a36Sopenharmony_ci struct page **vec = NULL; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci limit = sbi->s_readpages_nr; 19862306a36Sopenharmony_ci vec = kmalloc(limit * sizeof(*vec), GFP_KERNEL); 19962306a36Sopenharmony_ci if (!vec) { 20062306a36Sopenharmony_ci hmdfs_warning("cannot alloc vec (%u pages)", limit); 20162306a36Sopenharmony_ci return; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci cnt = 0; 20562306a36Sopenharmony_ci next_index = 0; 20662306a36Sopenharmony_ci for (idx = 0; idx < nr_pages; ++idx) { 20762306a36Sopenharmony_ci struct page *page = readahead_page(ractl); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci if (add_to_page_cache_lru(page, mapping, page->index, gfp)) { 21062306a36Sopenharmony_ci unlock_page(page); 21162306a36Sopenharmony_ci put_page(page); 21262306a36Sopenharmony_ci continue; 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci if (cnt && (cnt >= limit || page->index != next_index)) { 21662306a36Sopenharmony_ci ret = hmdfs_do_readpages_cloud(filp, cnt, vec); 21762306a36Sopenharmony_ci cnt = 0; 21862306a36Sopenharmony_ci if (ret) 21962306a36Sopenharmony_ci break; 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci next_index = page->index + 1; 22262306a36Sopenharmony_ci vec[cnt++] = page; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci if (cnt) 22662306a36Sopenharmony_ci ret = hmdfs_do_readpages_cloud(filp, cnt, vec); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci kfree(vec); 22962306a36Sopenharmony_ci trace_hmdfs_readpages_cloud(nr_pages, ret); 23062306a36Sopenharmony_ci return; 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic int hmdfs_readpage(struct file *file, struct page *page) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci loff_t offset = page_file_offset(page); 23662306a36Sopenharmony_ci int ret = -EACCES; 23762306a36Sopenharmony_ci char *page_buf; 23862306a36Sopenharmony_ci struct hmdfs_file_info *gfi = file->private_data; 23962306a36Sopenharmony_ci struct file *lower_file; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (gfi) 24262306a36Sopenharmony_ci lower_file = gfi->lower_file; 24362306a36Sopenharmony_ci else 24462306a36Sopenharmony_ci goto out; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci page_buf = kmap(page); 24762306a36Sopenharmony_ci if (!page_buf) 24862306a36Sopenharmony_ci goto out; 24962306a36Sopenharmony_ci ret = kernel_read(lower_file, page_buf, PAGE_SIZE, &offset); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci if (ret >= 0 && ret <= PAGE_SIZE) { 25262306a36Sopenharmony_ci ret = 0; 25362306a36Sopenharmony_ci memset(page_buf + ret, 0, PAGE_SIZE - ret); 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci kunmap(page); 25762306a36Sopenharmony_ci if (ret == 0) 25862306a36Sopenharmony_ci SetPageUptodate(page); 25962306a36Sopenharmony_ciout: 26062306a36Sopenharmony_ci unlock_page(page); 26162306a36Sopenharmony_ci return ret; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic int hmdfs_read_folio(struct file *file, struct folio *folio) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci struct page *page = &folio->page; 26762306a36Sopenharmony_ci return hmdfs_readpage(file, page); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ciconst struct file_operations hmdfs_dev_file_fops_cloud = { 27162306a36Sopenharmony_ci .owner = THIS_MODULE, 27262306a36Sopenharmony_ci .llseek = generic_file_llseek, 27362306a36Sopenharmony_ci .read_iter = generic_file_read_iter, 27462306a36Sopenharmony_ci .write_iter = NULL, 27562306a36Sopenharmony_ci .mmap = hmdfs_file_mmap_cloud, 27662306a36Sopenharmony_ci .open = hmdfs_file_open_cloud, 27762306a36Sopenharmony_ci .release = hmdfs_file_release_cloud, 27862306a36Sopenharmony_ci .flush = hmdfs_file_flush_cloud, 27962306a36Sopenharmony_ci .fsync = NULL, 28062306a36Sopenharmony_ci .splice_read = NULL, 28162306a36Sopenharmony_ci .splice_write = NULL, 28262306a36Sopenharmony_ci}; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ciconst struct address_space_operations hmdfs_dev_file_aops_cloud = { 28662306a36Sopenharmony_ci .read_folio = hmdfs_read_folio, 28762306a36Sopenharmony_ci .readahead = hmdfs_readahead, 28862306a36Sopenharmony_ci .write_begin = NULL, 28962306a36Sopenharmony_ci .write_end = NULL, 29062306a36Sopenharmony_ci .writepage = NULL, 29162306a36Sopenharmony_ci .dirty_folio = NULL, 29262306a36Sopenharmony_ci}; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ciconst struct address_space_operations hmdfs_aops_cloud = { 29562306a36Sopenharmony_ci .read_folio = hmdfs_read_folio, 29662306a36Sopenharmony_ci .readahead = hmdfs_readahead, 29762306a36Sopenharmony_ci}; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ciint analysis_dentry_file_from_cloud(struct hmdfs_sb_info *sbi, 30062306a36Sopenharmony_ci struct file *file, struct file *handler, 30162306a36Sopenharmony_ci struct dir_context *ctx) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci struct hmdfs_dentry_group_cloud *dentry_group = NULL; 30462306a36Sopenharmony_ci loff_t pos = ctx->pos; 30562306a36Sopenharmony_ci unsigned long dev_id = (unsigned long)((pos << 1) >> (POS_BIT_NUM - DEV_ID_BIT_NUM)); 30662306a36Sopenharmony_ci unsigned long group_id = (unsigned long)((pos << (1 + DEV_ID_BIT_NUM)) >> 30762306a36Sopenharmony_ci (POS_BIT_NUM - GROUP_ID_BIT_NUM)); 30862306a36Sopenharmony_ci loff_t offset = pos & OFFSET_BIT_MASK; 30962306a36Sopenharmony_ci int group_num = 0; 31062306a36Sopenharmony_ci char *dentry_name = NULL; 31162306a36Sopenharmony_ci int iterate_result = 0; 31262306a36Sopenharmony_ci int i, j; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci dentry_group = kzalloc(sizeof(*dentry_group), GFP_KERNEL); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (!dentry_group) 31762306a36Sopenharmony_ci return -ENOMEM; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (IS_ERR_OR_NULL(handler)) { 32062306a36Sopenharmony_ci kfree(dentry_group); 32162306a36Sopenharmony_ci return -ENOENT; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci group_num = get_dentry_group_cnt(file_inode(handler)); 32562306a36Sopenharmony_ci dentry_name = kzalloc(DENTRY_NAME_MAX_LEN, GFP_KERNEL); 32662306a36Sopenharmony_ci if (!dentry_name) { 32762306a36Sopenharmony_ci kfree(dentry_group); 32862306a36Sopenharmony_ci return -ENOMEM; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci for (i = group_id; i < group_num; i++) { 33262306a36Sopenharmony_ci int ret = hmdfs_metainfo_read_nocred(handler, dentry_group, 33362306a36Sopenharmony_ci sizeof(struct hmdfs_dentry_group_cloud), 33462306a36Sopenharmony_ci i); 33562306a36Sopenharmony_ci if (ret != sizeof(struct hmdfs_dentry_group_cloud)) { 33662306a36Sopenharmony_ci hmdfs_err("read dentry group failed ret:%d", ret); 33762306a36Sopenharmony_ci goto done; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci for (j = offset; j < DENTRY_PER_GROUP_CLOUD; j++) { 34162306a36Sopenharmony_ci int len; 34262306a36Sopenharmony_ci int file_type = DT_UNKNOWN; 34362306a36Sopenharmony_ci bool is_continue; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci len = le16_to_cpu(dentry_group->nsl[j].namelen); 34662306a36Sopenharmony_ci if (!test_bit_le(j, dentry_group->bitmap) || len == 0) 34762306a36Sopenharmony_ci continue; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci memset(dentry_name, 0, DENTRY_NAME_MAX_LEN); 35062306a36Sopenharmony_ci if (S_ISDIR(le16_to_cpu(dentry_group->nsl[j].i_mode))) 35162306a36Sopenharmony_ci file_type = DT_DIR; 35262306a36Sopenharmony_ci else if (S_ISREG(le16_to_cpu( 35362306a36Sopenharmony_ci dentry_group->nsl[j].i_mode))) 35462306a36Sopenharmony_ci file_type = DT_REG; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci strncat(dentry_name, dentry_group->filename[j], len); 35762306a36Sopenharmony_ci pos = hmdfs_set_pos(dev_id, i, j); 35862306a36Sopenharmony_ci is_continue = 35962306a36Sopenharmony_ci dir_emit(ctx, dentry_name, len, 36062306a36Sopenharmony_ci pos + INUNUMBER_START, file_type); 36162306a36Sopenharmony_ci if (!is_continue) { 36262306a36Sopenharmony_ci ctx->pos = pos; 36362306a36Sopenharmony_ci iterate_result = 1; 36462306a36Sopenharmony_ci goto done; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci offset = 0; 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cidone: 37162306a36Sopenharmony_ci kfree(dentry_name); 37262306a36Sopenharmony_ci kfree(dentry_group); 37362306a36Sopenharmony_ci return iterate_result; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic int hmdfs_iterate_cloud(struct file *file, struct dir_context *ctx) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci int err = 0; 37962306a36Sopenharmony_ci loff_t start_pos = ctx->pos; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci if (ctx->pos == -1) 38262306a36Sopenharmony_ci return 0; 38362306a36Sopenharmony_ci err = analysis_dentry_file_from_cloud( 38462306a36Sopenharmony_ci file->f_inode->i_sb->s_fs_info, file, file->private_data, ctx); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (err <= 0) 38762306a36Sopenharmony_ci ctx->pos = -1; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci trace_hmdfs_iterate_remote(file->f_path.dentry, start_pos, ctx->pos, 39062306a36Sopenharmony_ci err); 39162306a36Sopenharmony_ci return err; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ciint hmdfs_dir_open_cloud(struct inode *inode, struct file *file) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci struct clearcache_item *cache_item = NULL; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci get_cloud_cache_file(file->f_path.dentry, file->f_inode->i_sb->s_fs_info); 39962306a36Sopenharmony_ci cache_item = hmdfs_find_cache_item(CLOUD_DEVICE, 40062306a36Sopenharmony_ci file->f_path.dentry); 40162306a36Sopenharmony_ci if (cache_item) { 40262306a36Sopenharmony_ci file->private_data = cache_item->filp; 40362306a36Sopenharmony_ci get_file(file->private_data); 40462306a36Sopenharmony_ci kref_put(&cache_item->ref, release_cache_item); 40562306a36Sopenharmony_ci return 0; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci return -ENOENT; 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic int hmdfs_dir_release_cloud(struct inode *inode, struct file *file) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci if (file->private_data) 41462306a36Sopenharmony_ci fput(file->private_data); 41562306a36Sopenharmony_ci file->private_data = NULL; 41662306a36Sopenharmony_ci return 0; 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ciconst struct file_operations hmdfs_dev_dir_ops_cloud = { 42062306a36Sopenharmony_ci .owner = THIS_MODULE, 42162306a36Sopenharmony_ci .iterate_shared = hmdfs_iterate_cloud, 42262306a36Sopenharmony_ci .open = hmdfs_dir_open_cloud, 42362306a36Sopenharmony_ci .release = hmdfs_dir_release_cloud, 42462306a36Sopenharmony_ci .fsync = __generic_file_fsync, 42562306a36Sopenharmony_ci}; 426