From 73e8e56f7ea90fc7670b15687ad0f2f1f6053592 Mon Sep 17 00:00:00 2001 From: waterwin Date: Thu, 15 Sep 2022 16:47:18 +0800 Subject: [PATCH] hmdfs: async to release dentry ohos inclusion category: bugfix issue: #I5RA1C CVE: NA ---------------------------------------------- async to release dentry in merge view Signed-off-by: waterwin --- fs/hmdfs/dentry.c | 18 +++++----- fs/hmdfs/hmdfs_merge_view.h | 6 +++- fs/hmdfs/hmdfs_trace.h | 72 +++++++++++++++++++++++++++++++++++++ fs/hmdfs/inode_merge.c | 26 +++++++++++++- 4 files changed, 110 insertions(+), 12 deletions(-) diff --git a/fs/hmdfs/dentry.c b/fs/hmdfs/dentry.c index 8ec7ab33412f..ff1441abcb8f 100644 --- a/fs/hmdfs/dentry.c +++ b/fs/hmdfs/dentry.c @@ -12,6 +12,7 @@ #include "hmdfs_dentryfile.h" #include "hmdfs_device_view.h" #include "hmdfs_merge_view.h" +#include "hmdfs_trace.h" extern struct kmem_cache *hmdfs_dentry_cachep; @@ -255,14 +256,11 @@ void clear_comrades_locked(struct list_head *comrade_list) INIT_LIST_HEAD(comrade_list); } -void clear_comrades(struct dentry *dentry) +void clear_comrades(struct hmdfs_dentry_info_merge *mdi) { - 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); + mutex_lock(&mdi->comrade_list_lock); + clear_comrades_locked(&mdi->comrade_list); + mutex_unlock(&mdi->comrade_list_lock); } /** @@ -280,10 +278,10 @@ static void d_release_merge(struct dentry *dentry) { if (!dentry || !dentry->d_fsdata) return; - - clear_comrades(dentry); - kmem_cache_free(hmdfs_dentry_merge_cachep, dentry->d_fsdata); + trace_hmdfs_merge_d_release_enter(dentry); + merge_dentry_info_put(dentry->d_fsdata); dentry->d_fsdata = NULL; + trace_hmdfs_merge_d_release_exit(dentry); } const struct dentry_operations hmdfs_dops_merge = { diff --git a/fs/hmdfs/hmdfs_merge_view.h b/fs/hmdfs/hmdfs_merge_view.h index f7d21cc5bd7f..b8ff42fddf1f 100644 --- a/fs/hmdfs/hmdfs_merge_view.h +++ b/fs/hmdfs/hmdfs_merge_view.h @@ -34,6 +34,8 @@ struct hmdfs_dentry_info_merge { unsigned long ctime; int type; int work_count; + struct kref ref; + struct mutex mutex; struct mutex work_lock; wait_queue_head_t wait_queue; __u8 dentry_type; @@ -89,7 +91,7 @@ static inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade) kfree(comrade); } -void clear_comrades(struct dentry *dentry); +void clear_comrades(struct hmdfs_dentry_info_merge *mdi); static inline void link_comrade_unlocked(struct dentry *dentry, struct hmdfs_dentry_comrade *comrade) @@ -196,5 +198,7 @@ extern const struct dentry_operations hmdfs_dops_merge; * dentry cache for the merge view *****************************************************************************/ extern struct kmem_cache *hmdfs_dentry_merge_cachep; +void merge_dentry_info_release(struct kref *kref); +void merge_dentry_info_put(struct hmdfs_dentry_info_merge *mdi); #endif // HMDFS_MERGE_H diff --git a/fs/hmdfs/hmdfs_trace.h b/fs/hmdfs/hmdfs_trace.h index 86478425aea8..e7cfba8ebd2a 100644 --- a/fs/hmdfs/hmdfs_trace.h +++ b/fs/hmdfs/hmdfs_trace.h @@ -882,6 +882,78 @@ TRACE_EVENT(hmdfs_merge_update_dentry_info_exit, __get_str(dst_name)) ); +TRACE_EVENT(hmdfs_merge_d_release_enter, + + TP_PROTO(struct dentry *dentry), + + TP_ARGS(dentry), + + TP_STRUCT__entry( + __string(name, dentry->d_name.name) + ), + + TP_fast_assign( + __assign_str(name, dentry->d_name.name); + ), + + TP_printk("name:%s", + __get_str(name)) +); + +TRACE_EVENT(hmdfs_merge_d_release_exit, + + TP_PROTO(struct dentry *dentry), + + TP_ARGS(dentry), + + TP_STRUCT__entry( + __string(name, dentry->d_name.name) + ), + + TP_fast_assign( + __assign_str(name, dentry->d_name.name); + ), + + TP_printk("name:%s", + __get_str(name)) +); + +TRACE_EVENT(hmdfs_merge_dentry_info_put, + + TP_PROTO(unsigned int ref), + + TP_ARGS(ref), + + TP_STRUCT__entry( + __field(unsigned int, ref) + ), + + TP_fast_assign( + __entry->ref = ref; + ), + + TP_printk("ref:%u", + __entry->ref) +); + +TRACE_EVENT(hmdfs_merge_dentry_info_release, + + TP_PROTO(int count), + + TP_ARGS(count), + + TP_STRUCT__entry( + __field(int, count) + ), + + TP_fast_assign( + __entry->count = count; + ), + + TP_printk("count:%d", + __entry->count) +); + #endif #undef TRACE_INCLUDE_PATH diff --git a/fs/hmdfs/inode_merge.c b/fs/hmdfs/inode_merge.c index c020c8c201fa..69d6172dce66 100644 --- a/fs/hmdfs/inode_merge.c +++ b/fs/hmdfs/inode_merge.c @@ -36,6 +36,23 @@ struct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry) return d; } +void merge_dentry_info_release(struct kref *kref) +{ + struct hmdfs_dentry_info_merge *mdi; + + mdi = (struct hmdfs_dentry_info_merge *)container_of(kref, + struct hmdfs_dentry_info_merge, ref); + trace_hmdfs_merge_dentry_info_release((mdi->work_count)); + clear_comrades(mdi); + kmem_cache_free(hmdfs_dentry_merge_cachep, mdi); +} + +void merge_dentry_info_put(struct hmdfs_dentry_info_merge *mdi) +{ + trace_hmdfs_merge_dentry_info_put((kref_read(&mdi->ref))); + kref_put_mutex(&mdi->ref, merge_dentry_info_release, &mdi->mutex); +} + struct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id) { struct hmdfs_dentry_info_merge *dim = hmdfs_dm(dentry); @@ -429,6 +446,8 @@ static void merge_lookup_work_func(struct work_struct *work) trace_hmdfs_merge_lookup_work_exit(ml_work, found); kfree(ml_work->name); kfree(ml_work); + + merge_dentry_info_put(mdi); } static int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi, @@ -452,6 +471,9 @@ static int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi, ml_work->flags = flags; ml_work->sbi = sbi; ml_work->wait_queue = &mdi->wait_queue; + mutex_lock(&mdi->mutex); + kref_get(&mdi->ref); + mutex_unlock(&mdi->mutex); INIT_WORK(&ml_work->work, merge_lookup_work_func); schedule_work(&ml_work->work); @@ -680,6 +702,8 @@ int init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi, mdi->ctime = jiffies; mdi->type = DT_UNKNOWN; + kref_init(&mdi->ref); + mutex_init(&mdi->mutex); mdi->work_count = 0; mutex_init(&mdi->work_lock); init_waitqueue_head(&mdi->wait_queue); @@ -755,7 +779,7 @@ struct dentry *hmdfs_lookup_merge(struct inode *parent_inode, child_dentry, NULL); ret_dentry = d_splice_alias(child_inode, child_dentry); if (IS_ERR(ret_dentry)) { - clear_comrades(child_dentry); + merge_dentry_info_put(hmdfs_dm(child_dentry)); err = PTR_ERR(ret_dentry); goto out; } -- Gitee