I made a patch for disabling whiteout-lookup in the rightmost ro-branch. This
patch too prohibits the lookup/rename of whiteouts in unionfs_create() in the
case of an ro-branch.
This enables us to use an ro-nfs rightmost branch, which is an common use-case
for some users of unionfs.
Am Freitag, 16. Dezember 2005 08:50 schrieb [EMAIL PROTECTED]:
> > While I was thinking about Wilhelm's question, I've got an idea of new
> > option "dirs=<branch>=ro_wh".
> > Currently these options are 'ro' and 'rw'. A 'ro_wh' option is
> > perfectly equivalent to current 'ro'. But the meaning of 'ro' option
> > changes. In case of 'ro', unionfs does not lookup a whiteout entry, but
> > 'ro_wh' does.
>
> I have tried, here is a patch.
> This is for simple lookup and unionctl, not including unionfs inode
> operations (unionfs_create, etc.).
>
>
> Junjiro Okajima
>
>
> diff -rup ./unionfs-20051130-1554.orig/branchman.c
> ./unionfs-20051130-1554/branchman.c ---
> ./unionfs-20051130-1554.orig/branchman.c 2005-12-01 05:54:06.000000000
> +0900 +++ ./unionfs-20051130-1554/branchman.c 2005-12-16 16:29:50.000000000
> +0900 @@ -211,7 +211,7 @@ int unionfs_ioctl_addbranch(struct inode
> goto out;
>
> err = -EINVAL;
> - if (addargs->ab_perms & ~(MAY_READ | MAY_WRITE))
> + if (addargs->ab_perms & ~(MAY_READ | MAY_WRITE | MAY_WHITEOUT))
> goto out;
> if (!(addargs->ab_perms & MAY_READ))
> goto out;
> @@ -514,7 +514,7 @@ int unionfs_ioctl_rdwrbranch(struct inod
> if (rdwrargs->rwb_branch < 0
>
> || (rdwrargs->rwb_branch > (sbend(inode->i_sb) + 1)))
>
> goto out;
> - if (rdwrargs->rwb_perms & ~(MAY_READ | MAY_WRITE))
> + if (rdwrargs->rwb_perms & ~(MAY_READ | MAY_WRITE | MAY_WHITEOUT))
> goto out;
> if (!(rdwrargs->rwb_perms & MAY_READ))
> goto out;
> diff -rup ./unionfs-20051130-1554.orig/lookup.c
> ./unionfs-20051130-1554/lookup.c ---
> ./unionfs-20051130-1554.orig/lookup.c 2005-12-01 05:54:06.000000000 +0900
> +++ ./unionfs-20051130-1554/lookup.c 2005-12-16 16:29:50.000000000 +0900 @@
> -41,7 +41,8 @@ struct dentry *unionfs_lookup_backend(st
> int opaque;
> char *whname = NULL;
> const char *name;
> - int namelen;
> + int namelen, whlen;
> + struct super_block *sb;
>
> print_entry("mode = %d", lookupmode);
> PASSERT(dentry);
> @@ -82,6 +83,12 @@ struct dentry *unionfs_lookup_backend(st
> err = -EPERM;
> goto out_free;
> }
> + whname = get_whname(name, namelen, &whlen);
> + if (IS_ERR(whname)) {
> + err = PTR_ERR(whname);
> + whname = NULL;
> + goto out_free;
> + }
>
> /* must initialize dentry operations */
> dentry->d_op = &unionfs_dops;
> @@ -91,6 +98,7 @@ struct dentry *unionfs_lookup_backend(st
> bend = dbend(parent_dentry);
> bopaque = dbopaque(parent_dentry);
> ASSERT(bstart >= 0);
> + sb = dentry->d_sb;
>
> /* It would be ideal if we could convert partial lookups to only have
> * to do this work when they really need to. It could probably improve
> @@ -119,44 +127,37 @@ struct dentry *unionfs_lookup_backend(st
> if (!S_ISDIR(hidden_dir_dentry->d_inode->i_mode))
> continue;
>
> - /* Reuse the whiteout name because its value doesn't change. */
> - if (!whname) {
> - whname = KMALLOC(namelen + 5, GFP_UNIONFS);
> - if (!whname) {
> - err = -ENOMEM;
> + if (branchperms(sb, bindex) & (MAY_WRITE | MAY_WHITEOUT)) {
> + /* check if whiteout exists in this branch: lookup
> .wh.foo */
> + wh_hidden_dentry = LOOKUP_ONE_LEN(whname,
> hidden_dir_dentry,
> + whlen);
> + if (IS_ERR(wh_hidden_dentry)) {
> + err = PTR_ERR(wh_hidden_dentry);
> goto out_free;
> }
> - strcpy(whname, WHPFX);
> - strncat(whname, name, namelen);
> - whname[WHLEN + namelen] = '\0';
> - }
>
> - /* check if whiteout exists in this branch: lookup .wh.foo */
> - wh_hidden_dentry = LOOKUP_ONE_LEN(whname, hidden_dir_dentry,
> - namelen + WHLEN);
> - if (IS_ERR(wh_hidden_dentry)) {
> - err = PTR_ERR(wh_hidden_dentry);
> - goto out_free;
> - }
> + if (wh_hidden_dentry->d_inode) {
> + DPUT(wh_hidden_dentry);
> + /* We found a whiteout so lets give up. */
> + fist_dprint(8, "whiteout found in %d\n",
> bindex);
> + if (S_ISREG(wh_hidden_dentry->d_inode->i_mode))
> {
> + set_dbend(dentry, bindex);
> + set_dbopaque(dentry, bindex);
> + break;
> + }
> + err = -EIO;
> + printk(KERN_NOTICE "EIO: Invalid whiteout entry
> type"
> + " %d.\n",
> wh_hidden_dentry->d_inode->i_mode);
> + goto out_free;
> + }
>
> - if (wh_hidden_dentry->d_inode) {
> DPUT(wh_hidden_dentry);
> - /* We found a whiteout so lets give up. */
> - fist_dprint(8, "whiteout found in %d\n", bindex);
> - if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) {
> - set_dbend(dentry, bindex);
> - set_dbopaque(dentry, bindex);
> - break;
> - }
> - err = -EIO;
> - printk(KERN_NOTICE "EIO: Invalid whiteout entry type"
> - " %d.\n", wh_hidden_dentry->d_inode->i_mode);
> - goto out_free;
> + wh_hidden_dentry = NULL;
> + } else {
> + fist_dprint(8, "skipped bindex %d(0x%x)\n",
> + bindex, branchperms(sb, bindex));
> }
>
> - DPUT(wh_hidden_dentry);
> - wh_hidden_dentry = NULL;
> -
> /* Now do regular lookup; lookup foo */
> hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry,
> namelen);
> @@ -307,7 +308,7 @@ struct dentry *unionfs_lookup_backend(st
> ASSERT(dbend(dentry) <= sbmax(dentry->d_sb));
> ASSERT(dbstart(dentry) >= 0);
> }
> - KFREE(whname);
> + put_whname(whname);
> fist_print_dentry("OUT unionfs_lookup (parent)", parent_dentry);
> fist_print_dentry("OUT unionfs_lookup (child)", dentry);
> if (locked_parent)
> diff -rup ./unionfs-20051130-1554.orig/main.c
> ./unionfs-20051130-1554/main.c ---
> ./unionfs-20051130-1554.orig/main.c 2005-12-01 05:54:06.000000000 +0900 +++
> ./unionfs-20051130-1554/main.c 2005-12-16 16:29:50.000000000 +0900 @@
> -323,28 +323,31 @@ static int parse_dirs_option(struct supe
> branches = 0;
> while ((name = strsep(&options, ":")) != NULL) {
> int perms;
> - int l;
> + char *p;
>
> if (!*name)
> continue;
>
> branches++;
>
> - /* strip off =rw or =ro if it is specified. */
> - l = strlen(name);
> - if (!strcmp(name + l - 3, "=ro")) {
> - perms = MAY_READ;
> - name[l - 3] = '\0';
> - } else if (!strcmp(name + l - 3, "=rw")) {
> - perms = MAY_READ | MAY_WRITE;
> - name[l - 3] = '\0';
> - } else {
> - perms = MAY_READ | MAY_WRITE;
> + /* strip off =rw|ro|roh/ro_wh if it is specified. */
> + perms = MAY_READ | MAY_WRITE; /* default */
> + p = strchr(name, '=');
> + if (p) {
> + *p++ = '\0';
> + if (!strcmp(p, "ro"))
> + perms = MAY_READ;
> + else if (!strcmp(p, "roh") || !strcmp(p, "ro_wh"))
> + perms = MAY_READ | MAY_WHITEOUT;
> + else if (strcmp(p, "rw"))
> + printk(KERN_WARNING
> + "unionfs: unknown option '%s'\n", p);
> }
>
> - fist_dprint(4, "unionfs: using directory: %s (%c%c)\n",
> + fist_dprint(4, "unionfs: using directory: %s (%c%c%c)\n",
> name, perms & MAY_READ ? 'r' : '-',
> - perms & MAY_WRITE ? 'w' : '-');
> + perms & MAY_WRITE ? 'w' : '-',
> + perms & MAY_WHITEOUT ? 'h' : '-');
>
> err = path_lookup(name, LOOKUP_FOLLOW, &nd);
> RECORD_PATH_LOOKUP(&nd);
> diff -rup ./unionfs-20051130-1554.orig/rename.c
> ./unionfs-20051130-1554/rename.c ---
> ./unionfs-20051130-1554.orig/rename.c 2005-12-01 05:54:06.000000000 +0900
> +++ ./unionfs-20051130-1554/rename.c 2005-12-16 16:29:50.000000000 +0900 @@
> -668,42 +668,6 @@ static int unionfs_rename_all(struct ino
> return err;
> }
>
> -/*
> - * generate whiteout name, which is NOT terminated by NULL.
> - * @name: original d_name.name
> - * @len: original d_name.len
> - * @whlen: length of whname
> - * return value is the whname.
> - * correctly returned value as whname must be freed later.
> - * If an error occurs, returns PTR_ERR.
> - */
> -static inline char *get_whname(const char *name, int len, int *whlen)
> -{
> - char *ret;
> -
> - ASSERT(name && len && whlen);
> -#if 0
> - /* TODO: check the full path length with PATH_MAX */
> - if (len > PAGE_SIZE - WHLEN + 1)
> - return ERR_PTR(-ENAMETOOLONG);
> -#endif
> - ret = __getname();
> - if (!ret)
> - return ERR_PTR(-ENOMEM);
> -
> - memcpy(ret, WHPFX, WHLEN);
> - memcpy(ret + WHLEN, name, len);
> - *whlen = len + WHLEN;
> - ret[*whlen] = '\0';
> -
> - return ret;
> -}
> -
> -static inline void put_whname(char *whname)
> -{
> - __putname(whname);
> -}
> -
> static struct dentry *lookup_whiteout(struct dentry *dentry)
> {
> char *whname;
> diff -rup ./unionfs-20051130-1554.orig/super.c
> ./unionfs-20051130-1554/super.c ---
> ./unionfs-20051130-1554.orig/super.c 2005-12-01 05:54:06.000000000 +0900
> +++ ./unionfs-20051130-1554/super.c 2005-12-16 16:29:50.000000000 +0900 @@
> -452,7 +452,8 @@ static int unionfs_show_options(struct s
> PAGE_SIZE);
> perms = branchperms(sb, bindex);
> seq_printf(m, "%s=%s", hidden_path,
> - perms & MAY_WRITE ? "rw" : "ro");
> + perms & MAY_WRITE ? "rw" :
> + perms & MAY_WHITEOUT ? "roh" : "ro");
> if (bindex != bend) {
> seq_printf(m, ":");
> }
> diff -rup ./unionfs-20051130-1554.orig/unionctl.c
> ./unionfs-20051130-1554/unionctl.c ---
> ./unionfs-20051130-1554.orig/unionctl.c 2005-12-01 05:54:06.000000000
> +0900
> +++ ./unionfs-20051130-1554/unionctl.c 2005-12-16 16:29:50.000000000
> +0900
> @@ -35,6 +35,7 @@
>
> #define MAY_READ 4
> #define MAY_WRITE 2
> +#define MAY_WHITEOUT 32
>
> extern int find_union(const char *path, char **options, char
> **actual_path, int uniononly);
> @@ -59,9 +60,9 @@ void __attribute__ ((__noreturn__)) __us
> fprintf(stderr,
> "ACTION can be --add, --remove, --mode, --list, or
> --query.\nFurther
> arguments depend on ACTION.\n"); fprintf(stderr,
> - "\tunionctl UNION --add [ --before BRANCH | --after BRANCH ] [
> --mode
> (rw|ro) ] DIRECTORY\n"); + "\tunionctl UNION --add [ --before
> BRANCH |
> --after BRANCH ] [ --mode (rw|ro|roh) ] DIRECTORY\n"); fprintf(stderr,
> "\tunionctl UNION --remove BRANCH\n");
> - fprintf(stderr, "\tunionctl UNION --mode BRANCH (rw|ro)\n");
> + fprintf(stderr, "\tunionctl UNION --mode BRANCH (rw|ro|roh)\n");
> fprintf(stderr, "\tunionctl UNION --list\n");
> fprintf(stderr, "\tunionctl FILENAME --query\n");
> fprintf(stderr,
> @@ -69,6 +70,18 @@ void __attribute__ ((__noreturn__)) __us
> exit(EXIT_FAILURE);
> }
>
> +static inline int parse_rw(char *p)
> +{
> + if (strcmp(p, "ro") == 0)
> + return MAY_READ;
> + else if (strcmp(p, "roh") == 0 || strcmp(p, "ro_wh") == 0)
> + return MAY_READ | MAY_WHITEOUT;
> + else if (strcmp(p, "rw") == 0)
> + return MAY_READ | MAY_WRITE;
> + else
> + return 0;
> +}
> +
> static char **parse_options(char *options)
> {
> char **ret = NULL;
> @@ -77,8 +90,7 @@ static char **parse_options(char *option
> char *p;
> char *q;
> char *r;
> - char *s;
> - int l;
> + char *s, *t, *u;
>
> p = options;
> do {
> @@ -107,15 +119,18 @@ static char **parse_options(char *option
> exit(EXIT_FAILURE);
> }
>
> - l = strlen(r);
> - if (((r[l - 1] == 'o') || (r[l - 1] == 'w'))
> - && (r[l - 2] == 'r') && (r[l - 3] == '=')) {
> - r[l - 3] = '\0';
> - branchperms[n - 1] = MAY_READ;
> - if (r[l - 1] == 'w') {
> - branchperms[n - 1] |= MAY_WRITE;
> - }
> + t = strchr(r, '=');
> + u = t+1;
> + if (!t || !u || !*u)
> + goto err;
> + *t = 0;
> + branchperms[n - 1] = parse_rw(u);
> + if (!branchperms[n - 1]) {
> + err:
> + fprintf(stderr, "cannot parse '%s'\n",
> r);
> + exit(EXIT_FAILURE);
> }
> +
> ret[n - 1] = strdup(r);
> ret[n] = NULL;
>
> @@ -162,10 +177,11 @@ static void dump_branches(const char *pr
> int n = 0;
>
> while (branches[n]) {
> - char r, w;
> + char r, w, h;
> r = (branchperms[n] & MAY_READ) ? 'r' : '-';
> w = (branchperms[n] & MAY_WRITE) ? 'w' : '-';
> - printf("%s%s (%c%c)\n", prefix, branches[n], r, w);
> + h = (branchperms[n] & MAY_WHITEOUT) ? 'h' : '-';
> + printf("%s%s (%c%c%c)\n", prefix, branches[n], r, w, h);
> n++;
> }
> }
> @@ -312,14 +328,10 @@ int main(int argc, char *argv[])
> usage();
> }
>
> - if (!strcmp(argv[i], "ro")) {
> - addargs.ab_perms = MAY_READ;
> - } else if (!strcmp(argv[i], "rw")) {
> - addargs.ab_perms =
> - MAY_READ | MAY_WRITE;
> - } else {
> + addargs.ab_perms = parse_rw(argv[i]);
> + if (!addargs.ab_perms) {
> fprintf(stderr,
> - "Valid modes are ro and
> rw you specified: \"%s\"\n",
> + "Valid modes are
> ro/rw/roh you specified: \"%s\"\n",
> argv[i]);
> usage();
> }
> @@ -379,20 +391,15 @@ int main(int argc, char *argv[])
> usage();
> }
>
> - if (!strcmp(argv[4], "ro")) {
> - rdwrargs.rwb_perms = MAY_READ;
> - branchnum = 3;
> - } else if (!strcmp(argv[4], "rw")) {
> - rdwrargs.rwb_perms = MAY_READ | MAY_WRITE;
> - branchnum = 3;
> - } else if (!strcmp(argv[3], "ro")) {
> - rdwrargs.rwb_perms = MAY_READ;
> - branchnum = 4;
> - } else if (!strcmp(argv[3], "rw")) {
> - rdwrargs.rwb_perms = MAY_READ | MAY_WRITE;
> + branchnum = 3;
> + rdwrargs.rwb_perms = parse_rw(argv[4]);
> + if (!rdwrargs.rwb_perms) {
> branchnum = 4;
> - } else {
> - usage();
> + rdwrargs.rwb_perms = parse_rw(argv[3]);
> + if (!rdwrargs.rwb_perms) {
> + usage();
> + exit(EXIT_FAILURE);
> + }
> }
>
> if (realpath(argv[branchnum], resolv_bp) == NULL) {
> @@ -478,13 +485,14 @@ int main(int argc, char *argv[])
> }
>
> for (i = 0; i <= ret; i++) {
> - char r, w;
> + char r, w, h;
> r = (branchperms[i] & MAY_READ) ? 'r' : '-';
> w = (branchperms[i] & MAY_WRITE) ? 'w' : '-';
> + h = (branchperms[i] & MAY_WHITEOUT) ? 'h' : '-';
>
> if (FD_ISSET(i, &branchlist))
> - printf("%s\t%s (%c%c)\n", argv[unionpos],
> - branches[i], r, w);
> + printf("%s\t%s (%c%c%c)\n", argv[unionpos],
> + branches[i], r, w, h);
> }
> break;
> }
> diff -rup ./unionfs-20051130-1554.orig/unionfs.h
> ./unionfs-20051130-1554/unionfs.h ---
> ./unionfs-20051130-1554.orig/unionfs.h 2005-12-01 05:54:06.000000000
> +0900
> +++ ./unionfs-20051130-1554/unionfs.h 2005-12-16 16:29:50.000000000 +0900
> @@ -118,6 +118,20 @@ struct putmap {
> };
>
> /* unionfs super-block data in memory */
> +/*
> + * flags for branchperm.
> + * MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND in linux/fs.h.
> + * MAY_GENERIC is for unionfs_permission() and try linux
> + * generic_permission() or something after the branch i_op->permission()
> + * returned an error.
> + * MAY_GENERIC is set when the branch is marked as "<branch>=rog".
> + * MAY_WHITEOUT is for unionfs_lookup() and try lookup whiteout on
> readonly + * branch.
> + * MAY_HITEOUT is set when the branch is marked as "<branch>=roh".
> + */
> +#define __UNIONFS_PERM_LAST MAY_APPEND
> +//#define MAY_GENERIC (__UNIONFS_PERM_LAST<<1)
> +#define MAY_WHITEOUT (__UNIONFS_PERM_LAST<<2)
> struct unionfs_sb_info {
> int b_end;
>
> @@ -640,7 +654,42 @@ static inline int __is_robranch(struct d
> #define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque"
> #define UNIONFS_DIR_OPAQUE WHPFX UNIONFS_DIR_OPAQUE_NAME
>
> -;
> +/*
> + * generate whiteout name, which is NOT terminated by NULL.
> + * @name: original d_name.name
> + * @len: original d_name.len
> + * @whlen: length of whname
> + * return value is the whname.
> + * correctly returned value as whname must be freed later.
> + * If an error occurs, returns PTR_ERR.
> + */
> +static inline char *get_whname(const char *name, int len, int *whlen)
> +{
> + char *ret;
> +
> + ASSERT(name && len && whlen);
> +#if 0
> + /* TODO: check the full path length with PATH_MAX */
> + if (len > PAGE_SIZE - WHLEN + 1)
> + return ERR_PTR(-ENAMETOOLONG);
> +#endif
> + ret = __getname();
> + if (!ret)
> + return ERR_PTR(-ENOMEM);
> +
> + memcpy(ret, WHPFX, WHLEN);
> + memcpy(ret + WHLEN, name, len);
> + *whlen = len + WHLEN;
> + ret[*whlen] = '\0';
> +
> + return ret;
> +}
> +
> +static inline void put_whname(char *whname)
> +{
> + __putname(whname);
> +}
> +
> /*
> * Defines,structs,and functions for persistant used by kenrel and user
> */
> _______________________________________________
> unionfs mailing list
> [email protected]
> http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs
--
--
Wilhelm Meier
email: [EMAIL PROTECTED]
Only in ./unionfs-20051130-1554-rolast: .tmp_versions
diff -rup ./unionfs-20051130-1554/inode.c ./unionfs-20051130-1554-rolast/inode.c
--- ./unionfs-20051130-1554/inode.c 2005-11-30 21:54:06.000000000 +0100
+++ ./unionfs-20051130-1554-rolast/inode.c 2005-12-21 13:48:19.000000000 +0100
@@ -61,17 +61,19 @@ static int unionfs_create(struct inode *
strncat(name, dentry->d_name.name, dentry->d_name.len);
name[WHLEN + dentry->d_name.len] = '\0';
- whiteout_dentry =
- LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
- dentry->d_name.len + WHLEN);
- if (IS_ERR(whiteout_dentry)) {
- err = PTR_ERR(whiteout_dentry);
- whiteout_dentry = NULL;
- goto out;
+ if (!(is_robranch_super(dentry->d_sb, bstart))) {
+ whiteout_dentry =
+ LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
+ dentry->d_name.len + WHLEN);
+ if (IS_ERR(whiteout_dentry)) {
+ err = PTR_ERR(whiteout_dentry);
+ whiteout_dentry = NULL;
+ goto out;
+ }
+ PASSERT(whiteout_dentry);
}
- PASSERT(whiteout_dentry);
- if (whiteout_dentry->d_inode) {
+ if (whiteout_dentry && whiteout_dentry->d_inode) {
/* .wh.foo has been found. */
/* First truncate it and then rename it to foo (hence having
* the same overall effect as a normal create.
@@ -196,7 +198,8 @@ static int unionfs_create(struct inode *
}
out:
- DPUT(whiteout_dentry);
+ if (whiteout_dentry)
+ DPUT(whiteout_dentry);
KFREE(name);
fist_print_dentry("OUT unionfs_create :", dentry);
@@ -1043,8 +1046,6 @@ struct inode_operations unionfs_main_iop
* Local variables:
* c-basic-offset: 8
* c-comment-only-line-offset: 0
- * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0)
- * (substatement-open . 0) (label . 0) (statement-cont . +))
* indent-tabs-mode: t
* tab-width: 8
* End:
diff -rup ./unionfs-20051130-1554/lookup.c ./unionfs-20051130-1554-rolast/lookup.c
--- ./unionfs-20051130-1554/lookup.c 2005-11-30 21:54:06.000000000 +0100
+++ ./unionfs-20051130-1554-rolast/lookup.c 2005-12-21 13:48:57.000000000 +0100
@@ -118,45 +118,47 @@ struct dentry *unionfs_lookup_backend(st
/* also skip it if the parent isn't a directory. */
if (!S_ISDIR(hidden_dir_dentry->d_inode->i_mode))
continue;
-
- /* Reuse the whiteout name because its value doesn't change. */
- if (!whname) {
- whname = KMALLOC(namelen + 5, GFP_UNIONFS);
+
+ if (bindex < bend) {
+ /* Reuse the whiteout name because its value doesn't change. */
if (!whname) {
- err = -ENOMEM;
+ whname = KMALLOC(namelen + 5, GFP_UNIONFS);
+ if (!whname) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+ strcpy(whname, WHPFX);
+ strncat(whname, name, namelen);
+ whname[WHLEN + namelen] = '\0';
+ }
+
+ /* check if whiteout exists in this branch: lookup .wh.foo */
+ wh_hidden_dentry = LOOKUP_ONE_LEN(whname, hidden_dir_dentry,
+ namelen + WHLEN);
+ if (IS_ERR(wh_hidden_dentry)) {
+ err = PTR_ERR(wh_hidden_dentry);
goto out_free;
}
- strcpy(whname, WHPFX);
- strncat(whname, name, namelen);
- whname[WHLEN + namelen] = '\0';
- }
- /* check if whiteout exists in this branch: lookup .wh.foo */
- wh_hidden_dentry = LOOKUP_ONE_LEN(whname, hidden_dir_dentry,
- namelen + WHLEN);
- if (IS_ERR(wh_hidden_dentry)) {
- err = PTR_ERR(wh_hidden_dentry);
- goto out_free;
- }
+ if (wh_hidden_dentry->d_inode) {
+ DPUT(wh_hidden_dentry);
+ /* We found a whiteout so lets give up. */
+ fist_dprint(8, "whiteout found in %d\n", bindex);
+ if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) {
+ set_dbend(dentry, bindex);
+ set_dbopaque(dentry, bindex);
+ break;
+ }
+ err = -EIO;
+ printk(KERN_NOTICE "EIO: Invalid whiteout entry type"
+ " %d.\n", wh_hidden_dentry->d_inode->i_mode);
+ goto out_free;
+ }
- if (wh_hidden_dentry->d_inode) {
DPUT(wh_hidden_dentry);
- /* We found a whiteout so lets give up. */
- fist_dprint(8, "whiteout found in %d\n", bindex);
- if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) {
- set_dbend(dentry, bindex);
- set_dbopaque(dentry, bindex);
- break;
- }
- err = -EIO;
- printk(KERN_NOTICE "EIO: Invalid whiteout entry type"
- " %d.\n", wh_hidden_dentry->d_inode->i_mode);
- goto out_free;
+ wh_hidden_dentry = NULL;
}
-
- DPUT(wh_hidden_dentry);
- wh_hidden_dentry = NULL;
-
+
/* Now do regular lookup; lookup foo */
hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry,
namelen);
@@ -204,7 +206,10 @@ struct dentry *unionfs_lookup_backend(st
continue;
}
- opaque = is_opaque_dir(dentry, bindex);
+ opaque = 0;
+ if (bindex < bend) {
+ opaque = is_opaque_dir(dentry, bindex);
+ }
if (opaque < 0) {
err = opaque;
goto out_free;
@@ -307,7 +312,9 @@ struct dentry *unionfs_lookup_backend(st
ASSERT(dbend(dentry) <= sbmax(dentry->d_sb));
ASSERT(dbstart(dentry) >= 0);
}
- KFREE(whname);
+ if (whname)
+ KFREE(whname);
+
fist_print_dentry("OUT unionfs_lookup (parent)", parent_dentry);
fist_print_dentry("OUT unionfs_lookup (child)", dentry);
if (locked_parent)
_______________________________________________
unionfs mailing list
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs