• 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_open_cloud(struct inode * inode,struct file * file)34 int hmdfs_file_open_cloud(struct inode *inode, struct file *file)
35 {
36 	const char *dir_path;
37 	struct hmdfs_sb_info *sbi = inode->i_sb->s_fs_info;
38 	struct path root_path;
39 	struct file *lower_file;
40 	int err = 0;
41 
42 	struct hmdfs_file_info *gfi = kzalloc(sizeof(*gfi), GFP_KERNEL);
43 	if (!gfi)
44 		return -ENOMEM;
45 
46 	if (!sbi->cloud_dir) {
47 		hmdfs_info("no cloud_dir");
48 		kfree(gfi);
49 		return -EPERM;
50 	}
51 
52 	err = kern_path(sbi->cloud_dir, 0, &root_path);
53 	if (err) {
54 		hmdfs_info("kern_path failed: %d", err);
55 		kfree(gfi);
56 		return err;
57 	}
58 
59 	dir_path = hmdfs_get_dentry_relative_path(file->f_path.dentry);
60 	if(!dir_path) {
61 		hmdfs_err("get cloud path failed");
62 		kfree(gfi);
63 		return -ENOENT;
64 	}
65 
66 	lower_file = file_open_root(&root_path, dir_path,
67 			      file->f_flags | O_DIRECT, file->f_mode);
68 	path_put(&root_path);
69 	if (IS_ERR(lower_file)) {
70 		hmdfs_info("file_open_root failed: %ld", PTR_ERR(lower_file));
71 		err = PTR_ERR(lower_file);
72 		kfree(gfi);
73 	} else {
74 		gfi->lower_file = lower_file;
75 		file->private_data = gfi;
76 	}
77 	kfree(dir_path);
78 	return err;
79 }
80 
hmdfs_file_release_cloud(struct inode * inode,struct file * file)81 int hmdfs_file_release_cloud(struct inode *inode, struct file *file)
82 {
83 	struct hmdfs_file_info *gfi = hmdfs_f(file);
84 
85 	file->private_data = NULL;
86 	fput(gfi->lower_file);
87 	kfree(gfi);
88 	return 0;
89 }
90 
hmdfs_file_flush_cloud(struct file * file,fl_owner_t id)91 static int hmdfs_file_flush_cloud(struct file *file, fl_owner_t id)
92 {
93 	struct hmdfs_file_info *gfi = hmdfs_f(file);
94 
95 	if(!gfi || !gfi->lower_file)
96 		return 0;
97 
98 	if (gfi->lower_file->f_op->flush)
99 		return gfi->lower_file->f_op->flush(gfi->lower_file, id);
100 	return 0;
101 }
102 
hmdfs_file_mmap_cloud(struct file * file,struct vm_area_struct * vma)103 int hmdfs_file_mmap_cloud(struct file *file, struct vm_area_struct *vma)
104 {
105 	struct hmdfs_file_info *private_data = file->private_data;
106 	struct file *realfile = NULL;
107 	int ret;
108 
109 	if (!private_data)
110 		return -EINVAL;
111 
112 	realfile = private_data->lower_file;
113 	if (!realfile)
114 		return -EINVAL;
115 
116 	if (!realfile->f_op->mmap)
117 		return -ENODEV;
118 
119 	if (WARN_ON(file != vma->vm_file))
120 		return -EIO;
121 
122 	vma->vm_file = get_file(realfile);
123 	ret = call_mmap(vma->vm_file, vma);
124 	if (ret)
125 		fput(realfile);
126 	else
127 		fput(file);
128 
129 	file_accessed(file);
130 
131 	return ret;
132 }
133 
hmdfs_do_readpages_cloud(struct file * filp,int cnt,struct page ** vec)134 static int hmdfs_do_readpages_cloud(struct file *filp, int cnt,
135 				    struct page **vec)
136 {
137 	struct hmdfs_file_info *gfi = filp->private_data;
138 	struct file *lower_filp;
139 	loff_t pos = (loff_t)(vec[0]->index) << HMDFS_PAGE_OFFSET;
140 	void *pages_buf = NULL;
141 	int idx, ret;
142 
143 	if (gfi) {
144 		lower_filp = gfi->lower_file;
145 	}
146 	else {
147 		ret = -EINVAL;
148 		goto out_err;
149 	}
150 
151 	pages_buf = vmap(vec, cnt, VM_MAP, PAGE_KERNEL);
152 	if (!pages_buf) {
153 		ret = -ENOMEM;
154 		goto out_err;
155 	}
156 
157 	trace_hmdfs_do_readpages_cloud_begin(cnt, pos);
158 	ret = kernel_read(lower_filp, pages_buf, cnt * HMDFS_PAGE_SIZE, &pos);
159 	trace_hmdfs_do_readpages_cloud_end(cnt, pos, ret);
160 
161 	if (ret >= 0)
162 		memset(pages_buf + ret, 0, cnt * HMDFS_PAGE_SIZE - ret);
163 	else
164 		goto out_err;
165 
166 	vunmap(pages_buf);
167 	for (idx = 0; idx < cnt; ++idx) {
168 		SetPageUptodate(vec[idx]);
169 		unlock_page(vec[idx]);
170 	}
171 	goto out;
172 
173 out_err:
174 	if (pages_buf)
175 		vunmap(pages_buf);
176 	for (idx = 0; idx < cnt; ++idx) {
177 		ClearPageUptodate(vec[idx]);
178 		delete_from_page_cache(vec[idx]);
179 		unlock_page(vec[idx]);
180 		put_page(vec[idx]);
181 	}
182 out:
183 	return ret;
184 }
185 
hmdfs_readpages_cloud(struct file * filp,struct address_space * mapping,struct list_head * pages,unsigned int nr_pages)186 static int hmdfs_readpages_cloud(struct file *filp,
187 				 struct address_space *mapping,
188 				 struct list_head *pages,
189 				 unsigned int nr_pages)
190 {
191 	struct hmdfs_sb_info *sbi = hmdfs_sb(file_inode(filp)->i_sb);
192 	unsigned int ret = 0, idx, cnt, limit;
193 	unsigned long next_index;
194 	gfp_t gfp = readahead_gfp_mask(mapping);
195 	struct page **vec = NULL;
196 
197 	limit = sbi->s_readpages_nr;
198 	vec = kmalloc(limit * sizeof(*vec), GFP_KERNEL);
199 	if (!vec) {
200 		hmdfs_warning("cannot alloc vec (%u pages)", limit);
201 		return -ENOMEM;
202 	}
203 
204 	cnt = 0;
205 	next_index = 0;
206 	for (idx = 0; idx < nr_pages; ++idx) {
207 		struct page *page = lru_to_page(pages);
208 
209 		list_del(&page->lru);
210 		if (add_to_page_cache_lru(page, mapping, page->index, gfp)) {
211 			unlock_page(page);
212 			put_page(page);
213 			continue;
214 		}
215 
216 		if (cnt && (cnt >= limit || page->index != next_index)) {
217 			ret = hmdfs_do_readpages_cloud(filp, cnt, vec);
218 			cnt = 0;
219 			if (ret)
220 				break;
221 		}
222 		next_index = page->index + 1;
223 		vec[cnt++] = page;
224 	}
225 
226 	if (cnt)
227 		ret = hmdfs_do_readpages_cloud(filp, cnt, vec);
228 
229 	kfree(vec);
230 	trace_hmdfs_readpages_cloud(nr_pages, pages);
231 	return ret;
232 }
233 
hmdfs_readpage(struct file * file,struct page * page)234 static int hmdfs_readpage(struct file *file, struct page *page)
235 {
236 	loff_t offset = page_file_offset(page);
237 	int ret = -EACCES;
238 	char *page_buf;
239 	struct hmdfs_file_info *gfi = file->private_data;
240 	struct file *lower_file;
241 
242 	if (gfi)
243 		lower_file = gfi->lower_file;
244 	else
245 		goto out;
246 
247 	page_buf = kmap(page);
248 	if (!page_buf)
249 		goto out;
250 	ret = kernel_read(lower_file, page_buf, PAGE_SIZE, &offset);
251 
252 	if (ret >= 0 && ret <= PAGE_SIZE) {
253 		ret = 0;
254 		memset(page_buf + ret, 0, PAGE_SIZE - ret);
255 	}
256 
257 	kunmap(page);
258 	if (ret == 0)
259 		SetPageUptodate(page);
260 out:
261 	unlock_page(page);
262 	return ret;
263 }
264 
265 const struct file_operations hmdfs_dev_file_fops_cloud = {
266 	.owner = THIS_MODULE,
267 	.llseek = generic_file_llseek,
268 	.read_iter = generic_file_read_iter,
269 	.write_iter = NULL,
270 	.mmap = hmdfs_file_mmap_cloud,
271 	.open = hmdfs_file_open_cloud,
272 	.release = hmdfs_file_release_cloud,
273 	.flush = hmdfs_file_flush_cloud,
274 	.fsync = NULL,
275 	.splice_read = NULL,
276 	.splice_write = NULL,
277 };
278 
279 
280 const struct address_space_operations hmdfs_dev_file_aops_cloud = {
281 	.readpage = hmdfs_readpage,
282 	.readpages = hmdfs_readpages_cloud,
283 	.write_begin = NULL,
284 	.write_end = NULL,
285 	.writepage = NULL,
286 	.set_page_dirty = NULL,
287 };
288 
289 const struct address_space_operations hmdfs_aops_cloud = {
290 	.readpage = hmdfs_readpage,
291 	.readpages = hmdfs_readpages_cloud,
292 };
293 
analysis_dentry_file_from_cloud(struct hmdfs_sb_info * sbi,struct file * file,struct file * handler,struct dir_context * ctx)294 int analysis_dentry_file_from_cloud(struct hmdfs_sb_info *sbi,
295 				    struct file *file, struct file *handler,
296 				    struct dir_context *ctx)
297 {
298 	struct hmdfs_dentry_group_cloud *dentry_group = NULL;
299 	loff_t pos = ctx->pos;
300 	unsigned long dev_id = (unsigned long)((pos << 1) >> (POS_BIT_NUM - DEV_ID_BIT_NUM));
301 	unsigned long group_id = (unsigned long)((pos << (1 + DEV_ID_BIT_NUM)) >>
302 				 (POS_BIT_NUM - GROUP_ID_BIT_NUM));
303 	loff_t offset = pos & OFFSET_BIT_MASK;
304 	int group_num = 0;
305 	char *dentry_name = NULL;
306 	int iterate_result = 0;
307 	int i, j;
308 
309 	dentry_group = kzalloc(sizeof(*dentry_group), GFP_KERNEL);
310 
311 	if (!dentry_group)
312 		return -ENOMEM;
313 
314 	if (IS_ERR_OR_NULL(handler)) {
315 		kfree(dentry_group);
316 		return -ENOENT;
317 	}
318 
319 	group_num = get_dentry_group_cnt(file_inode(handler));
320 	dentry_name = kzalloc(DENTRY_NAME_MAX_LEN, GFP_KERNEL);
321 	if (!dentry_name) {
322 		kfree(dentry_group);
323 		return -ENOMEM;
324 	}
325 
326 	for (i = group_id; i < group_num; i++) {
327 		int ret = hmdfs_metainfo_read_nocred(handler, dentry_group,
328 					      sizeof(struct hmdfs_dentry_group_cloud),
329 					      i);
330 		if (ret != sizeof(struct hmdfs_dentry_group_cloud)) {
331 			hmdfs_err("read dentry group failed ret:%d", ret);
332 			goto done;
333 		}
334 
335 		for (j = offset; j < DENTRY_PER_GROUP_CLOUD; j++) {
336 			int len;
337 			int file_type = DT_UNKNOWN;
338 			bool is_continue;
339 
340 			len = le16_to_cpu(dentry_group->nsl[j].namelen);
341 			if (!test_bit_le(j, dentry_group->bitmap) || len == 0)
342 				continue;
343 
344 			memset(dentry_name, 0, DENTRY_NAME_MAX_LEN);
345 			if (S_ISDIR(le16_to_cpu(dentry_group->nsl[j].i_mode)))
346 				file_type = DT_DIR;
347 			else if (S_ISREG(le16_to_cpu(
348 					 dentry_group->nsl[j].i_mode)))
349 				file_type = DT_REG;
350 
351 			strncat(dentry_name, dentry_group->filename[j], len);
352 			pos = hmdfs_set_pos(dev_id, i, j);
353 			is_continue =
354 				dir_emit(ctx, dentry_name, len,
355 					 pos + INUNUMBER_START, file_type);
356 			if (!is_continue) {
357 				ctx->pos = pos;
358 				iterate_result = 1;
359 				goto done;
360 			}
361 		}
362 		offset = 0;
363 	}
364 
365 done:
366 	kfree(dentry_name);
367 	kfree(dentry_group);
368 	return iterate_result;
369 }
370 
hmdfs_iterate_cloud(struct file * file,struct dir_context * ctx)371 static int hmdfs_iterate_cloud(struct file *file, struct dir_context *ctx)
372 {
373 	int err = 0;
374 	loff_t start_pos = ctx->pos;
375 
376 	if (ctx->pos == -1)
377 		return 0;
378 	err = analysis_dentry_file_from_cloud(
379 		file->f_inode->i_sb->s_fs_info, file, file->private_data, ctx);
380 
381 	if (err <= 0)
382 		ctx->pos = -1;
383 
384 	trace_hmdfs_iterate_remote(file->f_path.dentry, start_pos, ctx->pos,
385 				   err);
386 	return err;
387 }
388 
hmdfs_dir_open_cloud(struct inode * inode,struct file * file)389 int hmdfs_dir_open_cloud(struct inode *inode, struct file *file)
390 {
391 	struct clearcache_item *cache_item = NULL;
392 
393 	get_cloud_cache_file(file->f_path.dentry, file->f_inode->i_sb->s_fs_info);
394 	cache_item = hmdfs_find_cache_item(CLOUD_DEVICE,
395 					   file->f_path.dentry);
396 	if (cache_item) {
397 		file->private_data = cache_item->filp;
398 		get_file(file->private_data);
399 		kref_put(&cache_item->ref, release_cache_item);
400 		return 0;
401 	}
402 
403 	return -ENOENT;
404 }
405 
hmdfs_dir_release_cloud(struct inode * inode,struct file * file)406 static int hmdfs_dir_release_cloud(struct inode *inode, struct file *file)
407 {
408 	if (file->private_data)
409 		fput(file->private_data);
410 	file->private_data = NULL;
411 	return 0;
412 }
413 
414 const struct file_operations hmdfs_dev_dir_ops_cloud = {
415 	.owner = THIS_MODULE,
416 	.iterate = hmdfs_iterate_cloud,
417 	.open = hmdfs_dir_open_cloud,
418 	.release = hmdfs_dir_release_cloud,
419 	.fsync = __generic_file_fsync,
420 };
421