Commit 0ba3f959 authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: writable branch 3/3, diropq



The functions to create/delete the opaque directory marker (called
'diropq') on the added writable branch.
For details, refer to previous commit.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 59ad1975
......@@ -12,6 +12,13 @@
#define WH_MASK 0444
/*
* If a directory contains this file, then it is opaque. We start with the
* .wh. flag so that it is blocked by lookup.
*/
static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
sizeof(AUFS_WH_DIROPQ) - 1);
/*
* generate whiteout name, which is NOT terminated by NULL.
* @name: original d_name.name
......@@ -83,6 +90,20 @@ out:
return err;
}
/*
* test if the @h_dentry sets opaque or not.
*/
int au_diropq_test(struct dentry *h_dentry)
{
int err;
struct inode *h_dir;
h_dir = d_inode(h_dentry);
err = au_wh_test(h_dentry, &diropq_name,
au_test_h_perm_sio(h_dir, MAY_EXEC));
return err;
}
/* ---------------------------------------------------------------------- */
/*
* functions for removing a whiteout
......@@ -545,6 +566,86 @@ out:
/* ---------------------------------------------------------------------- */
/*
* create or remove the diropq.
*/
static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
unsigned int flags)
{
struct dentry *opq_dentry, *h_dentry;
struct super_block *sb;
struct au_branch *br;
int err;
sb = dentry->d_sb;
br = au_sbr(sb, bindex);
h_dentry = au_h_dptr(dentry, bindex);
opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
if (IS_ERR(opq_dentry))
goto out;
if (au_ftest_diropq(flags, CREATE)) {
err = link_or_create_wh(sb, bindex, opq_dentry);
if (!err) {
au_set_dbdiropq(dentry, bindex);
goto out; /* success */
}
} else {
struct path tmp = {
.dentry = opq_dentry,
.mnt = au_br_mnt(br)
};
err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp);
if (!err)
au_set_dbdiropq(dentry, -1);
}
dput(opq_dentry);
opq_dentry = ERR_PTR(err);
out:
return opq_dentry;
}
struct do_diropq_args {
struct dentry **errp;
struct dentry *dentry;
aufs_bindex_t bindex;
unsigned int flags;
};
static void call_do_diropq(void *args)
{
struct do_diropq_args *a = args;
*a->errp = do_diropq(a->dentry, a->bindex, a->flags);
}
struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
unsigned int flags)
{
struct dentry *diropq, *h_dentry;
h_dentry = au_h_dptr(dentry, bindex);
if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE))
diropq = do_diropq(dentry, bindex, flags);
else {
int wkq_err;
struct do_diropq_args args = {
.errp = &diropq,
.dentry = dentry,
.bindex = bindex,
.flags = flags
};
wkq_err = au_wkq_wait(call_do_diropq, &args);
if (unlikely(wkq_err))
diropq = ERR_PTR(wkq_err);
}
return diropq;
}
/* ---------------------------------------------------------------------- */
/*
* lookup whiteout dentry.
* @h_parent: lower parent dentry which must exist and be locked
......
......@@ -17,6 +17,7 @@ struct qstr;
int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
struct dentry;
int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio);
int au_diropq_test(struct dentry *h_dentry);
struct inode;
struct path;
int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
......@@ -25,10 +26,33 @@ struct au_branch;
struct super_block;
int au_wh_init(struct au_branch *br, struct super_block *sb);
/* diropq flags */
#define AuDiropq_CREATE 1
#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
#define au_fset_diropq(flags, name) \
do { (flags) |= AuDiropq_##name; } while (0)
#define au_fclr_diropq(flags, name) \
do { (flags) &= ~AuDiropq_##name; } while (0)
struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
unsigned int flags);
struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
struct au_branch *br);
struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
struct dentry *h_parent);
/* ---------------------------------------------------------------------- */
static inline struct dentry *au_diropq_create(struct dentry *dentry,
aufs_bindex_t bindex)
{
return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
}
static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
{
return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
}
#endif /* __KERNEL__ */
#endif /* __AUFS_WHOUT_H__ */
......@@ -81,6 +81,9 @@ typedef int16_t aufs_bindex_t;
#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment