162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/hmdfs/file_local.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/file.h> 962306a36Sopenharmony_ci#include <linux/fs.h> 1062306a36Sopenharmony_ci#include <linux/namei.h> 1162306a36Sopenharmony_ci#include <linux/page-flags.h> 1262306a36Sopenharmony_ci#include <linux/pagemap.h> 1362306a36Sopenharmony_ci#include <linux/sched/signal.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "hmdfs_client.h" 1762306a36Sopenharmony_ci#include "hmdfs_dentryfile.h" 1862306a36Sopenharmony_ci#include "hmdfs_device_view.h" 1962306a36Sopenharmony_ci#include "hmdfs_merge_view.h" 2062306a36Sopenharmony_ci#include "hmdfs_share.h" 2162306a36Sopenharmony_ci#include "hmdfs_trace.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ciint hmdfs_file_open_local(struct inode *inode, struct file *file) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci int err = 0; 2662306a36Sopenharmony_ci struct file *lower_file = NULL; 2762306a36Sopenharmony_ci struct path lower_path; 2862306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 2962306a36Sopenharmony_ci const struct cred *cred = hmdfs_sb(sb)->cred; 3062306a36Sopenharmony_ci struct hmdfs_file_info *gfi = kzalloc(sizeof(*gfi), GFP_KERNEL); 3162306a36Sopenharmony_ci struct hmdfs_inode_info *info = hmdfs_i(inode); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci if (!gfi) { 3462306a36Sopenharmony_ci err = -ENOMEM; 3562306a36Sopenharmony_ci goto out_err; 3662306a36Sopenharmony_ci } 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci hmdfs_get_lower_path(file->f_path.dentry, &lower_path); 3962306a36Sopenharmony_ci if (inode->i_mapping != NULL && 4062306a36Sopenharmony_ci inode->i_mapping->a_ops == &hmdfs_aops_cloud) 4162306a36Sopenharmony_ci lower_file = dentry_open(&lower_path, file->f_flags | O_DIRECT, 4262306a36Sopenharmony_ci cred); 4362306a36Sopenharmony_ci else 4462306a36Sopenharmony_ci lower_file = dentry_open(&lower_path, file->f_flags, cred); 4562306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 4662306a36Sopenharmony_ci if (IS_ERR(lower_file)) { 4762306a36Sopenharmony_ci err = PTR_ERR(lower_file); 4862306a36Sopenharmony_ci kfree(gfi); 4962306a36Sopenharmony_ci } else { 5062306a36Sopenharmony_ci gfi->lower_file = lower_file; 5162306a36Sopenharmony_ci file->private_data = gfi; 5262306a36Sopenharmony_ci hmdfs_update_upper_file(file, lower_file); 5362306a36Sopenharmony_ci if (file->f_flags & (O_RDWR | O_WRONLY)) 5462306a36Sopenharmony_ci atomic_inc(&info->write_opened); 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ciout_err: 5762306a36Sopenharmony_ci return err; 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciint hmdfs_file_release_local(struct inode *inode, struct file *file) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct hmdfs_file_info *gfi = hmdfs_f(file); 6362306a36Sopenharmony_ci struct hmdfs_inode_info *info = hmdfs_i(inode); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (file->f_flags & (O_RDWR | O_WRONLY)) 6662306a36Sopenharmony_ci atomic_dec(&info->write_opened); 6762306a36Sopenharmony_ci file->private_data = NULL; 6862306a36Sopenharmony_ci fput(gfi->lower_file); 6962306a36Sopenharmony_ci kfree(gfi); 7062306a36Sopenharmony_ci return 0; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic void hmdfs_file_accessed(struct file *file) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci struct file *lower_file = hmdfs_f(file)->lower_file; 7662306a36Sopenharmony_ci struct inode *inode = file_inode(file); 7762306a36Sopenharmony_ci struct inode *lower_inode = file_inode(lower_file); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (file->f_flags & O_NOATIME) 8062306a36Sopenharmony_ci return; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci inode->i_atime = lower_inode->i_atime; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cissize_t hmdfs_do_read_iter(struct file *file, struct iov_iter *iter, 8662306a36Sopenharmony_ci loff_t *ppos) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci ssize_t ret; 8962306a36Sopenharmony_ci struct file *lower_file = hmdfs_f(file)->lower_file; 9062306a36Sopenharmony_ci struct kiocb *iocb; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (!iov_iter_count(iter)) 9362306a36Sopenharmony_ci return 0; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (file->f_inode->i_mapping != NULL && 9662306a36Sopenharmony_ci file->f_inode->i_mapping->a_ops == &hmdfs_aops_cloud) { 9762306a36Sopenharmony_ci iocb = container_of(ppos, struct kiocb, ki_pos); 9862306a36Sopenharmony_ci ret = generic_file_read_iter(iocb, iter); 9962306a36Sopenharmony_ci } else { 10062306a36Sopenharmony_ci ret = vfs_iter_read(lower_file, iter, ppos, 0); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci hmdfs_file_accessed(file); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return ret; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic ssize_t hmdfs_local_read_iter(struct kiocb *iocb, struct iov_iter *iter) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci return hmdfs_do_read_iter(iocb->ki_filp, iter, &iocb->ki_pos); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic void hmdfs_file_modified(struct file *file) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct inode *inode = file_inode(file); 11562306a36Sopenharmony_ci struct dentry *dentry = file_dentry(file); 11662306a36Sopenharmony_ci struct file *lower_file = hmdfs_f(file)->lower_file; 11762306a36Sopenharmony_ci struct inode *lower_inode = file_inode(lower_file); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci inode->i_atime = lower_inode->i_atime; 12062306a36Sopenharmony_ci inode->__i_ctime = lower_inode->__i_ctime; 12162306a36Sopenharmony_ci inode->i_mtime = lower_inode->i_mtime; 12262306a36Sopenharmony_ci i_size_write(inode, i_size_read(lower_inode)); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (!hmdfs_i_merge(hmdfs_i(inode))) 12562306a36Sopenharmony_ci update_inode_to_dentry(dentry, inode); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cissize_t hmdfs_do_write_iter(struct file *file, struct iov_iter *iter, 12962306a36Sopenharmony_ci loff_t *ppos) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci ssize_t ret; 13262306a36Sopenharmony_ci struct file *lower_file = hmdfs_f(file)->lower_file; 13362306a36Sopenharmony_ci struct inode *inode = file_inode(file); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (!iov_iter_count(iter)) 13662306a36Sopenharmony_ci return 0; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci inode_lock(inode); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci ret = file_remove_privs(file); 14162306a36Sopenharmony_ci if (ret) 14262306a36Sopenharmony_ci goto out_unlock; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci file_start_write(lower_file); 14562306a36Sopenharmony_ci ret = vfs_iter_write(lower_file, iter, ppos, 0); 14662306a36Sopenharmony_ci file_end_write(lower_file); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci hmdfs_file_modified(file); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ciout_unlock: 15162306a36Sopenharmony_ci inode_unlock(inode); 15262306a36Sopenharmony_ci return ret; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cissize_t hmdfs_local_write_iter(struct kiocb *iocb, struct iov_iter *iter) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci return hmdfs_do_write_iter(iocb->ki_filp, iter, &iocb->ki_pos); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ciint hmdfs_fsync_local(struct file *file, loff_t start, loff_t end, int datasync) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci int err; 16362306a36Sopenharmony_ci struct file *lower_file = hmdfs_f(file)->lower_file; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci err = __generic_file_fsync(file, start, end, datasync); 16662306a36Sopenharmony_ci if (err) 16762306a36Sopenharmony_ci goto out; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci err = vfs_fsync_range(lower_file, start, end, datasync); 17062306a36Sopenharmony_ciout: 17162306a36Sopenharmony_ci return err; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ciloff_t hmdfs_file_llseek_local(struct file *file, loff_t offset, int whence) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci loff_t ret; 17762306a36Sopenharmony_ci struct file *lower_file; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci lower_file = hmdfs_f(file)->lower_file; 18062306a36Sopenharmony_ci lower_file->f_pos = file->f_pos; 18162306a36Sopenharmony_ci ret = vfs_llseek(lower_file, offset, whence); 18262306a36Sopenharmony_ci file->f_pos = lower_file->f_pos; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci return ret; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ciint hmdfs_file_mmap_local(struct file *file, struct vm_area_struct *vma) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci struct hmdfs_file_info *private_data = file->private_data; 19062306a36Sopenharmony_ci struct file *realfile = NULL; 19162306a36Sopenharmony_ci int ret; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (!private_data) 19462306a36Sopenharmony_ci return -EINVAL; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci realfile = private_data->lower_file; 19762306a36Sopenharmony_ci if (!realfile) 19862306a36Sopenharmony_ci return -EINVAL; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci if (!realfile->f_op->mmap) 20162306a36Sopenharmony_ci return -ENODEV; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (WARN_ON(file != vma->vm_file)) 20462306a36Sopenharmony_ci return -EIO; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci vma->vm_file = get_file(realfile); 20762306a36Sopenharmony_ci ret = call_mmap(vma->vm_file, vma); 20862306a36Sopenharmony_ci if (ret) 20962306a36Sopenharmony_ci fput(realfile); 21062306a36Sopenharmony_ci else 21162306a36Sopenharmony_ci fput(file); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci file_accessed(file); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci return ret; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ciconst struct file_operations hmdfs_file_fops_local = { 21962306a36Sopenharmony_ci .owner = THIS_MODULE, 22062306a36Sopenharmony_ci .llseek = hmdfs_file_llseek_local, 22162306a36Sopenharmony_ci .read_iter = hmdfs_local_read_iter, 22262306a36Sopenharmony_ci .write_iter = hmdfs_local_write_iter, 22362306a36Sopenharmony_ci .mmap = hmdfs_file_mmap_local, 22462306a36Sopenharmony_ci .open = hmdfs_file_open_local, 22562306a36Sopenharmony_ci .release = hmdfs_file_release_local, 22662306a36Sopenharmony_ci .fsync = hmdfs_fsync_local, 22762306a36Sopenharmony_ci .splice_read = copy_splice_read, 22862306a36Sopenharmony_ci .splice_write = iter_file_splice_write, 22962306a36Sopenharmony_ci}; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic int hmdfs_iterate_local(struct file *file, struct dir_context *ctx) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci int err = 0; 23462306a36Sopenharmony_ci loff_t start_pos = ctx->pos; 23562306a36Sopenharmony_ci struct file *lower_file = hmdfs_f(file)->lower_file; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci if (ctx->pos == -1) 23862306a36Sopenharmony_ci return 0; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci lower_file->f_pos = file->f_pos; 24162306a36Sopenharmony_ci err = iterate_dir(lower_file, ctx); 24262306a36Sopenharmony_ci file->f_pos = lower_file->f_pos; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (err < 0) 24562306a36Sopenharmony_ci ctx->pos = -1; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci trace_hmdfs_iterate_local(file->f_path.dentry, start_pos, ctx->pos, 24862306a36Sopenharmony_ci err); 24962306a36Sopenharmony_ci return err; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ciint hmdfs_dir_open_local(struct inode *inode, struct file *file) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci int err = 0; 25562306a36Sopenharmony_ci struct file *lower_file = NULL; 25662306a36Sopenharmony_ci struct dentry *dentry = file->f_path.dentry; 25762306a36Sopenharmony_ci struct path lower_path; 25862306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 25962306a36Sopenharmony_ci const struct cred *cred = hmdfs_sb(sb)->cred; 26062306a36Sopenharmony_ci struct hmdfs_file_info *gfi = kzalloc(sizeof(*gfi), GFP_KERNEL); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (!gfi) 26362306a36Sopenharmony_ci return -ENOMEM; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (IS_ERR_OR_NULL(cred)) { 26662306a36Sopenharmony_ci err = -EPERM; 26762306a36Sopenharmony_ci goto out_err; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 27062306a36Sopenharmony_ci lower_file = dentry_open(&lower_path, file->f_flags, cred); 27162306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 27262306a36Sopenharmony_ci if (IS_ERR(lower_file)) { 27362306a36Sopenharmony_ci err = PTR_ERR(lower_file); 27462306a36Sopenharmony_ci goto out_err; 27562306a36Sopenharmony_ci } else { 27662306a36Sopenharmony_ci gfi->lower_file = lower_file; 27762306a36Sopenharmony_ci file->private_data = gfi; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci return err; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ciout_err: 28262306a36Sopenharmony_ci kfree(gfi); 28362306a36Sopenharmony_ci return err; 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cistatic int hmdfs_dir_release_local(struct inode *inode, struct file *file) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci struct hmdfs_file_info *gfi = hmdfs_f(file); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci file->private_data = NULL; 29162306a36Sopenharmony_ci fput(gfi->lower_file); 29262306a36Sopenharmony_ci kfree(gfi); 29362306a36Sopenharmony_ci return 0; 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ciconst struct file_operations hmdfs_dir_ops_local = { 29762306a36Sopenharmony_ci .owner = THIS_MODULE, 29862306a36Sopenharmony_ci .iterate_shared = hmdfs_iterate_local, 29962306a36Sopenharmony_ci .open = hmdfs_dir_open_local, 30062306a36Sopenharmony_ci .release = hmdfs_dir_release_local, 30162306a36Sopenharmony_ci .fsync = hmdfs_fsync_local, 30262306a36Sopenharmony_ci}; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic int __hmdfs_ioc_set_share_path(struct file *file, 30562306a36Sopenharmony_ci struct hmdfs_share_control *sc) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct super_block *sb = file->f_inode->i_sb; 30862306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(sb); 30962306a36Sopenharmony_ci struct hmdfs_share_table *st = &sbi->share_table; 31062306a36Sopenharmony_ci struct hmdfs_share_item *item; 31162306a36Sopenharmony_ci struct dentry *dentry; 31262306a36Sopenharmony_ci const char *dir_path, *full_path; 31362306a36Sopenharmony_ci struct qstr relative_path; 31462306a36Sopenharmony_ci struct fd src; 31562306a36Sopenharmony_ci int err = 0; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci src = fdget(sc->src_fd); 31862306a36Sopenharmony_ci if (!src.file) 31962306a36Sopenharmony_ci return -EBADF; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* only reg file can be shared */ 32262306a36Sopenharmony_ci if (!S_ISREG(src.file->f_inode->i_mode)) { 32362306a36Sopenharmony_ci err = -EPERM; 32462306a36Sopenharmony_ci goto err_out; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* share file is not allowed to be shared */ 32862306a36Sopenharmony_ci if (hmdfs_is_share_file(src.file)) { 32962306a36Sopenharmony_ci err = -EPERM; 33062306a36Sopenharmony_ci goto err_out; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci dentry = src.file->f_path.dentry; 33462306a36Sopenharmony_ci if (dentry->d_name.len > NAME_MAX) { 33562306a36Sopenharmony_ci err = -ENAMETOOLONG; 33662306a36Sopenharmony_ci goto err_out; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci dir_path = hmdfs_get_dentry_relative_path(file->f_path.dentry); 34062306a36Sopenharmony_ci if (unlikely(!dir_path)) { 34162306a36Sopenharmony_ci err = -ENOMEM; 34262306a36Sopenharmony_ci goto err_out; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci full_path = hmdfs_connect_path(dir_path, dentry->d_name.name); 34662306a36Sopenharmony_ci if (unlikely(!full_path)) { 34762306a36Sopenharmony_ci err = -ENOMEM; 34862306a36Sopenharmony_ci goto free_dir; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci relative_path.name = full_path; 35162306a36Sopenharmony_ci relative_path.len = strlen(full_path); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci spin_lock(&sbi->share_table.item_list_lock); 35462306a36Sopenharmony_ci item = hmdfs_lookup_share_item(st, &relative_path); 35562306a36Sopenharmony_ci if (!item) { 35662306a36Sopenharmony_ci err = insert_share_item(st, &relative_path, src.file, sc->cid); 35762306a36Sopenharmony_ci goto unlock; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (item->opened) 36162306a36Sopenharmony_ci err = -EEXIST; 36262306a36Sopenharmony_ci else 36362306a36Sopenharmony_ci update_share_item(item, src.file, sc->cid); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ciunlock: 36662306a36Sopenharmony_ci spin_unlock(&sbi->share_table.item_list_lock); 36762306a36Sopenharmony_ci kfree(full_path); 36862306a36Sopenharmony_cifree_dir: 36962306a36Sopenharmony_ci kfree(dir_path); 37062306a36Sopenharmony_cierr_out: 37162306a36Sopenharmony_ci fdput(src); 37262306a36Sopenharmony_ci return err; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cistatic int hmdfs_ioc_set_share_path(struct file *file, unsigned long arg) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci struct hmdfs_share_control sc; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (copy_from_user(&sc, (struct hmdfs_share_control __user *)arg, 38062306a36Sopenharmony_ci sizeof(sc))) 38162306a36Sopenharmony_ci return -EFAULT; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci return __hmdfs_ioc_set_share_path(file, &sc); 38462306a36Sopenharmony_ci} 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_cistatic long hmdfs_dir_ioctl_local(struct file *file, unsigned int cmd, 38762306a36Sopenharmony_ci unsigned long arg) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci switch (cmd) { 39062306a36Sopenharmony_ci case HMDFS_IOC_SET_SHARE_PATH: 39162306a36Sopenharmony_ci return hmdfs_ioc_set_share_path(file, arg); 39262306a36Sopenharmony_ci default: 39362306a36Sopenharmony_ci return -ENOTTY; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ciconst struct file_operations hmdfs_dir_ops_share = { 39862306a36Sopenharmony_ci .owner = THIS_MODULE, 39962306a36Sopenharmony_ci .iterate_shared = hmdfs_iterate_local, 40062306a36Sopenharmony_ci .open = hmdfs_dir_open_local, 40162306a36Sopenharmony_ci .release = hmdfs_dir_release_local, 40262306a36Sopenharmony_ci .fsync = hmdfs_fsync_local, 40362306a36Sopenharmony_ci .unlocked_ioctl = hmdfs_dir_ioctl_local, 40462306a36Sopenharmony_ci .compat_ioctl = hmdfs_dir_ioctl_local, 40562306a36Sopenharmony_ci}; 406