From bc01a3376467dd166f3bdc14fec8d42d912a2dfa Mon Sep 17 00:00:00 2001 From: qianjiaxing Date: Sun, 4 Sep 2022 11:46:27 +0000 Subject: [PATCH] hmdfs: async to lookup in merge view ohos inclusion category: bugfix issue: #I5RWZ7 CVE: NA ---------------------------------------------- async to lookup in merge view Signed-off-by: waterwin --- fs/hmdfs/dentry.c | 1 + fs/hmdfs/file_merge.c | 2 + fs/hmdfs/hmdfs_dentryfile.c | 84 +++++++++ fs/hmdfs/hmdfs_device_view.h | 1 + fs/hmdfs/hmdfs_merge_view.h | 51 +++++- fs/hmdfs/hmdfs_trace.h | 95 +++++++++++ fs/hmdfs/inode_merge.c | 319 ++++++++++++++++++++++++++--------- 7 files changed, 474 insertions(+), 79 deletions(-) diff --git a/fs/hmdfs/dentry.c b/fs/hmdfs/dentry.c index ac590df0982a..8ec7ab33412f 100644 --- a/fs/hmdfs/dentry.c +++ b/fs/hmdfs/dentry.c @@ -259,6 +259,7 @@ void clear_comrades(struct dentry *dentry) { struct hmdfs_dentry_info_merge *cdi = hmdfs_dm(dentry); + wait_event(cdi->wait_queue, !has_merge_lookup_work(cdi)); mutex_lock(&cdi->comrade_list_lock); clear_comrades_locked(&cdi->comrade_list); mutex_unlock(&cdi->comrade_list_lock); diff --git a/fs/hmdfs/file_merge.c b/fs/hmdfs/file_merge.c index ea974d77c843..e7b75b6e3e9f 100644 --- a/fs/hmdfs/file_merge.c +++ b/fs/hmdfs/file_merge.c @@ -378,6 +378,8 @@ int do_dir_open_merge(struct file *file, const struct cred *cred, if (IS_ERR_OR_NULL(cred)) return ret; + + wait_event(dim->wait_queue, !has_merge_lookup_work(dim)); mutex_lock(&dim->comrade_list_lock); list_for_each_entry(comrade, &(dim->comrade_list), list) { diff --git a/fs/hmdfs/hmdfs_dentryfile.c b/fs/hmdfs/hmdfs_dentryfile.c index bb9faff3e027..3455b91b4d61 100644 --- a/fs/hmdfs/hmdfs_dentryfile.c +++ b/fs/hmdfs/hmdfs_dentryfile.c @@ -19,6 +19,7 @@ #include "comm/transport.h" #include "hmdfs_client.h" #include "hmdfs_device_view.h" +#include "hmdfs_merge_view.h" /* Hashing code copied from f2fs */ #define HMDFS_HASH_COL_BIT ((0x1ULL) << 63) @@ -269,6 +270,89 @@ char *hmdfs_get_dentry_relative_path(struct dentry *dentry) return final_buf; } +static char *hmdfs_merge_dentry_path_raw(struct dentry *d, char *buf, int buflen) +{ + struct dentry *dentry = NULL; + char *end = NULL; + char *retval = NULL; + unsigned int len; + unsigned int seq = 0; + int error = 0; + struct hmdfs_dentry_info_merge *mdi = hmdfs_dm(d); + + rcu_read_lock(); +restart: + dentry = d; + end = buf + buflen; + len = buflen; + prepend(&end, &len, "\0", 1); + retval = end - 1; + *retval = '/'; + read_seqbegin_or_lock(&rename_lock, &seq); + while (mdi->dentry_type != HMDFS_LAYER_FIRST_MERGE) { + struct dentry *parent = dentry->d_parent; + + prefetch(parent); + error = prepend_name(&end, &len, &dentry->d_name); + if (error) + break; + retval = end; + dentry = parent; + mdi = hmdfs_dm(dentry); + } + if (!(seq & 1)) + rcu_read_unlock(); + if (need_seqretry(&rename_lock, seq)) { + seq = 1; + goto restart; + } + done_seqretry(&rename_lock, seq); + if (error) + goto Elong; + return retval; +Elong: + return ERR_PTR(-ENAMETOOLONG); +} + +char *hmdfs_merge_get_dentry_relative_path(struct dentry *dentry) +{ + char *final_buf = NULL; + char *buf = NULL; + char *p = NULL; + + buf = kzalloc(PATH_MAX, GFP_KERNEL); + if (!buf) + return NULL; + + final_buf = kzalloc(PATH_MAX, GFP_KERNEL); + if (!final_buf) { + kfree(buf); + return NULL; + } + + /* NULL dentry return root dir */ + if (!dentry) { + strcpy(final_buf, "/"); + kfree(buf); + return final_buf; + } + p = hmdfs_merge_dentry_path_raw(dentry, buf, PATH_MAX); + if (IS_ERR_OR_NULL(p)) { + kfree(buf); + kfree(final_buf); + return NULL; + } + + if (strlen(p) >= PATH_MAX) { + kfree(buf); + kfree(final_buf); + return NULL; + } + strcpy(final_buf, p); + kfree(buf); + return final_buf; +} + char *hmdfs_get_dentry_absolute_path(const char *rootdir, const char *relative_path) { diff --git a/fs/hmdfs/hmdfs_device_view.h b/fs/hmdfs/hmdfs_device_view.h index 160391226caf..0e397254c8ea 100644 --- a/fs/hmdfs/hmdfs_device_view.h +++ b/fs/hmdfs/hmdfs_device_view.h @@ -181,6 +181,7 @@ struct hmdfs_lookup_ret *hmdfs_lookup_by_con(struct hmdfs_peer *con, char *hmdfs_connect_path(const char *path, const char *name); char *hmdfs_get_dentry_relative_path(struct dentry *dentry); +char *hmdfs_merge_get_dentry_relative_path(struct dentry *dentry); char *hmdfs_get_dentry_absolute_path(const char *rootdir, const char *relative_path); int hmdfs_convert_lookup_flags(unsigned int hmdfs_flags, diff --git a/fs/hmdfs/hmdfs_merge_view.h b/fs/hmdfs/hmdfs_merge_view.h index ad9eff5cb5c3..f7d21cc5bd7f 100644 --- a/fs/hmdfs/hmdfs_merge_view.h +++ b/fs/hmdfs/hmdfs_merge_view.h @@ -12,15 +12,31 @@ #include "comm/connection.h" #include +#include +#include +#include /***************************************************************************** * Dentires for merge view and their comrades. * A dentry's lower dentry is named COMRADE. *****************************************************************************/ +struct merge_lookup_work { + char *name; + int devid; + unsigned int flags; + struct hmdfs_sb_info *sbi; + wait_queue_head_t *wait_queue; + struct work_struct work; +}; + struct hmdfs_dentry_info_merge { unsigned long ctime; - // For the merge view to link dentries with same names + int type; + int work_count; + struct mutex work_lock; + wait_queue_head_t wait_queue; + __u8 dentry_type; struct mutex comrade_list_lock; struct list_head comrade_list; }; @@ -85,6 +101,39 @@ static inline void link_comrade_unlocked(struct dentry *dentry, void clear_comrades_locked(struct list_head *comrade_list); +static inline bool is_comrade_list_empty(struct hmdfs_dentry_info_merge *mdi) +{ + bool ret; + + mutex_lock(&mdi->comrade_list_lock); + ret = list_empty(&mdi->comrade_list); + mutex_unlock(&mdi->comrade_list_lock); + + return ret; +} + +static inline bool has_merge_lookup_work(struct hmdfs_dentry_info_merge *mdi) +{ + bool ret; + + mutex_lock(&mdi->work_lock); + ret = (mdi->work_count != 0); + mutex_unlock(&mdi->work_lock); + + return ret; +} + +static inline bool is_merge_lookup_end(struct hmdfs_dentry_info_merge *mdi) +{ + bool ret; + + mutex_lock(&mdi->work_lock); + ret = mdi->work_count == 0 || !is_comrade_list_empty(mdi); + mutex_unlock(&mdi->work_lock); + + return ret; +} + #define for_each_comrade_locked(_dentry, _comrade) \ list_for_each_entry(_comrade, &(hmdfs_dm(_dentry)->comrade_list), list) diff --git a/fs/hmdfs/hmdfs_trace.h b/fs/hmdfs/hmdfs_trace.h index d3c5262b5f46..86478425aea8 100644 --- a/fs/hmdfs/hmdfs_trace.h +++ b/fs/hmdfs/hmdfs_trace.h @@ -17,6 +17,7 @@ #include "hmdfs_dentryfile.h" #include "hmdfs_client.h" #include "hmdfs_device_view.h" +#include "hmdfs_merge_view.h" #include "client_writeback.h" TRACE_EVENT(hmdfs_permission, @@ -787,6 +788,100 @@ TRACE_EVENT(hmdfs_server_open_exit, __entry->ctime_nsec, __entry->stable_ctime, __entry->stable_ctime_nsec) ); + +TRACE_EVENT(hmdfs_merge_lookup_work_enter, + + TP_PROTO(struct merge_lookup_work *ml_work), + + TP_ARGS(ml_work), + + TP_STRUCT__entry( + __field(int, devid) + __string(name, ml_work->name) + __field(unsigned int, flags) + ), + + TP_fast_assign( + __entry->devid = ml_work->devid; + __assign_str(name, ml_work->name); + __entry->flags = ml_work->flags; + ), + + TP_printk("devid = %d, name:%s, flags:%u", + __entry->devid, + __get_str(name), + __entry->flags) +); + +TRACE_EVENT(hmdfs_merge_lookup_work_exit, + + TP_PROTO(struct merge_lookup_work *ml_work, int found), + + TP_ARGS(ml_work, found), + + TP_STRUCT__entry( + __field(int, devid) + __string(name, ml_work->name) + __field(unsigned int, flags) + __field(int, found) + ), + + TP_fast_assign( + __entry->devid = ml_work->devid; + __assign_str(name, ml_work->name); + __entry->flags = ml_work->flags; + __entry->found = found; + ), + + TP_printk("devid = %d, name:%s, flags:%u, found:%d", + __entry->devid, + __get_str(name), + __entry->flags, + __entry->found) +); + +TRACE_EVENT(hmdfs_merge_update_dentry_info_enter, + + TP_PROTO(struct dentry *src_dentry, struct dentry *dst_dentry), + + TP_ARGS(src_dentry, dst_dentry), + + TP_STRUCT__entry( + __string(src_name, src_dentry->d_name.name) + __string(dst_name, dst_dentry->d_name.name) + ), + + TP_fast_assign( + __assign_str(src_name, src_dentry->d_name.name); + __assign_str(dst_name, dst_dentry->d_name.name); + ), + + TP_printk("src name:%s, dst name:%s", + __get_str(src_name), + __get_str(dst_name)) +); + +TRACE_EVENT(hmdfs_merge_update_dentry_info_exit, + + TP_PROTO(struct dentry *src_dentry, struct dentry *dst_dentry), + + TP_ARGS(src_dentry, dst_dentry), + + TP_STRUCT__entry( + __string(src_name, src_dentry->d_name.name) + __string(dst_name, dst_dentry->d_name.name) + ), + + TP_fast_assign( + __assign_str(src_name, src_dentry->d_name.name); + __assign_str(dst_name, dst_dentry->d_name.name); + ), + + TP_printk("src name:%s, dst name:%s", + __get_str(src_name), + __get_str(dst_name)) +); + #endif #undef TRACE_INCLUDE_PATH diff --git a/fs/hmdfs/inode_merge.c b/fs/hmdfs/inode_merge.c index 134c9d8d7f76..c020c8c201fa 100644 --- a/fs/hmdfs/inode_merge.c +++ b/fs/hmdfs/inode_merge.c @@ -342,77 +342,202 @@ int check_filename(const char *name, int len) return 0; } -static int lookup_merge_normal(struct dentry *child_dentry, unsigned int flags) +static struct hmdfs_dentry_comrade *merge_lookup_comrade( + struct hmdfs_sb_info *sbi, const char *name, int devid, + unsigned int flags) { - struct dentry *parent_dentry = dget_parent(child_dentry); - struct hmdfs_dentry_info_merge *pdi = hmdfs_dm(parent_dentry); - struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); - struct hmdfs_dentry_comrade *comrade, *cc; - struct path lo_p, path; - LIST_HEAD(head); - int ret = -ENOENT; - int dev_id = -1; - int ftype; - char *lo_name; - umode_t mode; + int err; + struct path root, path; + struct hmdfs_dentry_comrade *comrade = NULL; + const struct cred *old_cred = hmdfs_override_creds(sbi->cred); + + err = kern_path(sbi->real_dst, LOOKUP_DIRECTORY, &root); + if (err) { + comrade = ERR_PTR(err); + goto out; + } + + err = vfs_path_lookup(root.dentry, root.mnt, name, flags, &path); + if (err) { + comrade = ERR_PTR(err); + goto root_put; + } + + comrade = alloc_comrade(path.dentry, devid); + + path_put(&path); +root_put: + path_put(&root); +out: + hmdfs_revert_creds(old_cred); + return comrade; +} + +static bool is_valid_comrade(struct hmdfs_dentry_info_merge *mdi, umode_t mode) +{ + if (mdi->type == DT_UNKNOWN) { + mdi->type = S_ISDIR(mode) ? DT_DIR : DT_REG; + return true; + } + + if (mdi->type == DT_DIR && S_ISDIR(mode)) { + return true; + } + + if (mdi->type == DT_REG && list_empty(&mdi->comrade_list) && + !S_ISDIR(mode)) { + return true; + } + + return false; +} + +static void merge_lookup_work_func(struct work_struct *work) +{ + struct merge_lookup_work *ml_work; + struct hmdfs_dentry_comrade *comrade; + struct hmdfs_dentry_info_merge *mdi; + int found = false; + + ml_work = container_of(work, struct merge_lookup_work, work); + mdi = container_of(ml_work->wait_queue, struct hmdfs_dentry_info_merge, + wait_queue); + + trace_hmdfs_merge_lookup_work_enter(ml_work); + + comrade = merge_lookup_comrade(ml_work->sbi, ml_work->name, + ml_work->devid, ml_work->flags); + if (IS_ERR(comrade)) { + goto out; + } + + mutex_lock(&mdi->work_lock); + mutex_lock(&mdi->comrade_list_lock); + if (!is_valid_comrade(mdi, hmdfs_cm(comrade))) { + destroy_comrade(comrade); + } else { + found = true; + link_comrade(&mdi->comrade_list, comrade); + } + mutex_unlock(&mdi->comrade_list_lock); + +out: + if (--mdi->work_count == 0 || found) + wake_up_all(ml_work->wait_queue); + mutex_unlock(&mdi->work_lock); + + trace_hmdfs_merge_lookup_work_exit(ml_work, found); + kfree(ml_work->name); + kfree(ml_work); +} + +static int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi, + struct hmdfs_sb_info *sbi, int devid, const char *name, + unsigned int flags) +{ + int err = -ENOMEM; + struct merge_lookup_work *ml_work; + + ml_work = kmalloc(sizeof(*ml_work), GFP_KERNEL); + if (!ml_work) + goto out; + + ml_work->name = kstrdup(name, GFP_KERNEL); + if (!ml_work->name) { + kfree(ml_work); + goto out; + } + + ml_work->devid = devid; + ml_work->flags = flags; + ml_work->sbi = sbi; + ml_work->wait_queue = &mdi->wait_queue; + INIT_WORK(&ml_work->work, merge_lookup_work_func); - ftype = check_filename(child_dentry->d_name.name, - child_dentry->d_name.len); - if (ftype == DT_REG) - lo_name = conf_name_trans_reg(child_dentry, &dev_id); - else if (ftype == DT_DIR) - lo_name = conf_name_trans_dir(child_dentry); + schedule_work(&ml_work->work); + ++mdi->work_count; + err = 0; +out: + return err; +} + +static char *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type) +{ + char *rname; + + *type = check_filename(dentry->d_name.name, dentry->d_name.len); + if (*type == DT_REG) + rname = conf_name_trans_reg(dentry, devid); + else if (*type == DT_DIR) + rname = conf_name_trans_dir(dentry); else - lo_name = conf_name_trans_nop(child_dentry); - if (unlikely(!lo_name)) { - ret = -ENOMEM; + rname = conf_name_trans_nop(dentry); + + return rname; +} + +static int lookup_merge_normal(struct dentry *dentry, unsigned int flags) +{ + int ret = -ENOMEM; + int err = 0; + int devid = -1; + struct dentry *pdentry = dget_parent(dentry); + struct hmdfs_dentry_info_merge *mdi = hmdfs_dm(dentry); + struct hmdfs_sb_info *sbi = hmdfs_sb(dentry->d_sb); + struct hmdfs_peer *peer; + char *rname, *ppath, *cpath; + + rname = hmdfs_get_real_dname(dentry, &devid, &mdi->type); + if (unlikely(!rname)) { goto out; } - ret = hmdfs_get_path_in_sb(child_dentry->d_sb, sbi->real_dst, - LOOKUP_DIRECTORY, &path); - if (ret) { - if (ret == -ENOENT) - ret = -EINVAL; - goto free; + ppath = hmdfs_merge_get_dentry_relative_path(pdentry); + if (unlikely(!ppath)) { + hmdfs_err("failed to get parent relative path"); + goto out_rname; } - lo_p.mnt = path.mnt; - ret = -ENOENT; - mutex_lock(&pdi->comrade_list_lock); - list_for_each_entry(cc, &pdi->comrade_list, list) { - if (ftype == DT_REG && cc->dev_id != dev_id) - continue; + cpath = kzalloc(PATH_MAX, GFP_KERNEL); + if (unlikely(!cpath)) { + hmdfs_err("failed to get child device_view path"); + goto out_ppath; + } - lo_p.dentry = cc->lo_d; - comrade = lookup_comrade(lo_p, lo_name, cc->dev_id, flags); - if (IS_ERR(comrade)) { - ret = ret ? PTR_ERR(comrade) : 0; - continue; - } + mutex_lock(&sbi->connections.node_lock); + if (mdi->type != DT_REG || devid == 0) { + snprintf(cpath, PATH_MAX, "device_view/local%s/%s", ppath, + rname); + err = merge_lookup_async(mdi, sbi, 0, cpath, flags); + if (err) + hmdfs_err("failed to create local lookup work"); + } - mode = hmdfs_cm(comrade); - if ((ftype == DT_DIR && !S_ISDIR(mode)) || - (ftype == DT_REG && S_ISDIR(mode))) { - destroy_comrade(comrade); - ret = ret ? PTR_ERR(comrade) : 0; + list_for_each_entry(peer, &sbi->connections.node_list, list) { + if (mdi->type == DT_REG && peer->device_id != devid) continue; - } + snprintf(cpath, PATH_MAX, "device_view/%s%s/%s", peer->cid, + ppath, rname); + err = merge_lookup_async(mdi, sbi, peer->device_id, cpath, + flags); + if (err) + hmdfs_err("failed to create remote lookup work"); + } + mutex_unlock(&sbi->connections.node_lock); + wait_event(mdi->wait_queue, is_merge_lookup_end(mdi)); + + ret = -ENOENT; + if (!is_comrade_list_empty(mdi)) ret = 0; - link_comrade(&head, comrade); - - if (!S_ISDIR(mode)) - break; - } - mutex_unlock(&pdi->comrade_list_lock); - assign_comrades_unlocked(child_dentry, &head); - path_put(&path); -free: - kfree(lo_name); + kfree(cpath); +out_ppath: + kfree(ppath); +out_rname: + kfree(rname); out: - dput(parent_dentry); + dput(pdentry); return ret; } @@ -425,10 +550,12 @@ static int lookup_merge_normal(struct dentry *child_dentry, unsigned int flags) static int do_lookup_merge_root(struct path path_dev, struct dentry *child_dentry, unsigned int flags) { + struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); struct hmdfs_dentry_comrade *comrade; const int buf_len = max((int)HMDFS_CID_SIZE + 1, (int)sizeof(DEVICE_VIEW_LOCAL)); char *buf = kzalloc(buf_len, GFP_KERNEL); + struct hmdfs_peer *peer; LIST_HEAD(head); int ret; @@ -444,6 +571,20 @@ static int do_lookup_merge_root(struct path path_dev, } link_comrade(&head, comrade); + // lookup real_dst/device_view/cidxx + mutex_lock(&sbi->connections.node_lock); + list_for_each_entry(peer, &sbi->connections.node_list, list) { + mutex_unlock(&sbi->connections.node_lock); + memcpy(buf, peer->cid, HMDFS_CID_SIZE); + comrade = lookup_comrade(path_dev, buf, peer->device_id, flags); + if (IS_ERR(comrade)) + continue; + + link_comrade(&head, comrade); + mutex_lock(&sbi->connections.node_lock); + } + mutex_unlock(&sbi->connections.node_lock); + assign_comrades_unlocked(child_dentry, &head); ret = 0; @@ -529,19 +670,24 @@ static int lookup_merge_root(struct inode *root_inode, } int init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi, - struct dentry *dentry) + struct dentry *dentry) { - struct hmdfs_dentry_info_merge *info = NULL; + struct hmdfs_dentry_info_merge *mdi = NULL; - info = kmem_cache_zalloc(hmdfs_dentry_merge_cachep, GFP_NOFS); - if (!info) + mdi = kmem_cache_zalloc(hmdfs_dentry_merge_cachep, GFP_NOFS); + if (!mdi) return -ENOMEM; - info->ctime = jiffies; - INIT_LIST_HEAD(&info->comrade_list); - mutex_init(&info->comrade_list_lock); + mdi->ctime = jiffies; + mdi->type = DT_UNKNOWN; + mdi->work_count = 0; + mutex_init(&mdi->work_lock); + init_waitqueue_head(&mdi->wait_queue); + INIT_LIST_HEAD(&mdi->comrade_list); + mutex_init(&mdi->comrade_list_lock); + d_set_d_op(dentry, &hmdfs_dops_merge); - dentry->d_fsdata = info; + dentry->d_fsdata = mdi; return 0; } @@ -549,18 +695,17 @@ static void update_dm(struct dentry *dst, struct dentry *src) { struct hmdfs_dentry_info_merge *dmi_dst = hmdfs_dm(dst); struct hmdfs_dentry_info_merge *dmi_src = hmdfs_dm(src); - LIST_HEAD(tmp_dst); - LIST_HEAD(tmp_src); - - /* Mobilize all the comrades */ - mutex_lock(&dmi_dst->comrade_list_lock); - mutex_lock(&dmi_src->comrade_list_lock); - list_splice_init(&dmi_dst->comrade_list, &tmp_dst); - list_splice_init(&dmi_src->comrade_list, &tmp_src); - list_splice(&tmp_dst, &dmi_src->comrade_list); - list_splice(&tmp_src, &dmi_dst->comrade_list); - mutex_unlock(&dmi_src->comrade_list_lock); - mutex_unlock(&dmi_dst->comrade_list_lock); + + trace_hmdfs_merge_update_dentry_info_enter(src, dst); + + spin_lock(&dst->d_lock); + spin_lock(&src->d_lock); + dst->d_fsdata = dmi_src; + src->d_fsdata = dmi_dst; + spin_unlock(&src->d_lock); + spin_unlock(&dst->d_lock); + + trace_hmdfs_merge_update_dentry_info_exit(src, dst); } // do this in a map-reduce manner @@ -595,10 +740,13 @@ struct dentry *hmdfs_lookup_merge(struct inode *parent_inode, if (unlikely(err)) goto out; - if (pii->inode_type == HMDFS_LAYER_ZERO) + if (pii->inode_type == HMDFS_LAYER_ZERO) { + hmdfs_dm(child_dentry)->dentry_type = HMDFS_LAYER_FIRST_MERGE; err = lookup_merge_root(parent_inode, child_dentry, flags); - else + } else { + hmdfs_dm(child_dentry)->dentry_type = HMDFS_LAYER_OTHER_MERGE; err = lookup_merge_normal(child_dentry, flags); + } if (!err) { struct hmdfs_inode_info *info = NULL; @@ -853,8 +1001,11 @@ static int create_lo_d_parent_recur(struct dentry *d_parent, struct hmdfs_recursive_para *rec_op_para) { struct dentry *lo_d_parent, *d_pparent; + struct hmdfs_dentry_info_merge *pmdi = NULL; int ret = 0; + pmdi = hmdfs_dm(d_parent); + wait_event(pmdi->wait_queue, !has_merge_lookup_work(pmdi)); lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); if (!lo_d_parent) { d_pparent = dget_parent(d_parent); @@ -884,9 +1035,12 @@ int create_lo_d_child(struct inode *i_parent, struct dentry *d_child, { struct dentry *d_pparent, *lo_d_parent, *lo_d_child; struct dentry *d_parent = dget_parent(d_child); + struct hmdfs_dentry_info_merge *pmdi = hmdfs_dm(d_parent); int ret = 0; mode_t d_child_mode = rec_op_para->mode; + wait_event(pmdi->wait_queue, !has_merge_lookup_work(pmdi)); + lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); if (!lo_d_parent) { d_pparent = dget_parent(d_parent); @@ -985,6 +1139,8 @@ int do_rmdir_merge(struct inode *dir, struct dentry *dentry) struct dentry *lo_d_dir = NULL; struct inode *lo_i_dir = NULL; + wait_event(dim->wait_queue, !has_merge_lookup_work(dim)); + mutex_lock(&dim->comrade_list_lock); list_for_each_entry(comrade, &(dim->comrade_list), list) { lo_d = comrade->lo_d; @@ -1030,6 +1186,8 @@ int do_unlink_merge(struct inode *dir, struct dentry *dentry) struct dentry *lo_d_dir = NULL; struct inode *lo_i_dir = NULL; + wait_event(dim->wait_queue, !has_merge_lookup_work(dim)); + mutex_lock(&dim->comrade_list_lock); list_for_each_entry(comrade, &(dim->comrade_list), list) { lo_d = comrade->lo_d; @@ -1081,6 +1239,7 @@ int do_rename_merge(struct inode *old_dir, struct dentry *old_dentry, char *path_buf = kmalloc(PATH_MAX, GFP_KERNEL); char *abs_path_buf = kmalloc(PATH_MAX, GFP_KERNEL); char *path_name = NULL; + struct hmdfs_dentry_info_merge *pmdi = NULL; if (flags & ~RENAME_NOREPLACE) { ret = -EINVAL; @@ -1092,9 +1251,13 @@ int do_rename_merge(struct inode *old_dir, struct dentry *old_dentry, goto out; } + wait_event(dim->wait_queue, !has_merge_lookup_work(dim)); + list_for_each_entry(comrade, &dim->comrade_list, list) { lo_d_old = comrade->lo_d; d_new_dir = d_find_alias(new_dir); + pmdi = hmdfs_dm(d_new_dir); + wait_event(pmdi->wait_queue, !has_merge_lookup_work(pmdi)); lo_d_new_dir = hmdfs_get_lo_d(d_new_dir, comrade->dev_id); dput(d_new_dir); -- Gitee