diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-09-11 12:58:59 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-09-11 12:58:59 -0300 |
commit | 0520a938e11c34a5ffc422b9316b85e294b0fbb2 (patch) | |
tree | 9e44592eccb90ed2d2b3a893fb602e4ca894f695 /fs/aufs | |
parent | 273d4428f8c4cc94c9598f8bcc006ec2e8c654ea (diff) |
Linux-libre 4.7.3-gnupck-4.7.3-gnu
Diffstat (limited to 'fs/aufs')
-rw-r--r-- | fs/aufs/branch.c | 15 | ||||
-rw-r--r-- | fs/aufs/dbgaufs.c | 3 | ||||
-rw-r--r-- | fs/aufs/dcsub.c | 3 | ||||
-rw-r--r-- | fs/aufs/dentry.c | 8 | ||||
-rw-r--r-- | fs/aufs/dentry.h | 2 | ||||
-rw-r--r-- | fs/aufs/dinfo.c | 5 | ||||
-rw-r--r-- | fs/aufs/file.c | 12 | ||||
-rw-r--r-- | fs/aufs/file.h | 2 | ||||
-rw-r--r-- | fs/aufs/finfo.c | 4 | ||||
-rw-r--r-- | fs/aufs/iinfo.c | 5 | ||||
-rw-r--r-- | fs/aufs/inode.c | 6 | ||||
-rw-r--r-- | fs/aufs/inode.h | 2 | ||||
-rw-r--r-- | fs/aufs/loop.c | 3 | ||||
-rw-r--r-- | fs/aufs/module.c | 60 | ||||
-rw-r--r-- | fs/aufs/module.h | 14 | ||||
-rw-r--r-- | fs/aufs/sbinfo.c | 5 | ||||
-rw-r--r-- | fs/aufs/super.h | 2 | ||||
-rw-r--r-- | fs/aufs/vdir.c | 11 |
18 files changed, 120 insertions, 42 deletions
diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c index 80b018f57..3bfbe5b51 100644 --- a/fs/aufs/branch.c +++ b/fs/aufs/branch.c @@ -141,12 +141,12 @@ static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch, goto out_wbr; } - err = au_sbr_realloc(au_sbi(sb), new_nbranch); + err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0); if (!err) - err = au_di_realloc(au_di(root), new_nbranch); + err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0); if (!err) { inode = d_inode(root); - err = au_hinode_realloc(au_ii(inode), new_nbranch); + err = au_hinode_realloc(au_ii(inode), new_nbranch, /*may_shrink*/0); } if (!err) return add_branch; /* success */ @@ -890,7 +890,8 @@ static void au_br_do_del_brp(struct au_sbinfo *sbinfo, sbinfo->si_branch[0 + bbot] = NULL; sbinfo->si_bbot--; - p = krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST); + p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST, + /*may_shrink*/1); if (p) sbinfo->si_branch = p; /* harmless error */ @@ -909,7 +910,8 @@ static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex, /* au_h_dentry_init(au_hdentry(dinfo, bbot); */ dinfo->di_bbot--; - p = krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST); + p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST, + /*may_shrink*/1); if (p) dinfo->di_hdentry = p; /* harmless error */ @@ -928,7 +930,8 @@ static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex, /* au_hinode_init(au_hinode(iinfo, bbot)); */ iinfo->ii_bbot--; - p = krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST); + p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST, + /*may_shrink*/1); if (p) iinfo->ii_hinode = p; /* harmless error */ diff --git a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c index f85a813a4..4db01e853 100644 --- a/fs/aufs/dbgaufs.c +++ b/fs/aufs/dbgaufs.c @@ -256,7 +256,10 @@ void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) for (; bindex <= bbot; bindex++) { br = au_sbr(sb, bindex); xi = &br->br_xino; + /* debugfs acquires the parent i_mutex */ + lockdep_off(); debugfs_remove(xi->xi_dbgaufs); + lockdep_on(); xi->xi_dbgaufs = NULL; } } diff --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c index 09bc36af7..5d4639838 100644 --- a/fs/aufs/dcsub.c +++ b/fs/aufs/dcsub.c @@ -69,7 +69,8 @@ static int au_dpages_append(struct au_dcsub_pages *dpages, err = -ENOMEM; sz = dpages->ndpage * sizeof(*dpages->dpages); p = au_kzrealloc(dpages->dpages, sz, - sz + sizeof(*dpages->dpages), gfp); + sz + sizeof(*dpages->dpages), gfp, + /*may_shrink*/0); if (unlikely(!p)) goto out; diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c index 51af2cc72..5eb4f3620 100644 --- a/fs/aufs/dentry.c +++ b/fs/aufs/dentry.c @@ -36,7 +36,7 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry, br = au_sbr(dentry->d_sb, bindex); wh_able = !!au_br_whable(br->br_perm); if (wh_able) - wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/0); + wh_found = au_wh_test(h_parent, wh_name, ignore_perm); h_dentry = ERR_PTR(wh_found); if (!wh_found) goto real_lookup; @@ -701,7 +701,7 @@ void au_refresh_dop(struct dentry *dentry, int force_reval) int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) { - int err, ebrange; + int err, ebrange, nbr; unsigned int sigen; struct au_dinfo *dinfo, *tmp; struct super_block *sb; @@ -717,8 +717,9 @@ int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) if (unlikely(err)) goto out; + nbr = au_sbbot(sb) + 1; dinfo = au_di(dentry); - err = au_di_realloc(dinfo, au_sbbot(sb) + 1); + err = au_di_realloc(dinfo, nbr, /*may_shrink*/0); if (unlikely(err)) goto out; ebrange = au_dbrange_test(dentry); @@ -761,6 +762,7 @@ int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) au_dbg_verify_dinode(dentry); AuTraceErr(err); } + au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */ au_rw_write_unlock(&tmp->di_rwsem); au_di_free(tmp); if (unlikely(err)) diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h index dc027191c..01211d220 100644 --- a/fs/aufs/dentry.h +++ b/fs/aufs/dentry.h @@ -66,7 +66,7 @@ void au_di_swap(struct au_dinfo *a, struct au_dinfo *b); void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src); int au_di_init(struct dentry *dentry); void au_di_fin(struct dentry *dentry); -int au_di_realloc(struct au_dinfo *dinfo, int nbr); +int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink); void di_read_lock(struct dentry *d, int flags, unsigned int lsc); void di_read_unlock(struct dentry *d, int flags); diff --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c index 361e86142..2626c0cca 100644 --- a/fs/aufs/dinfo.c +++ b/fs/aufs/dinfo.c @@ -129,7 +129,7 @@ void au_di_fin(struct dentry *dentry) au_di_free(dinfo); } -int au_di_realloc(struct au_dinfo *dinfo, int nbr) +int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink) { int err, sz; struct au_hdentry *hdp; @@ -140,7 +140,8 @@ int au_di_realloc(struct au_dinfo *dinfo, int nbr) sz = sizeof(*hdp) * (dinfo->di_bbot + 1); if (!sz) sz = sizeof(*hdp); - hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS); + hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS, + may_shrink); if (hdp) { dinfo->di_hdentry = hdp; err = 0; diff --git a/fs/aufs/file.c b/fs/aufs/file.c index 429b56840..8d5ca6f7f 100644 --- a/fs/aufs/file.c +++ b/fs/aufs/file.c @@ -655,23 +655,26 @@ static void au_do_refresh_dir(struct file *file) */ static int refresh_file(struct file *file, int (*reopen)(struct file *file)) { - int err, need_reopen; + int err, need_reopen, nbr; aufs_bindex_t bbot, bindex; struct dentry *dentry; + struct super_block *sb; struct au_finfo *finfo; struct au_hfile *hfile; dentry = file->f_path.dentry; + sb = dentry->d_sb; + nbr = au_sbbot(sb) + 1; finfo = au_fi(file); if (!finfo->fi_hdir) { hfile = &finfo->fi_htop; AuDebugOn(!hfile->hf_file); - bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id); + bindex = au_br_index(sb, hfile->hf_br->br_id); AuDebugOn(bindex < 0); if (bindex != finfo->fi_btop) au_set_fbtop(file, bindex); } else { - err = au_fidir_realloc(finfo, au_sbbot(dentry->d_sb) + 1); + err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0); if (unlikely(err)) goto out; au_do_refresh_dir(file); @@ -681,6 +684,9 @@ static int refresh_file(struct file *file, int (*reopen)(struct file *file)) need_reopen = 1; if (!au_test_mmapped(file)) err = au_file_refresh_by_inode(file, &need_reopen); + if (finfo->fi_hdir) + /* harmless if err */ + au_fidir_realloc(finfo, nbr, /*may_shrink*/1); if (!err && need_reopen && !d_unlinked(dentry)) err = reopen(file); if (!err) { diff --git a/fs/aufs/file.h b/fs/aufs/file.h index 6ecd0df33..f53b381a7 100644 --- a/fs/aufs/file.h +++ b/fs/aufs/file.h @@ -110,7 +110,7 @@ void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, void au_update_figen(struct file *file); struct au_fidir *au_fidir_alloc(struct super_block *sb); -int au_fidir_realloc(struct au_finfo *finfo, int nbr); +int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink); void au_fi_init_once(void *_fi); void au_finfo_fin(struct file *file, int atonce); diff --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c index e0c16b2f1..0f016ed54 100644 --- a/fs/aufs/finfo.c +++ b/fs/aufs/finfo.c @@ -66,7 +66,7 @@ struct au_fidir *au_fidir_alloc(struct super_block *sb) return fidir; } -int au_fidir_realloc(struct au_finfo *finfo, int nbr) +int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink) { int err; struct au_fidir *fidir, *p; @@ -77,7 +77,7 @@ int au_fidir_realloc(struct au_finfo *finfo, int nbr) err = -ENOMEM; p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr), - GFP_NOFS); + GFP_NOFS, may_shrink); if (p) { p->fd_nent = nbr; finfo->fi_hdir = p; diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c index c83db695d..975cff389 100644 --- a/fs/aufs/iinfo.c +++ b/fs/aufs/iinfo.c @@ -205,7 +205,7 @@ int au_iinfo_init(struct inode *inode) return -ENOMEM; } -int au_hinode_realloc(struct au_iinfo *iinfo, int nbr) +int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink) { int err, i; struct au_hinode *hip; @@ -213,7 +213,8 @@ int au_hinode_realloc(struct au_iinfo *iinfo, int nbr) AuRwMustWriteLock(&iinfo->ii_rwsem); err = -ENOMEM; - hip = krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS); + hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS, + may_shrink); if (hip) { iinfo->ii_hinode = hip; i = iinfo->ii_bbot + 1; diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c index a4b994e8c..8f7446df6 100644 --- a/fs/aufs/inode.c +++ b/fs/aufs/inode.c @@ -27,7 +27,7 @@ static void au_refresh_hinode_attr(struct inode *inode, int do_version) static int au_ii_refresh(struct inode *inode, int *update) { - int err, e; + int err, e, nbr; umode_t type; aufs_bindex_t bindex, new_bindex; struct super_block *sb; @@ -39,9 +39,10 @@ static int au_ii_refresh(struct inode *inode, int *update) *update = 0; sb = inode->i_sb; + nbr = au_sbbot(sb) + 1; type = inode->i_mode & S_IFMT; iinfo = au_ii(inode); - err = au_hinode_realloc(iinfo, au_sbbot(sb) + 1); + err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0); if (unlikely(err)) goto out; @@ -79,6 +80,7 @@ static int au_ii_refresh(struct inode *inode, int *update) } } au_update_ibrange(inode, /*do_put_zero*/0); + au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */ e = au_dy_irefresh(inode); if (unlikely(e && !err)) err = e; diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h index 60995c054..33d9f5e8f 100644 --- a/fs/aufs/inode.h +++ b/fs/aufs/inode.h @@ -258,7 +258,7 @@ void au_icntnr_init_once(void *_c); void au_hinode_init(struct au_hinode *hinode); int au_iinfo_init(struct inode *inode); void au_iinfo_fin(struct inode *inode); -int au_hinode_realloc(struct au_iinfo *iinfo, int nbr); +int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink); #ifdef CONFIG_PROC_FS /* plink.c */ diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c index e92a34599..c3ca50f16 100644 --- a/fs/aufs/loop.c +++ b/fs/aufs/loop.c @@ -91,7 +91,8 @@ void au_warn_loopback(struct super_block *h_sb) new_nelem = au_warn_loopback_nelem + au_warn_loopback_step; a = au_kzrealloc(au_warn_loopback_array, au_warn_loopback_nelem * sizeof(unsigned long), - new_nelem * sizeof(unsigned long), GFP_ATOMIC); + new_nelem * sizeof(unsigned long), GFP_ATOMIC, + /*may_shrink*/0); if (a) { au_warn_loopback_nelem = new_nelem; au_warn_loopback_array = a; diff --git a/fs/aufs/module.c b/fs/aufs/module.c index ede9a232a..5092b4bd6 100644 --- a/fs/aufs/module.c +++ b/fs/aufs/module.c @@ -10,13 +10,57 @@ #include <linux/seq_file.h> #include "aufs.h" -void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp) +/* shrinkable realloc */ +void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink) { - if (new_sz <= nused) - return p; + size_t sz; + int diff; + + sz = 0; + diff = -1; + if (p) { +#if 0 /* unused */ + if (!new_sz) { + au_delayed_kfree(p); + p = NULL; + goto out; + } +#else + AuDebugOn(!new_sz); +#endif + sz = ksize(p); + diff = au_kmidx_sub(sz, new_sz); + } + if (sz && !diff) + goto out; + + if (sz < new_sz) + /* expand or SLOB */ + p = krealloc(p, new_sz, gfp); + else if (new_sz < sz && may_shrink) { + /* shrink */ + void *q; + + q = kmalloc(new_sz, gfp); + if (q) { + if (p) { + memcpy(q, p, new_sz); + au_delayed_kfree(p); + } + p = q; + } else + p = NULL; + } - p = krealloc(p, new_sz, gfp); - if (p) +out: + return p; +} + +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, + int may_shrink) +{ + p = au_krealloc(p, new_sz, gfp, may_shrink); + if (p && new_sz > nused) memset(p + nused, 0, new_sz - nused); return p; } @@ -38,9 +82,9 @@ static void au_do_dfree(struct work_struct *work __maybe_unused) head = &au_dfree.cache[AuCache_##idx].llist; \ node = llist_del_all(head); \ for (; node; node = next) { \ - struct au_##name *p = \ - p = llist_entry(node, struct au_##name, \ - lnode); \ + struct au_##name *p \ + = llist_entry(node, struct au_##name, \ + lnode); \ next = llist_next(node); \ au_cache_free_##name(p); \ } \ diff --git a/fs/aufs/module.h b/fs/aufs/module.h index 681dc75f5..6f968ba41 100644 --- a/fs/aufs/module.h +++ b/fs/aufs/module.h @@ -25,7 +25,19 @@ extern bool au_userns; extern int au_dir_roflags; -void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp); +void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink); +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, + int may_shrink); + +static inline int au_kmidx_sub(size_t sz, size_t new_sz) +{ +#ifndef CONFIG_SLOB + return kmalloc_index(sz) - kmalloc_index(new_sz); +#else + return -1; /* SLOB is untested */ +#endif +} + int au_seq_path(struct seq_file *seq, struct path *path); #ifdef CONFIG_PROC_FS diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c index 25f60549c..e113b5119 100644 --- a/fs/aufs/sbinfo.c +++ b/fs/aufs/sbinfo.c @@ -118,7 +118,7 @@ out: return err; } -int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr) +int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink) { int err, sz; struct au_branch **brp; @@ -129,7 +129,8 @@ int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr) sz = sizeof(*brp) * (sbinfo->si_bbot + 1); if (unlikely(!sz)) sz = sizeof(*brp); - brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS); + brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS, + may_shrink); if (brp) { sbinfo->si_branch = brp; err = 0; diff --git a/fs/aufs/super.h b/fs/aufs/super.h index b8ca14994..e4ac866e7 100644 --- a/fs/aufs/super.h +++ b/fs/aufs/super.h @@ -266,7 +266,7 @@ void au_iarray_free(struct inode **a, unsigned long long max); /* sbinfo.c */ void au_si_free(struct kobject *kobj); int au_si_alloc(struct super_block *sb); -int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr); +int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink); unsigned int au_sigen_inc(struct super_block *sb); aufs_bindex_t au_new_br_id(struct super_block *sb); diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c index e6e3a1eaa..b2eb4c058 100644 --- a/fs/aufs/vdir.c +++ b/fs/aufs/vdir.c @@ -266,8 +266,8 @@ static int append_deblk(struct au_vdir *vdir) unsigned char **o; err = -ENOMEM; - o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1), - GFP_NOFS); + o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1), + GFP_NOFS, /*may_shrink*/0); if (unlikely(!o)) goto out; @@ -690,8 +690,8 @@ static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) if (tgt->vd_nblk < src->vd_nblk) { unsigned char **p; - p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk, - GFP_NOFS); + p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk, + GFP_NOFS, /*may_shrink*/0); if (unlikely(!p)) goto out; tgt->vd_deblk = p; @@ -701,7 +701,8 @@ static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) unsigned char *p; tgt->vd_deblk_sz = deblk_sz; - p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS); + p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS, + /*may_shrink*/1); if (unlikely(!p)) goto out; tgt->vd_deblk[0] = p; |