int au_refresh_hinode_self(struct inode *inode, int do_attr) { int err, e; aufs_bindex_t bindex, new_bindex; unsigned char update; struct au_hinode *p, *q, tmp; struct super_block *sb; struct au_iinfo *iinfo; IiMustWriteLock(inode); update = 0; sb = inode->i_sb; iinfo = au_ii(inode); err = au_ii_realloc(iinfo, au_sbend(sb) + 1); if (unlikely(err)) goto out; p = iinfo->ii_hinode + iinfo->ii_bstart; err = 0; for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++, p++) { if (!p->hi_inode) continue; new_bindex = au_br_index(sb, p->hi_id); if (new_bindex == bindex) continue; if (new_bindex < 0) { update = 1; au_hiput(p); p->hi_inode = NULL; continue; } if (new_bindex < iinfo->ii_bstart) iinfo->ii_bstart = new_bindex; if (iinfo->ii_bend < new_bindex) iinfo->ii_bend = new_bindex; /* swap two lower inode, and loop again */ q = iinfo->ii_hinode + new_bindex; tmp = *q; *q = *p; *p = tmp; if (tmp.hi_inode) { bindex--; p--; } } au_update_ibrange(inode, /*do_put_zero*/0); e = au_dy_irefresh(inode); if (unlikely(e && !err)) err = e; if (do_attr) au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode)); out: return err; }
/* * returns a newly allocated branch. @new_nbranch is a number of branches * after adding a branch. */ static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch, int perm) { struct au_branch *add_branch; struct dentry *root; int err; err = -ENOMEM; root = sb->s_root; add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS); if (unlikely(!add_branch)) goto out; err = au_hnotify_init_br(add_branch, perm); if (unlikely(err)) goto out_br; add_branch->br_wbr = NULL; if (au_br_writable(perm)) { /* may be freed separately at changing the branch permission */ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr), GFP_NOFS); if (unlikely(!add_branch->br_wbr)) goto out_hnotify; } err = au_sbr_realloc(au_sbi(sb), new_nbranch); if (!err) err = au_di_realloc(au_di(root), new_nbranch); if (!err) err = au_ii_realloc(au_ii(root->d_inode), new_nbranch); if (!err) return add_branch; /* success */ kfree(add_branch->br_wbr); out_hnotify: au_hnotify_fin_br(add_branch); out_br: kfree(add_branch); out: return ERR_PTR(err); }
static int au_ii_refresh(struct inode *inode, int *update) { int err, e; umode_t type; aufs_bindex_t bindex, new_bindex; struct super_block *sb; struct au_iinfo *iinfo; struct au_hinode *p, *q, tmp; IiMustWriteLock(inode); *update = 0; sb = inode->i_sb; type = inode->i_mode & S_IFMT; iinfo = au_ii(inode); err = au_ii_realloc(iinfo, au_sbend(sb) + 1); if (unlikely(err)) goto out; AuDebugOn(iinfo->ii_bstart < 0); p = iinfo->ii_hinode + iinfo->ii_bstart; for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++, p++) { if (!p->hi_inode) continue; AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT)); new_bindex = au_br_index(sb, p->hi_id); if (new_bindex == bindex) continue; if (new_bindex < 0) { *update = 1; au_hiput(p); p->hi_inode = NULL; continue; } if (new_bindex < iinfo->ii_bstart) iinfo->ii_bstart = new_bindex; if (iinfo->ii_bend < new_bindex) iinfo->ii_bend = new_bindex; /* swap two lower inode, and loop again */ q = iinfo->ii_hinode + new_bindex; tmp = *q; *q = *p; *p = tmp; if (tmp.hi_inode) { bindex--; p--; } } au_update_ibrange(inode, /*do_put_zero*/0); e = au_dy_irefresh(inode); if (unlikely(e && !err)) err = e; out: AuTraceErr(err); return err; }