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 folio_clear_uptodate((struct folio *)vec[idx]);
178 filemap_remove_folio((struct folio *)vec[idx]);
179 unlock_page(vec[idx]);
180 put_page(vec[idx]);
181 }
182 out:
183 return ret;
184 }
185
hmdfs_readahead(struct readahead_control *ractl)186 static void hmdfs_readahead(struct readahead_control *ractl)
187 {
188 struct file *filp = ractl->file;
189 struct address_space *mapping = ractl->mapping;
190 unsigned int nr_pages = readahead_count(ractl);
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;
202 }
203
204 cnt = 0;
205 next_index = 0;
206 for (idx = 0; idx < nr_pages; ++idx) {
207 struct page *page = readahead_page(ractl);
208
209 if (add_to_page_cache_lru(page, mapping, page->index, gfp)) {
210 unlock_page(page);
211 put_page(page);
212 continue;
213 }
214
215 if (cnt && (cnt >= limit || page->index != next_index)) {
216 ret = hmdfs_do_readpages_cloud(filp, cnt, vec);
217 cnt = 0;
218 if (ret)
219 break;
220 }
221 next_index = page->index + 1;
222 vec[cnt++] = page;
223 }
224
225 if (cnt)
226 ret = hmdfs_do_readpages_cloud(filp, cnt, vec);
227
228 kfree(vec);
229 trace_hmdfs_readpages_cloud(nr_pages, ret);
230 return;
231 }
232
hmdfs_readpage(struct file *file, struct page *page)233 static int hmdfs_readpage(struct file *file, struct page *page)
234 {
235 loff_t offset = page_file_offset(page);
236 int ret = -EACCES;
237 char *page_buf;
238 struct hmdfs_file_info *gfi = file->private_data;
239 struct file *lower_file;
240
241 if (gfi)
242 lower_file = gfi->lower_file;
243 else
244 goto out;
245
246 page_buf = kmap(page);
247 if (!page_buf)
248 goto out;
249 ret = kernel_read(lower_file, page_buf, PAGE_SIZE, &offset);
250
251 if (ret >= 0 && ret <= PAGE_SIZE) {
252 ret = 0;
253 memset(page_buf + ret, 0, PAGE_SIZE - ret);
254 }
255
256 kunmap(page);
257 if (ret == 0)
258 SetPageUptodate(page);
259 out:
260 unlock_page(page);
261 return ret;
262 }
263
hmdfs_read_folio(struct file *file, struct folio *folio)264 static int hmdfs_read_folio(struct file *file, struct folio *folio)
265 {
266 struct page *page = &folio->page;
267 return hmdfs_readpage(file, page);
268 }
269
270 const struct file_operations hmdfs_dev_file_fops_cloud = {
271 .owner = THIS_MODULE,
272 .llseek = generic_file_llseek,
273 .read_iter = generic_file_read_iter,
274 .write_iter = NULL,
275 .mmap = hmdfs_file_mmap_cloud,
276 .open = hmdfs_file_open_cloud,
277 .release = hmdfs_file_release_cloud,
278 .flush = hmdfs_file_flush_cloud,
279 .fsync = NULL,
280 .splice_read = NULL,
281 .splice_write = NULL,
282 };
283
284
285 const struct address_space_operations hmdfs_dev_file_aops_cloud = {
286 .read_folio = hmdfs_read_folio,
287 .readahead = hmdfs_readahead,
288 .write_begin = NULL,
289 .write_end = NULL,
290 .writepage = NULL,
291 .dirty_folio = NULL,
292 };
293
294 const struct address_space_operations hmdfs_aops_cloud = {
295 .read_folio = hmdfs_read_folio,
296 .readahead = hmdfs_readahead,
297 };
298
analysis_dentry_file_from_cloud(struct hmdfs_sb_info *sbi, struct file *file, struct file *handler, struct dir_context *ctx)299 int analysis_dentry_file_from_cloud(struct hmdfs_sb_info *sbi,
300 struct file *file, struct file *handler,
301 struct dir_context *ctx)
302 {
303 struct hmdfs_dentry_group_cloud *dentry_group = NULL;
304 loff_t pos = ctx->pos;
305 unsigned long dev_id = (unsigned long)((pos << 1) >> (POS_BIT_NUM - DEV_ID_BIT_NUM));
306 unsigned long group_id = (unsigned long)((pos << (1 + DEV_ID_BIT_NUM)) >>
307 (POS_BIT_NUM - GROUP_ID_BIT_NUM));
308 loff_t offset = pos & OFFSET_BIT_MASK;
309 int group_num = 0;
310 char *dentry_name = NULL;
311 int iterate_result = 0;
312 int i, j;
313
314 dentry_group = kzalloc(sizeof(*dentry_group), GFP_KERNEL);
315
316 if (!dentry_group)
317 return -ENOMEM;
318
319 if (IS_ERR_OR_NULL(handler)) {
320 kfree(dentry_group);
321 return -ENOENT;
322 }
323
324 group_num = get_dentry_group_cnt(file_inode(handler));
325 dentry_name = kzalloc(DENTRY_NAME_MAX_LEN, GFP_KERNEL);
326 if (!dentry_name) {
327 kfree(dentry_group);
328 return -ENOMEM;
329 }
330
331 for (i = group_id; i < group_num; i++) {
332 int ret = hmdfs_metainfo_read_nocred(handler, dentry_group,
333 sizeof(struct hmdfs_dentry_group_cloud),
334 i);
335 if (ret != sizeof(struct hmdfs_dentry_group_cloud)) {
336 hmdfs_err("read dentry group failed ret:%d", ret);
337 goto done;
338 }
339
340 for (j = offset; j < DENTRY_PER_GROUP_CLOUD; j++) {
341 int len;
342 int file_type = DT_UNKNOWN;
343 bool is_continue;
344
345 len = le16_to_cpu(dentry_group->nsl[j].namelen);
346 if (!test_bit_le(j, dentry_group->bitmap) || len == 0)
347 continue;
348
349 memset(dentry_name, 0, DENTRY_NAME_MAX_LEN);
350 if (S_ISDIR(le16_to_cpu(dentry_group->nsl[j].i_mode)))
351 file_type = DT_DIR;
352 else if (S_ISREG(le16_to_cpu(
353 dentry_group->nsl[j].i_mode)))
354 file_type = DT_REG;
355
356 strncat(dentry_name, dentry_group->filename[j], len);
357 pos = hmdfs_set_pos(dev_id, i, j);
358 is_continue =
359 dir_emit(ctx, dentry_name, len,
360 pos + INUNUMBER_START, file_type);
361 if (!is_continue) {
362 ctx->pos = pos;
363 iterate_result = 1;
364 goto done;
365 }
366 }
367 offset = 0;
368 }
369
370 done:
371 kfree(dentry_name);
372 kfree(dentry_group);
373 return iterate_result;
374 }
375
hmdfs_iterate_cloud(struct file *file, struct dir_context *ctx)376 static int hmdfs_iterate_cloud(struct file *file, struct dir_context *ctx)
377 {
378 int err = 0;
379 loff_t start_pos = ctx->pos;
380
381 if (ctx->pos == -1)
382 return 0;
383 err = analysis_dentry_file_from_cloud(
384 file->f_inode->i_sb->s_fs_info, file, file->private_data, ctx);
385
386 if (err <= 0)
387 ctx->pos = -1;
388
389 trace_hmdfs_iterate_remote(file->f_path.dentry, start_pos, ctx->pos,
390 err);
391 return err;
392 }
393
hmdfs_dir_open_cloud(struct inode *inode, struct file *file)394 int hmdfs_dir_open_cloud(struct inode *inode, struct file *file)
395 {
396 struct clearcache_item *cache_item = NULL;
397
398 get_cloud_cache_file(file->f_path.dentry, file->f_inode->i_sb->s_fs_info);
399 cache_item = hmdfs_find_cache_item(CLOUD_DEVICE,
400 file->f_path.dentry);
401 if (cache_item) {
402 file->private_data = cache_item->filp;
403 get_file(file->private_data);
404 kref_put(&cache_item->ref, release_cache_item);
405 return 0;
406 }
407
408 return -ENOENT;
409 }
410
hmdfs_dir_release_cloud(struct inode *inode, struct file *file)411 static int hmdfs_dir_release_cloud(struct inode *inode, struct file *file)
412 {
413 if (file->private_data)
414 fput(file->private_data);
415 file->private_data = NULL;
416 return 0;
417 }
418
419 const struct file_operations hmdfs_dev_dir_ops_cloud = {
420 .owner = THIS_MODULE,
421 .iterate_shared = hmdfs_iterate_cloud,
422 .open = hmdfs_dir_open_cloud,
423 .release = hmdfs_dir_release_cloud,
424 .fsync = __generic_file_fsync,
425 };
426