1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * fs/hmdfs/inode_merge.c
4 *
5 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
6 */
7
8 #include "hmdfs_merge_view.h"
9 #include <linux/atomic.h>
10 #include <linux/fs.h>
11 #include <linux/fs_stack.h>
12 #include <linux/kernel.h>
13 #include <linux/list.h>
14 #include <linux/mount.h>
15 #include <linux/namei.h>
16 #include <linux/rwsem.h>
17 #include <linux/slab.h>
18 #include <linux/types.h>
19 #include "authority/authentication.h"
20 #include "hmdfs_trace.h"
21
22 struct kmem_cache *hmdfs_dentry_merge_cachep;
23
hmdfs_get_fst_lo_d(struct dentry * dentry)24 struct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry)
25 {
26 struct hmdfs_dentry_info_merge *dim = hmdfs_dm(dentry);
27 struct hmdfs_dentry_comrade *comrade = NULL;
28 struct dentry *d = NULL;
29
30 mutex_lock(&dim->comrade_list_lock);
31 comrade = list_first_entry_or_null(&dim->comrade_list,
32 struct hmdfs_dentry_comrade, list);
33 if (comrade)
34 d = dget(comrade->lo_d);
35 mutex_unlock(&dim->comrade_list_lock);
36 return d;
37 }
38
hmdfs_get_lo_d(struct dentry * dentry,int dev_id)39 struct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id)
40 {
41 struct hmdfs_dentry_info_merge *dim = hmdfs_dm(dentry);
42 struct hmdfs_dentry_comrade *comrade = NULL;
43 struct dentry *d = NULL;
44
45 mutex_lock(&dim->comrade_list_lock);
46 list_for_each_entry(comrade, &dim->comrade_list, list) {
47 if (comrade->dev_id == dev_id) {
48 d = dget(comrade->lo_d);
49 break;
50 }
51 }
52 mutex_unlock(&dim->comrade_list_lock);
53 return d;
54 }
55
update_inode_attr(struct inode * inode,struct dentry * child_dentry)56 static void update_inode_attr(struct inode *inode, struct dentry *child_dentry)
57 {
58 struct inode *li = NULL;
59 struct hmdfs_dentry_info_merge *cdi = hmdfs_dm(child_dentry);
60 struct hmdfs_dentry_comrade *comrade = NULL;
61 struct hmdfs_dentry_comrade *fst_comrade = NULL;
62
63 mutex_lock(&cdi->comrade_list_lock);
64 fst_comrade = list_first_entry(&cdi->comrade_list,
65 struct hmdfs_dentry_comrade, list);
66 list_for_each_entry(comrade, &cdi->comrade_list, list) {
67 li = d_inode(comrade->lo_d);
68 if (!li)
69 continue;
70
71 if (comrade == fst_comrade) {
72 inode->i_atime = li->i_atime;
73 inode->i_ctime = li->i_ctime;
74 inode->i_mtime = li->i_mtime;
75 inode->i_size = li->i_size;
76 continue;
77 }
78
79 if (hmdfs_time_compare(&inode->i_mtime, &li->i_mtime) < 0)
80 inode->i_mtime = li->i_mtime;
81 }
82 mutex_unlock(&cdi->comrade_list_lock);
83 }
84
get_num_comrades(struct dentry * dentry)85 static int get_num_comrades(struct dentry *dentry)
86 {
87 struct list_head *pos;
88 struct hmdfs_dentry_info_merge *dim = hmdfs_dm(dentry);
89 int count = 0;
90
91 mutex_lock(&dim->comrade_list_lock);
92 list_for_each(pos, &dim->comrade_list)
93 count++;
94 mutex_unlock(&dim->comrade_list_lock);
95 return count;
96 }
97
fill_inode_merge(struct super_block * sb,struct inode * parent_inode,struct dentry * child_dentry,struct dentry * lo_d_dentry)98 static struct inode *fill_inode_merge(struct super_block *sb,
99 struct inode *parent_inode,
100 struct dentry *child_dentry,
101 struct dentry *lo_d_dentry)
102 {
103 int ret = 0;
104 struct dentry *fst_lo_d = NULL;
105 struct hmdfs_inode_info *info = NULL;
106 struct inode *inode = NULL;
107 umode_t mode;
108
109 if (lo_d_dentry) {
110 fst_lo_d = lo_d_dentry;
111 dget(fst_lo_d);
112 } else {
113 fst_lo_d = hmdfs_get_fst_lo_d(child_dentry);
114 }
115 if (!fst_lo_d) {
116 inode = ERR_PTR(-EINVAL);
117 goto out;
118 }
119 if (hmdfs_i(parent_inode)->inode_type == HMDFS_LAYER_ZERO)
120 inode = hmdfs_iget_locked_root(sb, HMDFS_ROOT_MERGE, NULL,
121 NULL);
122 else
123 inode = hmdfs_iget5_locked_merge(sb, fst_lo_d);
124 if (!inode) {
125 hmdfs_err("iget5_locked get inode NULL");
126 inode = ERR_PTR(-ENOMEM);
127 goto out;
128 }
129 if (!(inode->i_state & I_NEW))
130 goto out;
131 info = hmdfs_i(inode);
132 if (hmdfs_i(parent_inode)->inode_type == HMDFS_LAYER_ZERO)
133 info->inode_type = HMDFS_LAYER_FIRST_MERGE;
134 else
135 info->inode_type = HMDFS_LAYER_OTHER_MERGE;
136
137 inode->i_uid = KUIDT_INIT((uid_t)1000);
138 inode->i_gid = KGIDT_INIT((gid_t)1000);
139
140 update_inode_attr(inode, child_dentry);
141 mode = d_inode(fst_lo_d)->i_mode;
142
143 if (S_ISREG(mode)) {
144 inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
145 inode->i_op = &hmdfs_file_iops_merge;
146 inode->i_fop = &hmdfs_file_fops_merge;
147 set_nlink(inode, 1);
148 } else if (S_ISDIR(mode)) {
149 inode->i_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IXOTH;
150 inode->i_op = &hmdfs_dir_iops_merge;
151 inode->i_fop = &hmdfs_dir_fops_merge;
152 set_nlink(inode, get_num_comrades(child_dentry) + 2);
153 } else {
154 ret = -EIO;
155 goto bad_inode;
156 }
157
158 unlock_new_inode(inode);
159 out:
160 dput(fst_lo_d);
161 return inode;
162 bad_inode:
163 iget_failed(inode);
164 return ERR_PTR(ret);
165 }
166
alloc_comrade(struct dentry * lo_d,int dev_id)167 struct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id)
168 {
169 struct hmdfs_dentry_comrade *comrade = NULL;
170
171 // 文件只有一个 comrade,考虑 {comrade, list + list lock}
172 comrade = kzalloc(sizeof(*comrade), GFP_KERNEL);
173 if (unlikely(!comrade))
174 return ERR_PTR(-ENOMEM);
175
176 comrade->lo_d = lo_d;
177 comrade->dev_id = dev_id;
178 dget(lo_d);
179 return comrade;
180 }
181
link_comrade(struct list_head * onstack_comrades_head,struct hmdfs_dentry_comrade * comrade)182 void link_comrade(struct list_head *onstack_comrades_head,
183 struct hmdfs_dentry_comrade *comrade)
184 {
185 struct hmdfs_dentry_comrade *c = NULL;
186
187 list_for_each_entry(c, onstack_comrades_head, list) {
188 if (likely(c->dev_id != comrade->dev_id))
189 continue;
190 hmdfs_err("Redundant comrade of device %llu", c->dev_id);
191 dput(comrade->lo_d);
192 kfree(comrade);
193 WARN_ON(1);
194 return;
195 }
196
197 if (comrade_is_local(comrade))
198 list_add(&comrade->list, onstack_comrades_head);
199 else
200 list_add_tail(&comrade->list, onstack_comrades_head);
201 }
202
203 /**
204 * assign_comrades_unlocked - assign a child dentry with comrades
205 *
206 * We tend to setup a local list of all the comrades we found and place the
207 * list onto the dentry_info to achieve atomicity.
208 */
assign_comrades_unlocked(struct dentry * child_dentry,struct list_head * onstack_comrades_head)209 static void assign_comrades_unlocked(struct dentry *child_dentry,
210 struct list_head *onstack_comrades_head)
211 {
212 struct hmdfs_dentry_info_merge *cdi = hmdfs_dm(child_dentry);
213
214 mutex_lock(&cdi->comrade_list_lock);
215 WARN_ON(!list_empty(&cdi->comrade_list));
216 list_splice_init(onstack_comrades_head, &cdi->comrade_list);
217 mutex_unlock(&cdi->comrade_list_lock);
218 }
219
lookup_comrade(struct path lower_path,const char * d_name,int dev_id,unsigned int flags)220 static struct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path,
221 const char *d_name,
222 int dev_id,
223 unsigned int flags)
224 {
225 struct path path;
226 struct hmdfs_dentry_comrade *comrade = NULL;
227 int err;
228
229 err = vfs_path_lookup(lower_path.dentry, lower_path.mnt, d_name, flags,
230 &path);
231 if (err)
232 return ERR_PTR(err);
233
234 comrade = alloc_comrade(path.dentry, dev_id);
235 path_put(&path);
236 return comrade;
237 }
238
239 /**
240 * conf_name_trans_nop - do nothing but copy
241 *
242 * WARNING: always check before translation
243 */
conf_name_trans_nop(struct dentry * d)244 static char *conf_name_trans_nop(struct dentry *d)
245 {
246 return kstrndup(d->d_name.name, d->d_name.len, GFP_KERNEL);
247 }
248
249 /**
250 * conf_name_trans_dir - conflicted name translation for directory
251 *
252 * WARNING: always check before translation
253 */
conf_name_trans_dir(struct dentry * d)254 static char *conf_name_trans_dir(struct dentry *d)
255 {
256 int len = d->d_name.len - strlen(CONFLICTING_DIR_SUFFIX);
257
258 return kstrndup(d->d_name.name, len, GFP_KERNEL);
259 }
260
261 /**
262 * conf_name_trans_reg - conflicted name translation for regular file
263 *
264 * WARNING: always check before translation
265 */
conf_name_trans_reg(struct dentry * d,int * dev_id)266 static char *conf_name_trans_reg(struct dentry *d, int *dev_id)
267 {
268 int dot_pos, start_cpy_pos, num_len, i;
269 int len = d->d_name.len;
270 char *name = kstrndup(d->d_name.name, d->d_name.len, GFP_KERNEL);
271
272 if (unlikely(!name))
273 return NULL;
274
275 // find the last dot if possible
276 for (dot_pos = len - 1; dot_pos >= 0; dot_pos--) {
277 if (name[dot_pos] == '.')
278 break;
279 }
280 if (dot_pos == -1)
281 dot_pos = len;
282
283 // retrieve the conf sn (i.e. dev_id)
284 num_len = 0;
285 for (i = dot_pos - 1; i >= 0; i--) {
286 if (name[i] >= '0' && name[i] <= '9')
287 num_len++;
288 else
289 break;
290 }
291
292 *dev_id = 0;
293 for (i = 0; i < num_len; i++)
294 *dev_id = *dev_id * 10 + name[dot_pos - num_len + i] - '0';
295
296 // move the file suffix( '\0' included) right after the file name
297 start_cpy_pos =
298 dot_pos - num_len - strlen(CONFLICTING_FILE_CONST_SUFFIX);
299 memmove(name + start_cpy_pos, name + dot_pos, len - dot_pos + 1);
300 return name;
301 }
302
check_filename(const char * name,int len)303 int check_filename(const char *name, int len)
304 {
305 int cmp_res = 0;
306
307 if (len >= strlen(CONFLICTING_DIR_SUFFIX)) {
308 cmp_res = strncmp(name + len - strlen(CONFLICTING_DIR_SUFFIX),
309 CONFLICTING_DIR_SUFFIX,
310 strlen(CONFLICTING_DIR_SUFFIX));
311 if (cmp_res == 0)
312 return DT_DIR;
313 }
314
315 if (len >= strlen(CONFLICTING_FILE_CONST_SUFFIX)) {
316 int dot_pos, start_cmp_pos, num_len, i;
317
318 for (dot_pos = len - 1; dot_pos >= 0; dot_pos--) {
319 if (name[dot_pos] == '.')
320 break;
321 }
322 if (dot_pos == -1)
323 dot_pos = len;
324
325 num_len = 0;
326 for (i = dot_pos - 1; i >= 0; i--) {
327 if (name[i] >= '0' && name[i] <= '9')
328 num_len++;
329 else
330 break;
331 }
332
333 start_cmp_pos = dot_pos - num_len -
334 strlen(CONFLICTING_FILE_CONST_SUFFIX);
335 cmp_res = strncmp(name + start_cmp_pos,
336 CONFLICTING_FILE_CONST_SUFFIX,
337 strlen(CONFLICTING_FILE_CONST_SUFFIX));
338 if (cmp_res == 0)
339 return DT_REG;
340 }
341
342 return 0;
343 }
344
lookup_merge_normal(struct dentry * child_dentry,unsigned int flags)345 static int lookup_merge_normal(struct dentry *child_dentry, unsigned int flags)
346 {
347 struct dentry *parent_dentry = dget_parent(child_dentry);
348 struct hmdfs_dentry_info_merge *pdi = hmdfs_dm(parent_dentry);
349 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
350 struct hmdfs_dentry_comrade *comrade, *cc;
351 struct path lo_p, path;
352 LIST_HEAD(head);
353 int ret = -ENOENT;
354 int dev_id = -1;
355 int ftype;
356 char *lo_name;
357 umode_t mode;
358
359 ftype = check_filename(child_dentry->d_name.name,
360 child_dentry->d_name.len);
361 if (ftype == DT_REG)
362 lo_name = conf_name_trans_reg(child_dentry, &dev_id);
363 else if (ftype == DT_DIR)
364 lo_name = conf_name_trans_dir(child_dentry);
365 else
366 lo_name = conf_name_trans_nop(child_dentry);
367 if (unlikely(!lo_name)) {
368 ret = -ENOMEM;
369 goto out;
370 }
371
372 ret = hmdfs_get_path_in_sb(child_dentry->d_sb, sbi->real_dst,
373 LOOKUP_DIRECTORY, &path);
374 if (ret) {
375 if (ret == -ENOENT)
376 ret = -EINVAL;
377 goto free;
378 }
379 lo_p.mnt = path.mnt;
380
381 ret = -ENOENT;
382 mutex_lock(&pdi->comrade_list_lock);
383 list_for_each_entry(cc, &pdi->comrade_list, list) {
384 if (ftype == DT_REG && cc->dev_id != dev_id)
385 continue;
386
387 lo_p.dentry = cc->lo_d;
388 comrade = lookup_comrade(lo_p, lo_name, cc->dev_id, flags);
389 if (IS_ERR(comrade)) {
390 ret = ret ? PTR_ERR(comrade) : 0;
391 continue;
392 }
393
394 mode = hmdfs_cm(comrade);
395 if ((ftype == DT_DIR && !S_ISDIR(mode)) ||
396 (ftype == DT_REG && S_ISDIR(mode))) {
397 destroy_comrade(comrade);
398 ret = ret ? PTR_ERR(comrade) : 0;
399 continue;
400 }
401
402 ret = 0;
403 link_comrade(&head, comrade);
404
405 if (!S_ISDIR(mode))
406 break;
407 }
408 mutex_unlock(&pdi->comrade_list_lock);
409
410 assign_comrades_unlocked(child_dentry, &head);
411 path_put(&path);
412 free:
413 kfree(lo_name);
414 out:
415 dput(parent_dentry);
416 return ret;
417 }
418
419 /**
420 * do_lookup_merge_root - lookup the root of the merge view(root/merge_view)
421 *
422 * It's common for a network filesystem to incur various of faults, so we
423 * intent to show mercy for faults here, except faults reported by the local.
424 */
do_lookup_merge_root(struct path path_dev,struct dentry * child_dentry,unsigned int flags)425 static int do_lookup_merge_root(struct path path_dev,
426 struct dentry *child_dentry, unsigned int flags)
427 {
428 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
429 struct hmdfs_dentry_comrade *comrade;
430 const int buf_len =
431 max((int)HMDFS_CID_SIZE + 1, (int)sizeof(DEVICE_VIEW_LOCAL));
432 char *buf = kzalloc(buf_len, GFP_KERNEL);
433 struct hmdfs_peer *peer;
434 LIST_HEAD(head);
435 int ret;
436
437 if (!buf)
438 return -ENOMEM;
439
440 // lookup real_dst/device_view/local
441 memcpy(buf, DEVICE_VIEW_LOCAL, sizeof(DEVICE_VIEW_LOCAL));
442 comrade = lookup_comrade(path_dev, buf, HMDFS_DEVID_LOCAL, flags);
443 if (IS_ERR(comrade)) {
444 ret = PTR_ERR(comrade);
445 goto out;
446 }
447 link_comrade(&head, comrade);
448
449 // lookup real_dst/device_view/cidxx
450 mutex_lock(&sbi->connections.node_lock);
451 list_for_each_entry(peer, &sbi->connections.node_list, list) {
452 mutex_unlock(&sbi->connections.node_lock);
453 memcpy(buf, peer->cid, HMDFS_CID_SIZE);
454 comrade = lookup_comrade(path_dev, buf, peer->device_id, flags);
455 if (IS_ERR(comrade))
456 continue;
457
458 link_comrade(&head, comrade);
459 mutex_lock(&sbi->connections.node_lock);
460 }
461 mutex_unlock(&sbi->connections.node_lock);
462
463 assign_comrades_unlocked(child_dentry, &head);
464 ret = 0;
465
466 out:
467 kfree(buf);
468 return ret;
469 }
470
471 // mkdir -p
lock_root_inode_shared(struct inode * root,bool * locked,bool * down)472 static void lock_root_inode_shared(struct inode *root, bool *locked, bool *down)
473 {
474 struct rw_semaphore *sem = &root->i_rwsem;
475 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
476 #define RWSEM_READER_OWNED (1UL << 0)
477 #define RWSEM_RD_NONSPINNABLE (1UL << 1)
478 #define RWSEM_WR_NONSPINNABLE (1UL << 2)
479 #define RWSEM_NONSPINNABLE (RWSEM_RD_NONSPINNABLE | RWSEM_WR_NONSPINNABLE)
480 #define RWSEM_OWNER_FLAGS_MASK (RWSEM_READER_OWNED | RWSEM_NONSPINNABLE)
481 struct task_struct *sem_owner =
482 (struct task_struct *)(atomic_long_read(&sem->owner) &
483 ~RWSEM_OWNER_FLAGS_MASK);
484 #else
485 struct task_struct *sem_owner = sem->owner;
486 #endif
487
488 *locked = false;
489 *down = false;
490
491 if (sem_owner != current)
492 return;
493
494 // It's us that takes the wsem
495 if (!inode_trylock_shared(root)) {
496 downgrade_write(sem);
497 *down = true;
498 }
499 *locked = true;
500 }
501
restore_root_inode_sem(struct inode * root,bool locked,bool down)502 static void restore_root_inode_sem(struct inode *root, bool locked, bool down)
503 {
504 if (!locked)
505 return;
506
507 inode_unlock_shared(root);
508 if (down)
509 inode_lock(root);
510 }
511
lookup_merge_root(struct inode * root_inode,struct dentry * child_dentry,unsigned int flags)512 static int lookup_merge_root(struct inode *root_inode,
513 struct dentry *child_dentry, unsigned int flags)
514 {
515 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
516 struct path path_dev;
517 int ret = -ENOENT;
518 int buf_len;
519 char *buf = NULL;
520 bool locked, down;
521
522 // consider additional one slash and one '\0'
523 buf_len = strlen(sbi->real_dst) + 1 + sizeof(DEVICE_VIEW_ROOT);
524 if (buf_len > PATH_MAX)
525 return -ENAMETOOLONG;
526
527 buf = kmalloc(buf_len, GFP_KERNEL);
528 if (unlikely(!buf))
529 return -ENOMEM;
530
531 sprintf(buf, "%s/%s", sbi->real_dst, DEVICE_VIEW_ROOT);
532 lock_root_inode_shared(root_inode, &locked, &down);
533 ret = hmdfs_get_path_in_sb(child_dentry->d_sb, buf, LOOKUP_DIRECTORY,
534 &path_dev);
535 if (ret)
536 goto free_buf;
537
538 ret = do_lookup_merge_root(path_dev, child_dentry, flags);
539 path_put(&path_dev);
540
541 free_buf:
542 kfree(buf);
543 restore_root_inode_sem(root_inode, locked, down);
544 return ret;
545 }
546
init_hmdfs_dentry_info_merge(struct hmdfs_sb_info * sbi,struct dentry * dentry)547 int init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi,
548 struct dentry *dentry)
549 {
550 struct hmdfs_dentry_info_merge *info = NULL;
551
552 info = kmem_cache_zalloc(hmdfs_dentry_merge_cachep, GFP_NOFS);
553 if (!info)
554 return -ENOMEM;
555
556 info->ctime = jiffies;
557 INIT_LIST_HEAD(&info->comrade_list);
558 mutex_init(&info->comrade_list_lock);
559 d_set_d_op(dentry, &hmdfs_dops_merge);
560 dentry->d_fsdata = info;
561 return 0;
562 }
563
update_dm(struct dentry * dst,struct dentry * src)564 static void update_dm(struct dentry *dst, struct dentry *src)
565 {
566 struct hmdfs_dentry_info_merge *dmi_dst = hmdfs_dm(dst);
567 struct hmdfs_dentry_info_merge *dmi_src = hmdfs_dm(src);
568 LIST_HEAD(tmp_dst);
569 LIST_HEAD(tmp_src);
570
571 /* Mobilize all the comrades */
572 mutex_lock(&dmi_dst->comrade_list_lock);
573 mutex_lock(&dmi_src->comrade_list_lock);
574 list_splice_init(&dmi_dst->comrade_list, &tmp_dst);
575 list_splice_init(&dmi_src->comrade_list, &tmp_src);
576 list_splice(&tmp_dst, &dmi_src->comrade_list);
577 list_splice(&tmp_src, &dmi_dst->comrade_list);
578 mutex_unlock(&dmi_src->comrade_list_lock);
579 mutex_unlock(&dmi_dst->comrade_list_lock);
580 }
581
582 // do this in a map-reduce manner
hmdfs_lookup_merge(struct inode * parent_inode,struct dentry * child_dentry,unsigned int flags)583 struct dentry *hmdfs_lookup_merge(struct inode *parent_inode,
584 struct dentry *child_dentry,
585 unsigned int flags)
586 {
587 bool create = flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET);
588 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
589 struct hmdfs_inode_info *pii = hmdfs_i(parent_inode);
590 struct inode *child_inode = NULL;
591 struct dentry *ret_dentry = NULL;
592 int err = 0;
593
594 /*
595 * Internal flags like LOOKUP_CREATE should not pass to device view.
596 * LOOKUP_REVAL is needed because dentry cache in hmdfs might be stale
597 * after rename in lower fs. LOOKUP_DIRECTORY is not needed because
598 * merge_view can do the judgement that whether result is directory or
599 * not.
600 */
601 flags = flags & LOOKUP_REVAL;
602
603 child_dentry->d_fsdata = NULL;
604
605 if (child_dentry->d_name.len > NAME_MAX) {
606 err = -ENAMETOOLONG;
607 goto out;
608 }
609
610 err = init_hmdfs_dentry_info_merge(sbi, child_dentry);
611 if (unlikely(err))
612 goto out;
613
614 if (pii->inode_type == HMDFS_LAYER_ZERO)
615 err = lookup_merge_root(parent_inode, child_dentry, flags);
616 else
617 err = lookup_merge_normal(child_dentry, flags);
618
619 if (!err) {
620 struct hmdfs_inode_info *info = NULL;
621
622 child_inode = fill_inode_merge(parent_inode->i_sb, parent_inode,
623 child_dentry, NULL);
624 ret_dentry = d_splice_alias(child_inode, child_dentry);
625 if (IS_ERR(ret_dentry)) {
626 clear_comrades(child_dentry);
627 err = PTR_ERR(ret_dentry);
628 goto out;
629 }
630 if (ret_dentry) {
631 update_dm(ret_dentry, child_dentry);
632 child_dentry = ret_dentry;
633 }
634 info = hmdfs_i(child_inode);
635 if (info->inode_type == HMDFS_LAYER_FIRST_MERGE)
636 hmdfs_root_inode_perm_init(child_inode);
637 else
638 check_and_fixup_ownership_remote(parent_inode,
639 child_dentry);
640
641 goto out;
642 }
643
644 if ((err == -ENOENT) && create)
645 err = 0;
646
647 out:
648 hmdfs_trace_merge(trace_hmdfs_lookup_merge_end, parent_inode,
649 child_dentry, err);
650 return err ? ERR_PTR(err) : ret_dentry;
651 }
652
hmdfs_getattr_merge(const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)653 static int hmdfs_getattr_merge(const struct path *path, struct kstat *stat,
654 u32 request_mask, unsigned int flags)
655 {
656 int ret;
657 struct path lower_path = {
658 .dentry = hmdfs_get_fst_lo_d(path->dentry),
659 .mnt = path->mnt,
660 };
661
662 if (unlikely(!lower_path.dentry)) {
663 hmdfs_err("Fatal! No comrades");
664 ret = -EINVAL;
665 goto out;
666 }
667
668 ret = vfs_getattr(&lower_path, stat, request_mask, flags);
669 out:
670 dput(lower_path.dentry);
671 return ret;
672 }
673
hmdfs_setattr_merge(struct dentry * dentry,struct iattr * ia)674 static int hmdfs_setattr_merge(struct dentry *dentry, struct iattr *ia)
675 {
676 struct inode *inode = d_inode(dentry);
677 struct dentry *lower_dentry = hmdfs_get_fst_lo_d(dentry);
678 struct inode *lower_inode = NULL;
679 struct iattr lower_ia;
680 unsigned int ia_valid = ia->ia_valid;
681 int err = 0;
682 kuid_t tmp_uid;
683
684 if (!lower_dentry) {
685 WARN_ON(1);
686 err = -EINVAL;
687 goto out;
688 }
689
690 lower_inode = d_inode(lower_dentry);
691 memcpy(&lower_ia, ia, sizeof(lower_ia));
692 if (ia_valid & ATTR_FILE)
693 lower_ia.ia_file = hmdfs_f(ia->ia_file)->lower_file;
694 lower_ia.ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE);
695
696 inode_lock(lower_inode);
697 tmp_uid = hmdfs_override_inode_uid(lower_inode);
698
699 err = notify_change(lower_dentry, &lower_ia, NULL);
700 i_size_write(inode, i_size_read(lower_inode));
701 inode->i_atime = lower_inode->i_atime;
702 inode->i_mtime = lower_inode->i_mtime;
703 inode->i_ctime = lower_inode->i_ctime;
704 hmdfs_revert_inode_uid(lower_inode, tmp_uid);
705
706 inode_unlock(lower_inode);
707
708 out:
709 dput(lower_dentry);
710 return err;
711 }
712
713 const struct inode_operations hmdfs_file_iops_merge = {
714 .getattr = hmdfs_getattr_merge,
715 .setattr = hmdfs_setattr_merge,
716 .permission = hmdfs_permission,
717 };
718
do_mkdir_merge(struct inode * parent_inode,struct dentry * child_dentry,umode_t mode,struct inode * lo_i_parent,struct dentry * lo_d_child)719 int do_mkdir_merge(struct inode *parent_inode, struct dentry *child_dentry,
720 umode_t mode, struct inode *lo_i_parent,
721 struct dentry *lo_d_child)
722 {
723 int ret = 0;
724 struct super_block *sb = parent_inode->i_sb;
725 struct inode *child_inode = NULL;
726
727 ret = vfs_mkdir(lo_i_parent, lo_d_child, mode);
728 if (ret)
729 goto out;
730
731 child_inode =
732 fill_inode_merge(sb, parent_inode, child_dentry, lo_d_child);
733 if (IS_ERR(child_inode)) {
734 ret = PTR_ERR(child_inode);
735 goto out;
736 }
737
738 d_add(child_dentry, child_inode);
739 /* nlink should be increased with the joining of children */
740 set_nlink(parent_inode, 2);
741 out:
742 return ret;
743 }
744
do_create_merge(struct inode * parent_inode,struct dentry * child_dentry,umode_t mode,bool want_excl,struct inode * lo_i_parent,struct dentry * lo_d_child)745 int do_create_merge(struct inode *parent_inode, struct dentry *child_dentry,
746 umode_t mode, bool want_excl, struct inode *lo_i_parent,
747 struct dentry *lo_d_child)
748 {
749 int ret = 0;
750 struct super_block *sb = parent_inode->i_sb;
751 struct inode *child_inode = NULL;
752
753 ret = vfs_create(lo_i_parent, lo_d_child, mode, want_excl);
754 if (ret)
755 goto out;
756
757 child_inode =
758 fill_inode_merge(sb, parent_inode, child_dentry, lo_d_child);
759 if (IS_ERR(child_inode)) {
760 ret = PTR_ERR(child_inode);
761 goto out;
762 }
763
764 d_add(child_dentry, child_inode);
765 /* nlink should be increased with the joining of children */
766 set_nlink(parent_inode, 2);
767 out:
768 return ret;
769 }
770
hmdfs_do_ops_merge(struct inode * i_parent,struct dentry * d_child,struct dentry * lo_d_child,struct path path,struct hmdfs_recursive_para * rec_op_para)771 int hmdfs_do_ops_merge(struct inode *i_parent, struct dentry *d_child,
772 struct dentry *lo_d_child, struct path path,
773 struct hmdfs_recursive_para *rec_op_para)
774 {
775 int ret = 0;
776
777 if (rec_op_para->is_last) {
778 switch (rec_op_para->opcode) {
779 case F_MKDIR_MERGE:
780 ret = do_mkdir_merge(i_parent, d_child,
781 rec_op_para->mode,
782 d_inode(path.dentry), lo_d_child);
783 break;
784 case F_CREATE_MERGE:
785 ret = do_create_merge(i_parent, d_child,
786 rec_op_para->mode,
787 rec_op_para->want_excl,
788 d_inode(path.dentry), lo_d_child);
789 break;
790 default:
791 ret = -EINVAL;
792 break;
793 }
794 } else {
795 ret = vfs_mkdir(d_inode(path.dentry), lo_d_child,
796 rec_op_para->mode);
797 }
798 if (ret)
799 hmdfs_err("vfs_ops failed, ops %d, err = %d",
800 rec_op_para->opcode, ret);
801 return ret;
802 }
803
hmdfs_create_lower_dentry(struct inode * i_parent,struct dentry * d_child,struct dentry * lo_d_parent,bool is_dir,struct hmdfs_recursive_para * rec_op_para)804 int hmdfs_create_lower_dentry(struct inode *i_parent, struct dentry *d_child,
805 struct dentry *lo_d_parent, bool is_dir,
806 struct hmdfs_recursive_para *rec_op_para)
807 {
808 struct hmdfs_sb_info *sbi = i_parent->i_sb->s_fs_info;
809 struct hmdfs_dentry_comrade *new_comrade = NULL;
810 struct dentry *lo_d_child = NULL;
811 char *path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
812 char *absolute_path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
813 char *path_name = NULL;
814 struct path path = { .mnt = NULL, .dentry = NULL };
815 int ret = 0;
816
817 if (unlikely(!path_buf || !absolute_path_buf)) {
818 ret = -ENOMEM;
819 goto out;
820 }
821
822 path_name = dentry_path_raw(lo_d_parent, path_buf, PATH_MAX);
823 if (IS_ERR(path_name)) {
824 ret = PTR_ERR(path_name);
825 goto out;
826 }
827 if ((strlen(sbi->real_dst) + strlen(path_name) +
828 strlen(d_child->d_name.name) + 2) > PATH_MAX) {
829 ret = -ENAMETOOLONG;
830 goto out;
831 }
832
833 sprintf(absolute_path_buf, "%s%s/%s", sbi->real_dst, path_name,
834 d_child->d_name.name);
835
836 if (is_dir)
837 lo_d_child = kern_path_create(AT_FDCWD, absolute_path_buf,
838 &path, LOOKUP_DIRECTORY);
839 else
840 lo_d_child = kern_path_create(AT_FDCWD, absolute_path_buf,
841 &path, 0);
842 if (IS_ERR(lo_d_child)) {
843 ret = PTR_ERR(lo_d_child);
844 goto out;
845 }
846 // to ensure link_comrade after vfs_mkdir succeed
847 ret = hmdfs_do_ops_merge(i_parent, d_child, lo_d_child, path,
848 rec_op_para);
849 if (ret)
850 goto out_put;
851 new_comrade = alloc_comrade(lo_d_child, HMDFS_DEVID_LOCAL);
852 if (IS_ERR(new_comrade)) {
853 ret = PTR_ERR(new_comrade);
854 goto out_put;
855 } else {
856 link_comrade_unlocked(d_child, new_comrade);
857 }
858
859 out_put:
860 done_path_create(&path, lo_d_child);
861 out:
862 kfree(absolute_path_buf);
863 kfree(path_buf);
864 return ret;
865 }
866
create_lo_d_parent_recur(struct dentry * d_parent,struct dentry * d_child,umode_t mode,struct hmdfs_recursive_para * rec_op_para)867 static int create_lo_d_parent_recur(struct dentry *d_parent,
868 struct dentry *d_child, umode_t mode,
869 struct hmdfs_recursive_para *rec_op_para)
870 {
871 struct dentry *lo_d_parent, *d_pparent;
872 int ret = 0;
873
874 lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL);
875 if (!lo_d_parent) {
876 d_pparent = dget_parent(d_parent);
877 ret = create_lo_d_parent_recur(d_pparent, d_parent,
878 d_inode(d_parent)->i_mode,
879 rec_op_para);
880 dput(d_pparent);
881 if (ret)
882 goto out;
883 lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL);
884 if (!lo_d_parent) {
885 ret = -ENOENT;
886 goto out;
887 }
888 }
889 rec_op_para->is_last = false;
890 rec_op_para->mode = mode;
891 ret = hmdfs_create_lower_dentry(d_inode(d_parent), d_child, lo_d_parent,
892 true, rec_op_para);
893 out:
894 dput(lo_d_parent);
895 return ret;
896 }
897
create_lo_d_child(struct inode * i_parent,struct dentry * d_child,bool is_dir,struct hmdfs_recursive_para * rec_op_para)898 int create_lo_d_child(struct inode *i_parent, struct dentry *d_child,
899 bool is_dir, struct hmdfs_recursive_para *rec_op_para)
900 {
901 struct dentry *d_pparent, *lo_d_parent, *lo_d_child;
902 struct dentry *d_parent = dget_parent(d_child);
903 int ret = 0;
904 mode_t d_child_mode = rec_op_para->mode;
905
906 lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL);
907 if (!lo_d_parent) {
908 d_pparent = dget_parent(d_parent);
909 ret = create_lo_d_parent_recur(d_pparent, d_parent,
910 d_inode(d_parent)->i_mode,
911 rec_op_para);
912 dput(d_pparent);
913 if (unlikely(ret)) {
914 lo_d_child = ERR_PTR(ret);
915 goto out;
916 }
917 lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL);
918 if (!lo_d_parent) {
919 lo_d_child = ERR_PTR(-ENOENT);
920 goto out;
921 }
922 }
923 rec_op_para->is_last = true;
924 rec_op_para->mode = d_child_mode;
925 ret = hmdfs_create_lower_dentry(i_parent, d_child, lo_d_parent, is_dir,
926 rec_op_para);
927
928 out:
929 dput(d_parent);
930 dput(lo_d_parent);
931 return ret;
932 }
933
hmdfs_init_recursive_para(struct hmdfs_recursive_para * rec_op_para,int opcode,mode_t mode,bool want_excl,const char * name)934 void hmdfs_init_recursive_para(struct hmdfs_recursive_para *rec_op_para,
935 int opcode, mode_t mode, bool want_excl,
936 const char *name)
937 {
938 rec_op_para->is_last = true;
939 rec_op_para->opcode = opcode;
940 rec_op_para->mode = mode;
941 rec_op_para->want_excl = want_excl;
942 rec_op_para->name = name;
943 }
944
hmdfs_mkdir_merge(struct inode * dir,struct dentry * dentry,umode_t mode)945 int hmdfs_mkdir_merge(struct inode *dir, struct dentry *dentry, umode_t mode)
946 {
947 int ret = 0;
948 struct hmdfs_recursive_para *rec_op_para = NULL;
949
950 // confict_name & file_type is checked by hmdfs_mkdir_local
951 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) {
952 ret = -EACCES;
953 goto out;
954 }
955 rec_op_para = kmalloc(sizeof(*rec_op_para), GFP_KERNEL);
956 if (!rec_op_para) {
957 ret = -ENOMEM;
958 goto out;
959 }
960
961 hmdfs_init_recursive_para(rec_op_para, F_MKDIR_MERGE, mode, false,
962 NULL);
963 ret = create_lo_d_child(dir, dentry, true, rec_op_para);
964 out:
965 hmdfs_trace_merge(trace_hmdfs_mkdir_merge, dir, dentry, ret);
966 if (ret)
967 d_drop(dentry);
968 kfree(rec_op_para);
969 return ret;
970 }
971
hmdfs_create_merge(struct inode * dir,struct dentry * dentry,umode_t mode,bool want_excl)972 int hmdfs_create_merge(struct inode *dir, struct dentry *dentry, umode_t mode,
973 bool want_excl)
974 {
975 struct hmdfs_recursive_para *rec_op_para = NULL;
976 int ret = 0;
977
978 rec_op_para = kmalloc(sizeof(*rec_op_para), GFP_KERNEL);
979 if (!rec_op_para) {
980 ret = -ENOMEM;
981 goto out;
982 }
983 hmdfs_init_recursive_para(rec_op_para, F_CREATE_MERGE, mode, want_excl,
984 NULL);
985 // confict_name & file_type is checked by hmdfs_create_local
986 ret = create_lo_d_child(dir, dentry, false, rec_op_para);
987 out:
988 hmdfs_trace_merge(trace_hmdfs_create_merge, dir, dentry, ret);
989 if (ret)
990 d_drop(dentry);
991 kfree(rec_op_para);
992 return ret;
993 }
994
do_rmdir_merge(struct inode * dir,struct dentry * dentry)995 int do_rmdir_merge(struct inode *dir, struct dentry *dentry)
996 {
997 int ret = 0;
998 struct hmdfs_dentry_info_merge *dim = hmdfs_dm(dentry);
999 struct hmdfs_dentry_comrade *comrade = NULL;
1000 struct dentry *lo_d = NULL;
1001 struct dentry *lo_d_dir = NULL;
1002 struct inode *lo_i_dir = NULL;
1003
1004 mutex_lock(&dim->comrade_list_lock);
1005 list_for_each_entry(comrade, &(dim->comrade_list), list) {
1006 lo_d = comrade->lo_d;
1007 lo_d_dir = lock_parent(lo_d);
1008 lo_i_dir = d_inode(lo_d_dir);
1009 ret = vfs_rmdir(lo_i_dir, lo_d);
1010 unlock_dir(lo_d_dir);
1011 if (ret)
1012 break;
1013 }
1014 mutex_unlock(&dim->comrade_list_lock);
1015 hmdfs_trace_merge(trace_hmdfs_rmdir_merge, dir, dentry, ret);
1016 return ret;
1017 }
1018
hmdfs_rmdir_merge(struct inode * dir,struct dentry * dentry)1019 int hmdfs_rmdir_merge(struct inode *dir, struct dentry *dentry)
1020 {
1021 int ret = 0;
1022
1023 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) {
1024 ret = -EACCES;
1025 goto out;
1026 }
1027
1028 ret = do_rmdir_merge(dir, dentry);
1029 if (ret) {
1030 hmdfs_err("rm dir failed:%d", ret);
1031 goto out;
1032 }
1033
1034 d_drop(dentry);
1035 out:
1036 hmdfs_trace_merge(trace_hmdfs_rmdir_merge, dir, dentry, ret);
1037 return ret;
1038 }
1039
do_unlink_merge(struct inode * dir,struct dentry * dentry)1040 int do_unlink_merge(struct inode *dir, struct dentry *dentry)
1041 {
1042 int ret = 0;
1043 struct hmdfs_dentry_info_merge *dim = hmdfs_dm(dentry);
1044 struct hmdfs_dentry_comrade *comrade = NULL;
1045 struct dentry *lo_d = NULL;
1046 struct dentry *lo_d_dir = NULL;
1047 struct inode *lo_i_dir = NULL;
1048
1049 mutex_lock(&dim->comrade_list_lock);
1050 list_for_each_entry(comrade, &(dim->comrade_list), list) {
1051 lo_d = comrade->lo_d;
1052 lo_d_dir = lock_parent(lo_d);
1053 lo_i_dir = d_inode(lo_d_dir);
1054 ret = vfs_unlink(lo_i_dir, lo_d, NULL); // lo_d GET
1055 unlock_dir(lo_d_dir);
1056 if (ret)
1057 break;
1058 }
1059 mutex_unlock(&dim->comrade_list_lock);
1060
1061 return ret;
1062 }
1063
hmdfs_unlink_merge(struct inode * dir,struct dentry * dentry)1064 int hmdfs_unlink_merge(struct inode *dir, struct dentry *dentry)
1065 {
1066 int ret = 0;
1067
1068 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) {
1069 ret = -EACCES;
1070 goto out;
1071 }
1072
1073 ret = do_unlink_merge(dir, dentry);
1074 if (ret) {
1075 hmdfs_err("unlink failed:%d", ret);
1076 goto out;
1077 }
1078
1079 d_drop(dentry);
1080 out:
1081 return ret;
1082 }
1083
do_rename_merge(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)1084 int do_rename_merge(struct inode *old_dir, struct dentry *old_dentry,
1085 struct inode *new_dir, struct dentry *new_dentry,
1086 unsigned int flags)
1087 {
1088 int ret = 0;
1089 struct hmdfs_sb_info *sbi = (old_dir->i_sb)->s_fs_info;
1090 struct hmdfs_dentry_info_merge *dim = hmdfs_dm(old_dentry);
1091 struct hmdfs_dentry_comrade *comrade = NULL, *new_comrade = NULL;
1092 struct path lo_p_new = { .mnt = NULL, .dentry = NULL };
1093 struct inode *lo_i_old_dir = NULL, *lo_i_new_dir = NULL;
1094 struct dentry *lo_d_old_dir = NULL, *lo_d_old = NULL,
1095 *lo_d_new_dir = NULL, *lo_d_new = NULL;
1096 struct dentry *d_new_dir = NULL;
1097 char *path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
1098 char *abs_path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
1099 char *path_name = NULL;
1100
1101 if (flags & ~RENAME_NOREPLACE) {
1102 ret = -EINVAL;
1103 goto out;
1104 }
1105
1106 if (unlikely(!path_buf || !abs_path_buf)) {
1107 ret = -ENOMEM;
1108 goto out;
1109 }
1110
1111 list_for_each_entry(comrade, &dim->comrade_list, list) {
1112 lo_d_old = comrade->lo_d;
1113 d_new_dir = d_find_alias(new_dir);
1114 lo_d_new_dir = hmdfs_get_lo_d(d_new_dir, comrade->dev_id);
1115 dput(d_new_dir);
1116
1117 if (!lo_d_new_dir)
1118 continue;
1119 path_name = dentry_path_raw(lo_d_new_dir, path_buf, PATH_MAX);
1120 dput(lo_d_new_dir);
1121 if (IS_ERR(path_name)) {
1122 ret = PTR_ERR(path_name);
1123 continue;
1124 }
1125
1126 if (strlen(sbi->real_dst) + strlen(path_name) +
1127 strlen(new_dentry->d_name.name) + 2 > PATH_MAX) {
1128 ret = -ENAMETOOLONG;
1129 goto out;
1130 }
1131
1132 snprintf(abs_path_buf, PATH_MAX, "%s%s/%s", sbi->real_dst,
1133 path_name, new_dentry->d_name.name);
1134 if (S_ISDIR(d_inode(old_dentry)->i_mode))
1135 lo_d_new = kern_path_create(AT_FDCWD, abs_path_buf,
1136 &lo_p_new,
1137 LOOKUP_DIRECTORY);
1138 else
1139 lo_d_new = kern_path_create(AT_FDCWD, abs_path_buf,
1140 &lo_p_new, 0);
1141 if (IS_ERR(lo_d_new))
1142 continue;
1143
1144 lo_d_new_dir = dget_parent(lo_d_new);
1145 lo_i_new_dir = d_inode(lo_d_new_dir);
1146 lo_d_old_dir = dget_parent(lo_d_old);
1147 lo_i_old_dir = d_inode(lo_d_old_dir);
1148
1149 ret = vfs_rename(lo_i_old_dir, lo_d_old, lo_i_new_dir, lo_d_new,
1150 NULL, flags);
1151 new_comrade = alloc_comrade(lo_p_new.dentry, comrade->dev_id);
1152 if (IS_ERR(new_comrade)) {
1153 ret = PTR_ERR(new_comrade);
1154 goto no_comrade;
1155 }
1156
1157 link_comrade_unlocked(new_dentry, new_comrade);
1158 no_comrade:
1159 done_path_create(&lo_p_new, lo_d_new);
1160 dput(lo_d_old_dir);
1161 dput(lo_d_new_dir);
1162 }
1163 out:
1164 kfree(abs_path_buf);
1165 kfree(path_buf);
1166 return ret;
1167 }
1168
hmdfs_rename_merge(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)1169 int hmdfs_rename_merge(struct inode *old_dir, struct dentry *old_dentry,
1170 struct inode *new_dir, struct dentry *new_dentry,
1171 unsigned int flags)
1172 {
1173 char *old_dir_buf = NULL;
1174 char *new_dir_buf = NULL;
1175 char *old_dir_path = NULL;
1176 char *new_dir_path = NULL;
1177 struct dentry *old_dir_dentry = NULL;
1178 struct dentry *new_dir_dentry = NULL;
1179 int ret = 0;
1180
1181 if (hmdfs_file_type(old_dentry->d_name.name) != HMDFS_TYPE_COMMON ||
1182 hmdfs_file_type(new_dentry->d_name.name) != HMDFS_TYPE_COMMON) {
1183 ret = -EACCES;
1184 goto rename_out;
1185 }
1186 old_dir_buf = kmalloc(PATH_MAX, GFP_KERNEL);
1187 new_dir_buf = kmalloc(PATH_MAX, GFP_KERNEL);
1188 if (!old_dir_buf || !new_dir_buf) {
1189 ret = -ENOMEM;
1190 goto rename_out;
1191 }
1192
1193 new_dir_dentry = d_find_alias(new_dir);
1194 if (!new_dir_dentry) {
1195 ret = -EINVAL;
1196 goto rename_out;
1197 }
1198
1199 old_dir_dentry = d_find_alias(old_dir);
1200 if (!old_dir_dentry) {
1201 ret = -EINVAL;
1202 dput(new_dir_dentry);
1203 goto rename_out;
1204 }
1205
1206 old_dir_path = dentry_path_raw(old_dir_dentry, old_dir_buf, PATH_MAX);
1207 new_dir_path = dentry_path_raw(new_dir_dentry, new_dir_buf, PATH_MAX);
1208 dput(new_dir_dentry);
1209 dput(old_dir_dentry);
1210 if (strcmp(old_dir_path, new_dir_path)) {
1211 ret = -EPERM;
1212 goto rename_out;
1213 }
1214
1215 trace_hmdfs_rename_merge(old_dir, old_dentry, new_dir, new_dentry,
1216 flags);
1217 ret = do_rename_merge(old_dir, old_dentry, new_dir, new_dentry, flags);
1218
1219 if (ret != 0)
1220 d_drop(new_dentry);
1221
1222 if (S_ISREG(old_dentry->d_inode->i_mode) && !ret)
1223 d_invalidate(old_dentry);
1224
1225 rename_out:
1226 hmdfs_trace_rename_merge(old_dir, old_dentry, new_dir, new_dentry, ret);
1227 kfree(old_dir_buf);
1228 kfree(new_dir_buf);
1229 return ret;
1230 }
1231
1232 const struct inode_operations hmdfs_dir_iops_merge = {
1233 .lookup = hmdfs_lookup_merge,
1234 .mkdir = hmdfs_mkdir_merge,
1235 .create = hmdfs_create_merge,
1236 .rmdir = hmdfs_rmdir_merge,
1237 .unlink = hmdfs_unlink_merge,
1238 .rename = hmdfs_rename_merge,
1239 .permission = hmdfs_permission,
1240 };
1241