1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * fs/hmdfs/inode_local.c
4 *
5 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
6 */
7
8 #include <linux/file.h>
9 #include <linux/fs_stack.h>
10 #include <linux/kernel.h>
11 #include <linux/mount.h>
12 #include <linux/namei.h>
13 #include <linux/string.h>
14
15 #include "authority/authentication.h"
16 #include "comm/socket_adapter.h"
17 #include "comm/transport.h"
18 #include "hmdfs_client.h"
19 #include "hmdfs_dentryfile.h"
20 #include "hmdfs_device_view.h"
21 #include "hmdfs_trace.h"
22
23 extern struct kmem_cache *hmdfs_dentry_cachep;
24
25 struct hmdfs_name_data {
26 struct dir_context ctx;
27 const struct qstr *to_find;
28 char *name;
29 bool found;
30 };
31
init_hmdfs_dentry_info(struct hmdfs_sb_info * sbi,struct dentry * dentry,int dentry_type)32 int init_hmdfs_dentry_info(struct hmdfs_sb_info *sbi, struct dentry *dentry,
33 int dentry_type)
34 {
35 struct hmdfs_dentry_info *info =
36 kmem_cache_zalloc(hmdfs_dentry_cachep, GFP_ATOMIC);
37
38 if (!info)
39 return -ENOMEM;
40 dentry->d_fsdata = info;
41 INIT_LIST_HEAD(&info->cache_list_head);
42 INIT_LIST_HEAD(&info->remote_cache_list_head);
43 spin_lock_init(&info->cache_list_lock);
44 mutex_init(&info->remote_cache_list_lock);
45 mutex_init(&info->cache_pull_lock);
46 spin_lock_init(&info->lock);
47 info->dentry_type = dentry_type;
48 info->device_id = 0;
49 if (dentry_type == HMDFS_LAYER_ZERO ||
50 dentry_type == HMDFS_LAYER_FIRST_DEVICE ||
51 dentry_type == HMDFS_LAYER_SECOND_LOCAL ||
52 dentry_type == HMDFS_LAYER_SECOND_REMOTE)
53 d_set_d_op(dentry, &hmdfs_dev_dops);
54 else
55 d_set_d_op(dentry, &hmdfs_dops);
56 return 0;
57 }
58
set_sharefile_flag(struct hmdfs_dentry_info * gdi)59 static inline void set_sharefile_flag(struct hmdfs_dentry_info *gdi)
60 {
61 gdi->file_type = HM_SHARE;
62 }
63
check_and_fixup_share_ops(struct inode * inode,const char * name)64 static inline void check_and_fixup_share_ops(struct inode *inode,
65 const char *name)
66 {
67 const char *share_dir = ".share";
68
69 if (S_ISDIR(inode->i_mode) &&
70 !strncmp(name, share_dir, strlen(share_dir))) {
71 inode->i_op = &hmdfs_dir_inode_ops_share;
72 inode->i_fop = &hmdfs_dir_ops_share;
73 }
74 }
75
fill_inode_local(struct super_block * sb,struct inode * lower_inode,const char * name)76 struct inode *fill_inode_local(struct super_block *sb,
77 struct inode *lower_inode, const char *name)
78 {
79 int ret = 0;
80 struct inode *inode;
81 struct hmdfs_inode_info *info;
82
83 if (!igrab(lower_inode))
84 return ERR_PTR(-ESTALE);
85
86 inode = hmdfs_iget5_locked_local(sb, lower_inode);
87 if (!inode) {
88 hmdfs_err("iget5_locked get inode NULL");
89 iput(lower_inode);
90 return ERR_PTR(-ENOMEM);
91 }
92 if (!(inode->i_state & I_NEW)) {
93 iput(lower_inode);
94 return inode;
95 }
96
97 info = hmdfs_i(inode);
98 #ifdef CONFIG_HMDFS_FS_PERMISSION
99 info->perm = hmdfs_read_perm(lower_inode);
100 #endif
101 if (S_ISDIR(lower_inode->i_mode))
102 inode->i_mode = (lower_inode->i_mode & S_IFMT) | S_IRWXU |
103 S_IRWXG | S_IXOTH;
104 else if (S_ISREG(lower_inode->i_mode))
105 inode->i_mode = (lower_inode->i_mode & S_IFMT) | S_IRUSR |
106 S_IWUSR | S_IRGRP | S_IWGRP;
107
108 #ifdef CONFIG_HMDFS_FS_PERMISSION
109 inode->i_uid = lower_inode->i_uid;
110 inode->i_gid = lower_inode->i_gid;
111 #else
112 inode->i_uid = KUIDT_INIT((uid_t)1000);
113 inode->i_gid = KGIDT_INIT((gid_t)1000);
114 #endif
115 inode->i_atime = lower_inode->i_atime;
116 inode->i_ctime = lower_inode->i_ctime;
117 inode->i_mtime = lower_inode->i_mtime;
118 inode->i_generation = lower_inode->i_generation;
119
120 info->inode_type = HMDFS_LAYER_OTHER_LOCAL;
121 if (S_ISDIR(lower_inode->i_mode)) {
122 inode->i_op = &hmdfs_dir_inode_ops_local;
123 inode->i_fop = &hmdfs_dir_ops_local;
124 inode->i_mode |= S_IXUGO;
125 } else if (S_ISREG(lower_inode->i_mode)) {
126 inode->i_op = &hmdfs_file_iops_local;
127 inode->i_fop = &hmdfs_file_fops_local;
128 } else {
129 ret = -EIO;
130 goto bad_inode;
131 }
132
133 fsstack_copy_inode_size(inode, lower_inode);
134 check_and_fixup_share_ops(inode, name);
135 unlock_new_inode(inode);
136 return inode;
137 bad_inode:
138 iget_failed(inode);
139 return ERR_PTR(ret);
140 }
141
142 /* hmdfs_convert_lookup_flags - covert hmdfs lookup flags to vfs lookup flags
143 *
144 * @hmdfs_flags: hmdfs lookup flags
145 * @vfs_flags: pointer to converted flags
146 *
147 * return 0 on success, or err code on failure.
148 */
hmdfs_convert_lookup_flags(unsigned int hmdfs_flags,unsigned int * vfs_flags)149 int hmdfs_convert_lookup_flags(unsigned int hmdfs_flags,
150 unsigned int *vfs_flags)
151 {
152 *vfs_flags = 0;
153
154 /* currently only support HMDFS_LOOKUP_REVAL */
155 if (hmdfs_flags & ~HMDFS_LOOKUP_REVAL)
156 return -EINVAL;
157
158 if (hmdfs_flags & HMDFS_LOOKUP_REVAL)
159 *vfs_flags |= LOOKUP_REVAL;
160
161 return 0;
162 }
163
hmdfs_name_match(struct dir_context * ctx,const char * name,int namelen,loff_t offset,u64 ino,unsigned int d_type)164 static int hmdfs_name_match(struct dir_context *ctx, const char *name,
165 int namelen, loff_t offset, u64 ino,
166 unsigned int d_type)
167 {
168 struct hmdfs_name_data *buf =
169 container_of(ctx, struct hmdfs_name_data, ctx);
170 struct qstr candidate = QSTR_INIT(name, namelen);
171
172 if (qstr_case_eq(buf->to_find, &candidate)) {
173 memcpy(buf->name, name, namelen);
174 buf->name[namelen] = 0;
175 buf->found = true;
176 return 1;
177 }
178 return 0;
179 }
180
__lookup_nosensitive(struct path * lower_parent_path,struct dentry * child_dentry,unsigned int flags,struct path * lower_path)181 static int __lookup_nosensitive(struct path *lower_parent_path,
182 struct dentry *child_dentry, unsigned int flags,
183 struct path *lower_path)
184 {
185 struct file *file;
186 const struct cred *cred = current_cred();
187 const struct qstr *name = &child_dentry->d_name;
188 int err;
189 struct hmdfs_name_data buffer = {
190 .ctx.actor = hmdfs_name_match,
191 .to_find = name,
192 .name = __getname(),
193 .found = false,
194 };
195
196 if (!buffer.name) {
197 err = -ENOMEM;
198 goto out;
199 }
200 file = dentry_open(lower_parent_path, O_RDONLY, cred);
201 if (IS_ERR(file)) {
202 err = PTR_ERR(file);
203 goto put_name;
204 }
205 err = iterate_dir(file, &buffer.ctx);
206 fput(file);
207 if (err)
208 goto put_name;
209 if (buffer.found)
210 err = vfs_path_lookup(lower_parent_path->dentry,
211 lower_parent_path->mnt, buffer.name,
212 flags, lower_path);
213 else
214 err = -ENOENT;
215 put_name:
216 __putname(buffer.name);
217 out:
218 return err;
219 }
220
hmdfs_lookup_local(struct inode * parent_inode,struct dentry * child_dentry,unsigned int flags)221 struct dentry *hmdfs_lookup_local(struct inode *parent_inode,
222 struct dentry *child_dentry,
223 unsigned int flags)
224 {
225 const char *d_name = child_dentry->d_name.name;
226 int err = 0;
227 struct path lower_path, lower_parent_path;
228 struct dentry *lower_dentry = NULL, *parent_dentry = NULL, *ret = NULL;
229 struct hmdfs_dentry_info *gdi = NULL;
230 struct inode *child_inode = NULL;
231 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
232
233 trace_hmdfs_lookup_local(parent_inode, child_dentry, flags);
234 if (child_dentry->d_name.len > NAME_MAX) {
235 ret = ERR_PTR(-ENAMETOOLONG);
236 goto out;
237 }
238
239 /* local device */
240 parent_dentry = dget_parent(child_dentry);
241 hmdfs_get_lower_path(parent_dentry, &lower_parent_path);
242 err = init_hmdfs_dentry_info(sbi, child_dentry,
243 HMDFS_LAYER_OTHER_LOCAL);
244 if (err) {
245 ret = ERR_PTR(err);
246 goto out_err;
247 }
248
249 gdi = hmdfs_d(child_dentry);
250
251 flags &= ~LOOKUP_FOLLOW;
252 err = vfs_path_lookup(lower_parent_path.dentry, lower_parent_path.mnt,
253 (child_dentry->d_name.name), 0, &lower_path);
254 if (err == -ENOENT && !sbi->s_case_sensitive)
255 err = __lookup_nosensitive(&lower_parent_path, child_dentry, 0,
256 &lower_path);
257 if (err && err != -ENOENT) {
258 ret = ERR_PTR(err);
259 goto out_err;
260 } else if (!err) {
261 hmdfs_set_lower_path(child_dentry, &lower_path);
262 child_inode = fill_inode_local(parent_inode->i_sb,
263 d_inode(lower_path.dentry),
264 child_dentry->d_name.name);
265
266 if (IS_ERR(child_inode)) {
267 err = PTR_ERR(child_inode);
268 ret = ERR_PTR(err);
269 hmdfs_put_reset_lower_path(child_dentry);
270 goto out_err;
271 }
272 ret = d_splice_alias(child_inode, child_dentry);
273 if (IS_ERR(ret)) {
274 err = PTR_ERR(ret);
275 hmdfs_put_reset_lower_path(child_dentry);
276 goto out_err;
277 }
278
279 check_and_fixup_ownership(parent_inode, child_inode);
280 goto out_err;
281 }
282 /*
283 * return 0 here, so that vfs can continue the process of making this
284 * negative dentry to a positive one while creating a new file.
285 */
286 err = 0;
287 ret = 0;
288
289 lower_dentry = lookup_one_len_unlocked(d_name, lower_parent_path.dentry,
290 child_dentry->d_name.len);
291 if (IS_ERR(lower_dentry)) {
292 err = PTR_ERR(lower_dentry);
293 ret = lower_dentry;
294 goto out_err;
295 }
296 lower_path.dentry = lower_dentry;
297 lower_path.mnt = mntget(lower_parent_path.mnt);
298 hmdfs_set_lower_path(child_dentry, &lower_path);
299
300 out_err:
301 if (!err)
302 hmdfs_set_time(child_dentry, jiffies);
303 hmdfs_put_lower_path(&lower_parent_path);
304 dput(parent_dentry);
305 out:
306 trace_hmdfs_lookup_local_end(parent_inode, child_dentry, err);
307 return ret;
308 }
309
hmdfs_mkdir_local_dentry(struct inode * dir,struct dentry * dentry,umode_t mode)310 int hmdfs_mkdir_local_dentry(struct inode *dir, struct dentry *dentry,
311 umode_t mode)
312 {
313 struct inode *lower_dir = hmdfs_i(dir)->lower_inode;
314 struct dentry *lower_dir_dentry = NULL;
315 struct super_block *sb = dir->i_sb;
316 struct path lower_path;
317 struct dentry *lower_dentry = NULL;
318 int error = 0;
319 struct inode *lower_inode = NULL;
320 struct inode *child_inode = NULL;
321 bool local_res = false;
322 struct cache_fs_override or;
323 __u16 child_perm;
324 kuid_t tmp_uid;
325
326 error = hmdfs_override_dir_id_fs(&or, dir, dentry, &child_perm);
327 if (error)
328 goto cleanup;
329
330 hmdfs_get_lower_path(dentry, &lower_path);
331 lower_dentry = lower_path.dentry;
332 lower_dir_dentry = lock_parent(lower_dentry);
333
334 tmp_uid = hmdfs_override_inode_uid(lower_dir);
335 mode = (mode & S_IFMT) | 00771;
336
337 error = vfs_mkdir(lower_dir, lower_dentry, mode);
338 hmdfs_revert_inode_uid(lower_dir, tmp_uid);
339 if (error) {
340 hmdfs_err("vfs_mkdir() error:%d", error);
341 goto out;
342 }
343 local_res = true;
344 lower_inode = d_inode(lower_dentry);
345 #ifdef CONFIG_HMDFS_FS_PERMISSION
346 error = hmdfs_persist_perm(lower_dentry, &child_perm);
347 #endif
348 child_inode = fill_inode_local(sb, lower_inode, dentry->d_name.name);
349 if (IS_ERR(child_inode)) {
350 error = PTR_ERR(child_inode);
351 goto out;
352 }
353 d_add(dentry, child_inode);
354 set_nlink(dir, hmdfs_i(dir)->lower_inode->i_nlink);
355 out:
356 unlock_dir(lower_dir_dentry);
357 if (local_res)
358 hmdfs_drop_remote_cache_dents(dentry->d_parent);
359
360 if (error) {
361 hmdfs_clear_drop_flag(dentry->d_parent);
362 d_drop(dentry);
363 }
364 hmdfs_put_lower_path(&lower_path);
365 hmdfs_revert_dir_id_fs(&or);
366 cleanup:
367 return error;
368 }
369
hmdfs_mkdir_local(struct inode * dir,struct dentry * dentry,umode_t mode)370 int hmdfs_mkdir_local(struct inode *dir, struct dentry *dentry, umode_t mode)
371 {
372 int err = 0;
373
374 if (check_filename(dentry->d_name.name, dentry->d_name.len)) {
375 err = -EINVAL;
376 return err;
377 }
378
379 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) {
380 err = -EACCES;
381 return err;
382 }
383 err = hmdfs_mkdir_local_dentry(dir, dentry, mode);
384 trace_hmdfs_mkdir_local(dir, dentry, err);
385 return err;
386 }
387
hmdfs_create_local_dentry(struct inode * dir,struct dentry * dentry,umode_t mode,bool want_excl)388 int hmdfs_create_local_dentry(struct inode *dir, struct dentry *dentry,
389 umode_t mode, bool want_excl)
390 {
391 struct inode *lower_dir = NULL;
392 struct dentry *lower_dir_dentry = NULL;
393 struct super_block *sb = dir->i_sb;
394 struct path lower_path;
395 struct dentry *lower_dentry = NULL;
396 int error = 0;
397 struct inode *lower_inode = NULL;
398 struct inode *child_inode = NULL;
399 kuid_t tmp_uid;
400 #ifdef CONFIG_HMDFS_FS_PERMISSION
401 const struct cred *saved_cred = NULL;
402 struct fs_struct *saved_fs = NULL, *copied_fs = NULL;
403 __u16 child_perm;
404 #endif
405
406 #ifdef CONFIG_HMDFS_FS_PERMISSION
407 saved_cred = hmdfs_override_file_fsids(dir, &child_perm);
408 if (!saved_cred) {
409 error = -ENOMEM;
410 goto path_err;
411 }
412
413 saved_fs = current->fs;
414 copied_fs = hmdfs_override_fsstruct(saved_fs);
415 if (!copied_fs) {
416 error = -ENOMEM;
417 goto revert_fsids;
418 }
419 #endif
420 hmdfs_get_lower_path(dentry, &lower_path);
421 lower_dentry = lower_path.dentry;
422 mode = (mode & S_IFMT) | 00660;
423 lower_dir_dentry = lock_parent(lower_dentry);
424 lower_dir = d_inode(lower_dir_dentry);
425 tmp_uid = hmdfs_override_inode_uid(lower_dir);
426 error = vfs_create(lower_dir, lower_dentry, mode, want_excl);
427 hmdfs_revert_inode_uid(lower_dir, tmp_uid);
428 unlock_dir(lower_dir_dentry);
429 if (error)
430 goto out;
431
432 lower_inode = d_inode(lower_dentry);
433 #ifdef CONFIG_HMDFS_FS_PERMISSION
434 error = hmdfs_persist_perm(lower_dentry, &child_perm);
435 #endif
436 child_inode = fill_inode_local(sb, lower_inode, dentry->d_name.name);
437 if (IS_ERR(child_inode)) {
438 error = PTR_ERR(child_inode);
439 goto out_created;
440 }
441 d_add(dentry, child_inode);
442
443 out_created:
444 hmdfs_drop_remote_cache_dents(dentry->d_parent);
445 out:
446 if (error) {
447 hmdfs_clear_drop_flag(dentry->d_parent);
448 d_drop(dentry);
449 }
450 hmdfs_put_lower_path(&lower_path);
451
452 #ifdef CONFIG_HMDFS_FS_PERMISSION
453 hmdfs_revert_fsstruct(saved_fs, copied_fs);
454 revert_fsids:
455 hmdfs_revert_fsids(saved_cred);
456 #endif
457 #ifdef CONFIG_HMDFS_FS_PERMISSION
458 path_err:
459 #endif
460 return error;
461 }
462
hmdfs_create_local(struct inode * dir,struct dentry * child_dentry,umode_t mode,bool want_excl)463 int hmdfs_create_local(struct inode *dir, struct dentry *child_dentry,
464 umode_t mode, bool want_excl)
465 {
466 int err = 0;
467
468 if (check_filename(child_dentry->d_name.name,
469 child_dentry->d_name.len)) {
470 err = -EINVAL;
471 return err;
472 }
473
474 if (hmdfs_file_type(child_dentry->d_name.name) != HMDFS_TYPE_COMMON) {
475 err = -EACCES;
476 return err;
477 }
478
479 err = hmdfs_create_local_dentry(dir, child_dentry, mode, want_excl);
480 trace_hmdfs_create_local(dir, child_dentry, err);
481 return err;
482 }
483
hmdfs_rmdir_local_dentry(struct inode * dir,struct dentry * dentry)484 int hmdfs_rmdir_local_dentry(struct inode *dir, struct dentry *dentry)
485 {
486 struct inode *lower_dir = NULL;
487 struct dentry *lower_dir_dentry = NULL;
488 kuid_t tmp_uid;
489 struct path lower_path;
490 struct dentry *lower_dentry = NULL;
491 int error = 0;
492
493 hmdfs_clear_cache_dents(dentry, true);
494 hmdfs_get_lower_path(dentry, &lower_path);
495 lower_dentry = lower_path.dentry;
496 lower_dir_dentry = lock_parent(lower_dentry);
497 lower_dir = d_inode(lower_dir_dentry);
498 tmp_uid = hmdfs_override_inode_uid(lower_dir);
499
500 error = vfs_rmdir(lower_dir, lower_dentry);
501 hmdfs_revert_inode_uid(lower_dir, tmp_uid);
502 unlock_dir(lower_dir_dentry);
503 hmdfs_put_lower_path(&lower_path);
504 if (error)
505 goto path_err;
506 hmdfs_drop_remote_cache_dents(dentry->d_parent);
507 path_err:
508 if (error)
509 hmdfs_clear_drop_flag(dentry->d_parent);
510 return error;
511 }
512
hmdfs_rmdir_local(struct inode * dir,struct dentry * dentry)513 int hmdfs_rmdir_local(struct inode *dir, struct dentry *dentry)
514 {
515 int err = 0;
516
517 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) {
518 err = -EACCES;
519 goto out;
520 }
521
522 err = hmdfs_rmdir_local_dentry(dir, dentry);
523 if (err != 0) {
524 hmdfs_err("rm dir failed:%d", err);
525 goto out;
526 }
527
528 /* drop dentry even remote failed
529 * it maybe cause that one remote devices disconnect
530 * when doing remote rmdir
531 */
532 d_drop(dentry);
533 out:
534 /* return connect device's errcode */
535 trace_hmdfs_rmdir_local(dir, dentry, err);
536 return err;
537 }
538
hmdfs_unlink_local_dentry(struct inode * dir,struct dentry * dentry)539 int hmdfs_unlink_local_dentry(struct inode *dir, struct dentry *dentry)
540 {
541 struct inode *lower_dir = hmdfs_i(dir)->lower_inode;
542 struct dentry *lower_dir_dentry = NULL;
543 struct path lower_path;
544 struct dentry *lower_dentry = NULL;
545 int error;
546 kuid_t tmp_uid;
547
548 hmdfs_get_lower_path(dentry, &lower_path);
549 lower_dentry = lower_path.dentry;
550 dget(lower_dentry);
551 lower_dir_dentry = lock_parent(lower_dentry);
552 tmp_uid = hmdfs_override_inode_uid(lower_dir);
553 error = vfs_unlink(lower_dir, lower_dentry, NULL);
554 hmdfs_revert_inode_uid(lower_dir, tmp_uid);
555 set_nlink(d_inode(dentry),
556 hmdfs_i(d_inode(dentry))->lower_inode->i_nlink);
557 unlock_dir(lower_dir_dentry);
558 dput(lower_dentry);
559 if (error)
560 goto path_err;
561
562 hmdfs_drop_remote_cache_dents(dentry->d_parent);
563 d_drop(dentry);
564 hmdfs_put_lower_path(&lower_path);
565
566 path_err:
567 if (error)
568 hmdfs_clear_drop_flag(dentry->d_parent);
569 return error;
570 }
571
hmdfs_unlink_local(struct inode * dir,struct dentry * dentry)572 int hmdfs_unlink_local(struct inode *dir, struct dentry *dentry)
573 {
574 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON)
575 return -EACCES;
576
577 return hmdfs_unlink_local_dentry(dir, dentry);
578 }
579
hmdfs_rename_local_dentry(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)580 int hmdfs_rename_local_dentry(struct inode *old_dir, struct dentry *old_dentry,
581 struct inode *new_dir, struct dentry *new_dentry,
582 unsigned int flags)
583 {
584 struct path lower_old_path;
585 struct path lower_new_path;
586 struct dentry *lower_old_dentry = NULL;
587 struct dentry *lower_new_dentry = NULL;
588 struct dentry *lower_old_dir_dentry = NULL;
589 struct dentry *lower_new_dir_dentry = NULL;
590 struct dentry *trap = NULL;
591 int rc = 0;
592 kuid_t old_dir_uid, new_dir_uid;
593
594 if (flags)
595 return -EINVAL;
596
597 hmdfs_get_lower_path(old_dentry, &lower_old_path);
598 lower_old_dentry = lower_old_path.dentry;
599 if (!lower_old_dentry) {
600 hmdfs_err("lower_old_dentry as NULL");
601 rc = -EACCES;
602 goto out_put_old_path;
603 }
604
605 hmdfs_get_lower_path(new_dentry, &lower_new_path);
606 lower_new_dentry = lower_new_path.dentry;
607 if (!lower_new_dentry) {
608 hmdfs_err("lower_new_dentry as NULL");
609 rc = -EACCES;
610 goto out_put_new_path;
611 }
612
613 lower_old_dir_dentry = dget_parent(lower_old_dentry);
614 lower_new_dir_dentry = dget_parent(lower_new_dentry);
615 trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
616 old_dir_uid = hmdfs_override_inode_uid(d_inode(lower_old_dir_dentry));
617 new_dir_uid = hmdfs_override_inode_uid(d_inode(lower_new_dir_dentry));
618
619 /* source should not be ancestor of target */
620 if (trap == lower_old_dentry) {
621 rc = -EINVAL;
622 goto out_lock;
623 }
624 /* target should not be ancestor of source */
625 if (trap == lower_new_dentry) {
626 rc = -ENOTEMPTY;
627 goto out_lock;
628 }
629
630 rc = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry,
631 d_inode(lower_new_dir_dentry), lower_new_dentry, NULL,
632 flags);
633 out_lock:
634 dget(old_dentry);
635
636 hmdfs_revert_inode_uid(d_inode(lower_old_dir_dentry), old_dir_uid);
637 hmdfs_revert_inode_uid(d_inode(lower_new_dir_dentry), new_dir_uid);
638
639 unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
640 if (rc == 0) {
641 hmdfs_drop_remote_cache_dents(old_dentry->d_parent);
642 if (old_dentry->d_parent != new_dentry->d_parent)
643 hmdfs_drop_remote_cache_dents(new_dentry->d_parent);
644 } else {
645 hmdfs_clear_drop_flag(old_dentry->d_parent);
646 if (old_dentry->d_parent != new_dentry->d_parent)
647 hmdfs_clear_drop_flag(old_dentry->d_parent);
648 d_drop(new_dentry);
649 }
650
651 dput(old_dentry);
652 dput(lower_old_dir_dentry);
653 dput(lower_new_dir_dentry);
654
655 out_put_new_path:
656 hmdfs_put_lower_path(&lower_new_path);
657 out_put_old_path:
658 hmdfs_put_lower_path(&lower_old_path);
659 return rc;
660 }
661
hmdfs_rename_local(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)662 int hmdfs_rename_local(struct inode *old_dir, struct dentry *old_dentry,
663 struct inode *new_dir, struct dentry *new_dentry,
664 unsigned int flags)
665 {
666 int err = 0;
667 int ret = 0;
668
669 trace_hmdfs_rename_local(old_dir, old_dentry, new_dir, new_dentry,
670 flags);
671 if (hmdfs_file_type(old_dentry->d_name.name) != HMDFS_TYPE_COMMON ||
672 hmdfs_file_type(new_dentry->d_name.name) != HMDFS_TYPE_COMMON) {
673 err = -EACCES;
674 goto rename_out;
675 }
676
677 if (S_ISREG(old_dentry->d_inode->i_mode)) {
678 err = hmdfs_rename_local_dentry(old_dir, old_dentry, new_dir,
679 new_dentry, flags);
680 } else if (S_ISDIR(old_dentry->d_inode->i_mode)) {
681 ret = hmdfs_rename_local_dentry(old_dir, old_dentry, new_dir,
682 new_dentry, flags);
683 if (ret != 0) {
684 err = ret;
685 goto rename_out;
686 }
687 }
688
689 if (!err)
690 d_invalidate(old_dentry);
691
692 rename_out:
693 return err;
694 }
695
hmdfs_setattr_local(struct dentry * dentry,struct iattr * ia)696 static int hmdfs_setattr_local(struct dentry *dentry, struct iattr *ia)
697 {
698 struct inode *inode = d_inode(dentry);
699 struct inode *lower_inode = hmdfs_i(inode)->lower_inode;
700 struct path lower_path;
701 struct dentry *lower_dentry = NULL;
702 struct iattr lower_ia;
703 unsigned int ia_valid = ia->ia_valid;
704 int err = 0;
705 kuid_t tmp_uid;
706
707 hmdfs_get_lower_path(dentry, &lower_path);
708 lower_dentry = lower_path.dentry;
709 memcpy(&lower_ia, ia, sizeof(lower_ia));
710 if (ia_valid & ATTR_FILE)
711 lower_ia.ia_file = hmdfs_f(ia->ia_file)->lower_file;
712 lower_ia.ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE);
713 if (ia_valid & ATTR_SIZE) {
714 err = inode_newsize_ok(inode, ia->ia_size);
715 if (err)
716 goto out;
717 truncate_setsize(inode, ia->ia_size);
718 }
719 inode_lock(lower_inode);
720 tmp_uid = hmdfs_override_inode_uid(lower_inode);
721
722 err = notify_change(lower_dentry, &lower_ia, NULL);
723 i_size_write(inode, i_size_read(lower_inode));
724 inode->i_atime = lower_inode->i_atime;
725 inode->i_mtime = lower_inode->i_mtime;
726 inode->i_ctime = lower_inode->i_ctime;
727 err = update_inode_to_dentry(dentry, inode);
728 hmdfs_revert_inode_uid(lower_inode, tmp_uid);
729
730 inode_unlock(lower_inode);
731 out:
732 hmdfs_put_lower_path(&lower_path);
733 return err;
734 }
735
hmdfs_getattr_local(const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)736 static int hmdfs_getattr_local(const struct path *path, struct kstat *stat,
737 u32 request_mask, unsigned int flags)
738 {
739 struct path lower_path;
740 int ret;
741
742 hmdfs_get_lower_path(path->dentry, &lower_path);
743 ret = vfs_getattr(&lower_path, stat, request_mask, flags);
744 stat->ino = d_inode(path->dentry)->i_ino;
745 stat->uid = d_inode(path->dentry)->i_uid;
746 stat->gid = d_inode(path->dentry)->i_gid;
747 hmdfs_put_lower_path(&lower_path);
748
749 return ret;
750 }
751
hmdfs_permission(struct inode * inode,int mask)752 int hmdfs_permission(struct inode *inode, int mask)
753 {
754 #ifdef CONFIG_HMDFS_FS_PERMISSION
755 unsigned int mode = inode->i_mode;
756 kuid_t cur_uid = current_fsuid();
757
758 if (uid_eq(cur_uid, ROOT_UID) || uid_eq(cur_uid, SYSTEM_UID))
759 return 0;
760
761 if (uid_eq(cur_uid, inode->i_uid)) {
762 mode >>= 6;
763 } else if (in_group_p(inode->i_gid)) {
764 mode >>= 3;
765 }
766
767 if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
768 return 0;
769
770 trace_hmdfs_permission(inode->i_ino);
771 return -EACCES;
772 #else
773
774 return 0;
775 #endif
776 }
777
hmdfs_local_listxattr(struct dentry * dentry,char * list,size_t size)778 static ssize_t hmdfs_local_listxattr(struct dentry *dentry, char *list,
779 size_t size)
780 {
781 struct path lower_path;
782 ssize_t res = 0;
783 size_t r_size = size;
784
785 if (!hmdfs_support_xattr(dentry))
786 return -EOPNOTSUPP;
787
788 if (size > HMDFS_LISTXATTR_SIZE_MAX)
789 r_size = HMDFS_LISTXATTR_SIZE_MAX;
790
791 hmdfs_get_lower_path(dentry, &lower_path);
792 res = vfs_listxattr(lower_path.dentry, list, r_size);
793 hmdfs_put_lower_path(&lower_path);
794
795 if (res == -ERANGE && r_size != size) {
796 hmdfs_info("no support listxattr size over than %d",
797 HMDFS_LISTXATTR_SIZE_MAX);
798 res = -E2BIG;
799 }
800
801 return res;
802 }
803
hmdfs_get_path_from_share_table(struct hmdfs_sb_info * sbi,struct dentry * cur_dentry,struct path * src_path)804 int hmdfs_get_path_from_share_table(struct hmdfs_sb_info *sbi,
805 struct dentry *cur_dentry, struct path *src_path)
806 {
807 struct hmdfs_share_item *item;
808 const char *path_name;
809 struct qstr relative_path;
810 int err = 0;
811
812 path_name = hmdfs_get_dentry_relative_path(cur_dentry);
813 if (unlikely(!path_name)) {
814 err = -ENOMEM;
815 goto err_out;
816 }
817 relative_path.name = path_name;
818 relative_path.len = strlen(path_name);
819
820 spin_lock(&sbi->share_table.item_list_lock);
821 item = hmdfs_lookup_share_item(&sbi->share_table, &relative_path);
822 if (!item) {
823 spin_unlock(&sbi->share_table.item_list_lock);
824 err = -ENOENT;
825 goto err_out;
826 }
827 *src_path = item->file->f_path;
828 path_get(src_path);
829
830 kfree(path_name);
831 spin_unlock(&sbi->share_table.item_list_lock);
832 err_out:
833 return err;
834 }
835
hmdfs_lookup_share(struct inode * parent_inode,struct dentry * child_dentry,unsigned int flags)836 struct dentry *hmdfs_lookup_share(struct inode *parent_inode,
837 struct dentry *child_dentry, unsigned int flags)
838 {
839 const struct qstr *d_name = &child_dentry->d_name;
840 int err = 0;
841 struct dentry *ret = NULL;
842 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
843 struct path src_path;
844 struct inode *child_inode = NULL;
845
846 trace_hmdfs_lookup_share(parent_inode, child_dentry, flags);
847 if (d_name->len > NAME_MAX) {
848 ret = ERR_PTR(-ENAMETOOLONG);
849 goto err_out;
850 }
851
852 err = init_hmdfs_dentry_info(sbi, child_dentry, HMDFS_LAYER_OTHER_LOCAL);
853 if (err) {
854 ret = ERR_PTR(err);
855 goto err_out;
856 }
857
858 err = hmdfs_get_path_from_share_table(sbi, child_dentry, &src_path);
859 if (err) {
860 ret = ERR_PTR(err);
861 goto err_out;
862 }
863
864 hmdfs_set_lower_path(child_dentry, &src_path);
865 child_inode = fill_inode_local(parent_inode->i_sb,
866 d_inode(src_path.dentry), d_name->name);
867
868 set_sharefile_flag(hmdfs_d(child_dentry));
869
870 if (IS_ERR(child_inode)) {
871 err = PTR_ERR(child_inode);
872 ret = ERR_PTR(err);
873 hmdfs_put_reset_lower_path(child_dentry);
874 goto err_out;
875 }
876 ret = d_splice_alias(child_inode, child_dentry);
877 if (IS_ERR(ret)) {
878 err = PTR_ERR(ret);
879 hmdfs_put_reset_lower_path(child_dentry);
880 goto err_out;
881 }
882
883 check_and_fixup_ownership(parent_inode, child_inode);
884
885 err_out:
886 if (!err)
887 hmdfs_set_time(child_dentry, jiffies);
888 trace_hmdfs_lookup_share_end(parent_inode, child_dentry, err);
889 return ret;
890 }
891
892 const struct inode_operations hmdfs_dir_inode_ops_local = {
893 .lookup = hmdfs_lookup_local,
894 .mkdir = hmdfs_mkdir_local,
895 .create = hmdfs_create_local,
896 .rmdir = hmdfs_rmdir_local,
897 .unlink = hmdfs_unlink_local,
898 .rename = hmdfs_rename_local,
899 .permission = hmdfs_permission,
900 .setattr = hmdfs_setattr_local,
901 .getattr = hmdfs_getattr_local,
902 };
903
904 const struct inode_operations hmdfs_dir_inode_ops_share = {
905 .lookup = hmdfs_lookup_share,
906 .permission = hmdfs_permission,
907 };
908
909 const struct inode_operations hmdfs_file_iops_local = {
910 .setattr = hmdfs_setattr_local,
911 .getattr = hmdfs_getattr_local,
912 .permission = hmdfs_permission,
913 .listxattr = hmdfs_local_listxattr,
914 };
915