diff options
Diffstat (limited to 'fs/aufs/vdir.c')
-rw-r--r-- | fs/aufs/vdir.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c index feddcc204..e6e3a1eaa 100644 --- a/fs/aufs/vdir.c +++ b/fs/aufs/vdir.c @@ -97,7 +97,7 @@ static void au_nhash_wh_do_free(struct hlist_head *head) struct hlist_node *node; hlist_for_each_entry_safe(pos, node, head, wh_hash) - kfree(pos); + au_delayed_kfree(pos); } static void au_nhash_de_do_free(struct hlist_head *head) @@ -106,7 +106,7 @@ static void au_nhash_de_do_free(struct hlist_head *head) struct hlist_node *node; hlist_for_each_entry_safe(pos, node, head, hash) - au_cache_free_vdir_dehstr(pos); + au_cache_dfree_vdir_dehstr(pos); } static void au_nhash_do_free(struct au_nhash *nhash, @@ -124,7 +124,7 @@ static void au_nhash_do_free(struct au_nhash *nhash, nhash_count(head); free(head++); } - kfree(nhash->nh_head); + au_delayed_kfree(nhash->nh_head); } void au_nhash_wh_free(struct au_nhash *whlist) @@ -167,6 +167,8 @@ static struct hlist_head *au_name_hash(struct au_nhash *nhash, AuDebugOn(!nhash->nh_num || !nhash->nh_head); v = 0; + if (len > 8) + len = 8; while (len--) v += *name++; /* v = hash_long(v, magic_bit); */ @@ -335,15 +337,23 @@ out: /* ---------------------------------------------------------------------- */ -void au_vdir_free(struct au_vdir *vdir) +void au_vdir_free(struct au_vdir *vdir, int atonce) { unsigned char **deblk; deblk = vdir->vd_deblk; - while (vdir->vd_nblk--) - kfree(*deblk++); - kfree(vdir->vd_deblk); - au_cache_free_vdir(vdir); + if (!atonce) { + while (vdir->vd_nblk--) + au_delayed_kfree(*deblk++); + au_delayed_kfree(vdir->vd_deblk); + au_cache_dfree_vdir(vdir); + } else { + /* not delayed */ + while (vdir->vd_nblk--) + kfree(*deblk++); + kfree(vdir->vd_deblk); + au_cache_free_vdir(vdir); + } } static struct au_vdir *alloc_vdir(struct file *file) @@ -377,10 +387,10 @@ static struct au_vdir *alloc_vdir(struct file *file) if (!err) return vdir; /* success */ - kfree(vdir->vd_deblk); + au_delayed_kfree(vdir->vd_deblk); out_free: - au_cache_free_vdir(vdir); + au_cache_dfree_vdir(vdir); out: vdir = ERR_PTR(err); return vdir; @@ -392,7 +402,7 @@ static int reinit_vdir(struct au_vdir *vdir) union au_vdir_deblk_p p, deblk_end; while (vdir->vd_nblk > 1) { - kfree(vdir->vd_deblk[vdir->vd_nblk - 1]); + au_delayed_kfree(vdir->vd_deblk[vdir->vd_nblk - 1]); /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ vdir->vd_nblk--; } @@ -523,7 +533,7 @@ static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir, } } - free_page((unsigned long)o); + au_delayed_free_page((unsigned long)o); out: AuTraceErr(err); @@ -624,6 +634,7 @@ static int read_vdir(struct file *file, int may_read) err = 0; inode = file_inode(file); IMustLock(inode); + IiMustWriteLock(inode); SiMustAnyLock(inode->i_sb); allocated = NULL; @@ -661,7 +672,7 @@ static int read_vdir(struct file *file, int may_read) if (allocated) au_set_ivdir(inode, allocated); } else if (allocated) - au_vdir_free(allocated); + au_vdir_free(allocated, /*atonce*/0); out: return err; @@ -755,7 +766,7 @@ int au_vdir_init(struct file *file) if (allocated) au_set_fvdir_cache(file, allocated); } else if (allocated) - au_vdir_free(allocated); + au_vdir_free(allocated, /*atonce*/0); out: return err; |