CPUA CPUB ocfs2_dentry_convert_worker get 'l_lock'
get 'dentry_attach_lock' interruptted by dio_end_io: dio_end_io dio_bio_end_aio dio_complete dio->end_io ocfs2_dio_end_io ocfs2_rw_unlock ... try to get 'l_lock' but CPUA has got it. try to get 'dentry_attach_lock', but CPUB has got 'dentry_attach_lock', and would not release it. so we need use spin_lock_irqsave for 'dentry_attach_lock' to prevent interruptted by softirq. Signed-off-by: Jun Piao <piao...@huawei.com> Reviewed-by: Alex Chen <alex.c...@huawei.com> --- fs/ocfs2/dcache.c | 14 ++++++++------ fs/ocfs2/dlmglue.c | 14 +++++++------- fs/ocfs2/namei.c | 5 +++-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 2903730..6555fbf 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -230,6 +230,7 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, int ret; struct dentry *alias; struct ocfs2_dentry_lock *dl = dentry->d_fsdata; + unsigned long flags; trace_ocfs2_dentry_attach_lock(dentry->d_name.len, dentry->d_name.name, (unsigned long long)parent_blkno, dl); @@ -309,10 +310,10 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, ocfs2_dentry_lock_res_init(dl, parent_blkno, inode); out_attach: - spin_lock(&dentry_attach_lock); + spin_lock_irqsave(&dentry_attach_lock, flags); dentry->d_fsdata = dl; dl->dl_count++; - spin_unlock(&dentry_attach_lock); + spin_unlock_irqrestore(&dentry_attach_lock, flags); /* * This actually gets us our PRMODE level lock. From now on, @@ -333,9 +334,9 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, if (ret < 0 && !alias) { ocfs2_lock_res_free(&dl->dl_lockres); BUG_ON(dl->dl_count != 1); - spin_lock(&dentry_attach_lock); + spin_lock_irqsave(&dentry_attach_lock, flags); dentry->d_fsdata = NULL; - spin_unlock(&dentry_attach_lock); + spin_unlock_irqrestore(&dentry_attach_lock, flags); kfree(dl); iput(inode); } @@ -379,13 +380,14 @@ void ocfs2_dentry_lock_put(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl) { int unlock = 0; + unsigned long flags; BUG_ON(dl->dl_count == 0); - spin_lock(&dentry_attach_lock); + spin_lock_irqsave(&dentry_attach_lock, flags); dl->dl_count--; unlock = !dl->dl_count; - spin_unlock(&dentry_attach_lock); + spin_unlock_irqrestore(&dentry_attach_lock, flags); if (unlock) ocfs2_drop_dentry_lock(osb, dl); diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 4689940..9bff3d2 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -3801,7 +3801,7 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres); struct ocfs2_inode_info *oi = OCFS2_I(dl->dl_inode); struct dentry *dentry; - unsigned long flags; + unsigned long flags, d_flags; int extra_ref = 0; /* @@ -3831,13 +3831,13 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, * flag. */ spin_lock_irqsave(&lockres->l_lock, flags); - spin_lock(&dentry_attach_lock); + spin_lock_irqsave(&dentry_attach_lock, d_flags); if (!(lockres->l_flags & OCFS2_LOCK_FREEING) && dl->dl_count) { dl->dl_count++; extra_ref = 1; } - spin_unlock(&dentry_attach_lock); + spin_unlock_irqrestore(&dentry_attach_lock, d_flags); spin_unlock_irqrestore(&lockres->l_lock, flags); mlog(0, "extra_ref = %d\n", extra_ref); @@ -3850,13 +3850,13 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, if (!extra_ref) return UNBLOCK_CONTINUE; - spin_lock(&dentry_attach_lock); + spin_lock_irqsave(&dentry_attach_lock, d_flags); while (1) { dentry = ocfs2_find_local_alias(dl->dl_inode, dl->dl_parent_blkno, 1); if (!dentry) break; - spin_unlock(&dentry_attach_lock); + spin_unlock_irqrestore(&dentry_attach_lock, d_flags); if (S_ISDIR(dl->dl_inode->i_mode)) shrink_dcache_parent(dentry); @@ -3874,9 +3874,9 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, d_delete(dentry); dput(dentry); - spin_lock(&dentry_attach_lock); + spin_lock_irqsave(&dentry_attach_lock, d_flags); } - spin_unlock(&dentry_attach_lock); + spin_unlock_irqrestore(&dentry_attach_lock, d_flags); /* * If we are the last holder of this dentry lock, there is no diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 3b0a10d..a17454e 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -223,13 +223,14 @@ static void ocfs2_cleanup_add_entry_failure(struct ocfs2_super *osb, struct dentry *dentry, struct inode *inode) { struct ocfs2_dentry_lock *dl = dentry->d_fsdata; + unsigned long flags; ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); ocfs2_lock_res_free(&dl->dl_lockres); BUG_ON(dl->dl_count != 1); - spin_lock(&dentry_attach_lock); + spin_lock_irqsave(&dentry_attach_lock, flags); dentry->d_fsdata = NULL; - spin_unlock(&dentry_attach_lock); + spin_unlock_irqrestore(&dentry_attach_lock, flags); kfree(dl); iput(inode); } -- _______________________________________________ Ocfs2-devel mailing list Ocfs2-devel@oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel