• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * fs/hmdfs/file_cloud.c
4  *
5  * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
6  */
7 
8 #include <linux/backing-dev.h>
9 #include <linux/file.h>
10 #include <linux/fs.h>
11 #include <linux/namei.h>
12 #include <linux/page-flags.h>
13 #include <linux/pagemap.h>
14 #include <linux/pagevec.h>
15 #include <linux/sched/signal.h>
16 #include <linux/slab.h>
17 #include <linux/wait.h>
18 
19 #include "file_remote.h"
20 
21 #include "comm/socket_adapter.h"
22 #include "hmdfs.h"
23 #include "hmdfs_client.h"
24 #include "hmdfs_dentryfile.h"
25 #include "hmdfs_dentryfile_cloud.h"
26 #include "hmdfs_trace.h"
27 
28 static const struct vm_operations_struct hmdfs_cloud_vm_ops = {
29 	.fault = filemap_fault,
30 	.map_pages = filemap_map_pages,
31 	.page_mkwrite = NULL,
32 };
33 
hmdfs_file_read_iter_cloud(struct kiocb * iocb,struct iov_iter * iter)34 static ssize_t hmdfs_file_read_iter_cloud(struct kiocb *iocb,
35 					  struct iov_iter *iter)
36 {
37 	ssize_t ret = -ENOENT;
38 	struct file *filp = iocb->ki_filp;
39 	struct hmdfs_file_info *gfi = filp->private_data;
40 	struct file *lower_file = NULL;
41 
42 	if (gfi)
43 		lower_file = gfi->lower_file;
44 
45 	if (lower_file) {
46 		kiocb_clone(iocb, iocb, lower_file);
47 		ret = vfs_iter_read(lower_file, iter, &iocb->ki_pos, 0);
48 	}
49 
50 	return ret;
51 }
52 
hmdfs_file_open_cloud(struct inode * inode,struct file * file)53 int hmdfs_file_open_cloud(struct inode *inode, struct file *file)
54 {
55 	const char *dir_path;
56 	struct hmdfs_sb_info *sbi = inode->i_sb->s_fs_info;
57 	struct path root_path;
58 	struct file *lower_file;
59 	int err = 0;
60 
61 	struct hmdfs_file_info *gfi = kzalloc(sizeof(*gfi), GFP_KERNEL);
62 	if (!gfi)
63 		return -ENOMEM;
64 
65 	if (!sbi->cloud_dir) {
66 		hmdfs_info("no cloud_dir");
67 		kfree(gfi);
68 		return -EPERM;
69 	}
70 
71 	err = kern_path(sbi->cloud_dir, 0, &root_path);
72 	if (err) {
73 		hmdfs_info("kern_path failed: %d", err);
74 		kfree(gfi);
75 		return err;
76 	}
77 
78 	dir_path = hmdfs_get_dentry_relative_path(file->f_path.dentry);
79 	if(!dir_path) {
80 		hmdfs_err("get cloud path failed");
81 		kfree(gfi);
82 		return -ENOENT;
83 	}
84 
85 	lower_file = file_open_root(&root_path, dir_path,
86 			      file->f_flags, file->f_mode);
87 	path_put(&root_path);
88 	if (IS_ERR(lower_file)) {
89 		hmdfs_info("file_open_root failed: %ld", PTR_ERR(lower_file));
90 		err = PTR_ERR(lower_file);
91 		kfree(gfi);
92 	} else {
93 		gfi->lower_file = lower_file;
94 		file->private_data = gfi;
95 	}
96 	kfree(dir_path);
97 	return err;
98 }
99 
hmdfs_file_release_cloud(struct inode * inode,struct file * file)100 int hmdfs_file_release_cloud(struct inode *inode, struct file *file)
101 {
102 	struct hmdfs_file_info *gfi = hmdfs_f(file);
103 
104 	file->private_data = NULL;
105 	fput(gfi->lower_file);
106 	kfree(gfi);
107 	return 0;
108 }
109 
hmdfs_file_flush_cloud(struct file * file,fl_owner_t id)110 static int hmdfs_file_flush_cloud(struct file *file, fl_owner_t id)
111 {
112 	struct hmdfs_file_info *gfi = hmdfs_f(file);
113 
114 	if(!gfi || !gfi->lower_file)
115 		return 0;
116 
117 	if (gfi->lower_file->f_op->flush)
118 		return gfi->lower_file->f_op->flush(gfi->lower_file, id);
119 	return 0;
120 }
121 
hmdfs_file_mmap_cloud(struct file * file,struct vm_area_struct * vma)122 int hmdfs_file_mmap_cloud(struct file *file, struct vm_area_struct *vma)
123 {
124 	struct hmdfs_file_info *private_data = file->private_data;
125 	struct file *realfile = NULL;
126 	int ret;
127 
128 	if (!private_data)
129 		return -EINVAL;
130 
131 	realfile = private_data->lower_file;
132 	if (!realfile)
133 		return -EINVAL;
134 
135 	if (!realfile->f_op->mmap)
136 		return -ENODEV;
137 
138 	if (WARN_ON(file != vma->vm_file))
139 		return -EIO;
140 
141 	vma->vm_file = get_file(realfile);
142 	ret = call_mmap(vma->vm_file, vma);
143 	if (ret)
144 		fput(realfile);
145 	else
146 		fput(file);
147 
148 	file_accessed(file);
149 
150 	return ret;
151 }
152 
153 const struct file_operations hmdfs_dev_file_fops_cloud = {
154 	.owner = THIS_MODULE,
155 	.llseek = generic_file_llseek,
156 	.read_iter = hmdfs_file_read_iter_cloud,
157 	.write_iter = NULL,
158 	.mmap = hmdfs_file_mmap_cloud,
159 	.open = hmdfs_file_open_cloud,
160 	.release = hmdfs_file_release_cloud,
161 	.flush = hmdfs_file_flush_cloud,
162 	.fsync = NULL,
163 	.splice_read = NULL,
164 	.splice_write = NULL,
165 };
166 
167 
168 const struct address_space_operations hmdfs_dev_file_aops_cloud = {
169 	.readpage = NULL,
170 	.write_begin = NULL,
171 	.write_end = NULL,
172 	.writepage = NULL,
173 	.set_page_dirty = NULL,
174 };
175 
analysis_dentry_file_from_cloud(struct hmdfs_sb_info * sbi,struct file * file,struct file * handler,struct dir_context * ctx)176 int analysis_dentry_file_from_cloud(struct hmdfs_sb_info *sbi,
177 				    struct file *file, struct file *handler,
178 				    struct dir_context *ctx)
179 {
180 	struct hmdfs_dentry_group_cloud *dentry_group = NULL;
181 	loff_t pos = ctx->pos;
182 	unsigned long dev_id = (unsigned long)((pos << 1) >> (POS_BIT_NUM - DEV_ID_BIT_NUM));
183 	unsigned long group_id = (unsigned long)((pos << (1 + DEV_ID_BIT_NUM)) >>
184 				 (POS_BIT_NUM - GROUP_ID_BIT_NUM));
185 	loff_t offset = pos & OFFSET_BIT_MASK;
186 	int group_num = 0;
187 	char *dentry_name = NULL;
188 	int iterate_result = 0;
189 	int i, j;
190 
191 	dentry_group = kzalloc(sizeof(*dentry_group), GFP_KERNEL);
192 
193 	if (!dentry_group)
194 		return -ENOMEM;
195 
196 	if (IS_ERR_OR_NULL(handler)) {
197 		kfree(dentry_group);
198 		return -ENOENT;
199 	}
200 
201 	group_num = get_dentry_group_cnt(file_inode(handler));
202 	dentry_name = kzalloc(DENTRY_NAME_MAX_LEN, GFP_KERNEL);
203 	if (!dentry_name) {
204 		kfree(dentry_group);
205 		return -ENOMEM;
206 	}
207 
208 	for (i = group_id; i < group_num; i++) {
209 		int ret = hmdfs_metainfo_read(sbi, handler, dentry_group,
210 					      sizeof(struct hmdfs_dentry_group_cloud),
211 					      i);
212 		if (ret != sizeof(struct hmdfs_dentry_group_cloud)) {
213 			hmdfs_err("read dentry group failed ret:%d", ret);
214 			goto done;
215 		}
216 
217 		for (j = offset; j < DENTRY_PER_GROUP_CLOUD; j++) {
218 			int len;
219 			int file_type = DT_UNKNOWN;
220 			bool is_continue;
221 
222 			len = le16_to_cpu(dentry_group->nsl[j].namelen);
223 			if (!test_bit_le(j, dentry_group->bitmap) || len == 0)
224 				continue;
225 
226 			memset(dentry_name, 0, DENTRY_NAME_MAX_LEN);
227 			if (S_ISDIR(le16_to_cpu(dentry_group->nsl[j].i_mode)))
228 				file_type = DT_DIR;
229 			else if (S_ISREG(le16_to_cpu(
230 					 dentry_group->nsl[j].i_mode)))
231 				file_type = DT_REG;
232 
233 			strncat(dentry_name, dentry_group->filename[j], len);
234 			pos = hmdfs_set_pos(dev_id, i, j);
235 			is_continue =
236 				dir_emit(ctx, dentry_name, len,
237 					 pos + INUNUMBER_START, file_type);
238 			if (!is_continue) {
239 				ctx->pos = pos;
240 				iterate_result = 1;
241 				goto done;
242 			}
243 		}
244 		offset = 0;
245 	}
246 
247 done:
248 	kfree(dentry_name);
249 	kfree(dentry_group);
250 	return iterate_result;
251 }
252 
hmdfs_iterate_cloud(struct file * file,struct dir_context * ctx)253 static int hmdfs_iterate_cloud(struct file *file, struct dir_context *ctx)
254 {
255 	int err = 0;
256 	loff_t start_pos = ctx->pos;
257 
258 	if (ctx->pos == -1)
259 		return 0;
260 	err = analysis_dentry_file_from_cloud(
261 		file->f_inode->i_sb->s_fs_info, file, file->private_data, ctx);
262 
263 	if (err <= 0)
264 		ctx->pos = -1;
265 
266 	trace_hmdfs_iterate_remote(file->f_path.dentry, start_pos, ctx->pos,
267 				   err);
268 	return err;
269 }
270 
hmdfs_dir_open_cloud(struct inode * inode,struct file * file)271 int hmdfs_dir_open_cloud(struct inode *inode, struct file *file)
272 {
273 	struct clearcache_item *cache_item = NULL;
274 
275 	get_cloud_cache_file(file->f_path.dentry, file->f_inode->i_sb->s_fs_info);
276 	cache_item = hmdfs_find_cache_item(CLOUD_DEVICE,
277 					   file->f_path.dentry);
278 	if (cache_item) {
279 		file->private_data = cache_item->filp;
280 		get_file(file->private_data);
281 		kref_put(&cache_item->ref, release_cache_item);
282 		return 0;
283 	}
284 
285 	return -ENOENT;
286 }
287 
hmdfs_dir_release_cloud(struct inode * inode,struct file * file)288 static int hmdfs_dir_release_cloud(struct inode *inode, struct file *file)
289 {
290 	if (file->private_data)
291 		fput(file->private_data);
292 	file->private_data = NULL;
293 	return 0;
294 }
295 
296 const struct file_operations hmdfs_dev_dir_ops_cloud = {
297 	.owner = THIS_MODULE,
298 	.iterate = hmdfs_iterate_cloud,
299 	.open = hmdfs_dir_open_cloud,
300 	.release = hmdfs_dir_release_cloud,
301 	.fsync = __generic_file_fsync,
302 };
303