1bbb1e54dSMiklos Szeredi /* 2bbb1e54dSMiklos Szeredi * Copyright (C) 2011 Novell Inc. 3bbb1e54dSMiklos Szeredi * Copyright (C) 2016 Red Hat, Inc. 4bbb1e54dSMiklos Szeredi * 5bbb1e54dSMiklos Szeredi * This program is free software; you can redistribute it and/or modify it 6bbb1e54dSMiklos Szeredi * under the terms of the GNU General Public License version 2 as published by 7bbb1e54dSMiklos Szeredi * the Free Software Foundation. 8bbb1e54dSMiklos Szeredi */ 9bbb1e54dSMiklos Szeredi 10bbb1e54dSMiklos Szeredi #include <linux/fs.h> 11bbb1e54dSMiklos Szeredi #include <linux/namei.h> 12bbb1e54dSMiklos Szeredi #include <linux/xattr.h> 13*02b69b28SMiklos Szeredi #include <linux/ratelimit.h> 14bbb1e54dSMiklos Szeredi #include "overlayfs.h" 15bbb1e54dSMiklos Szeredi #include "ovl_entry.h" 16bbb1e54dSMiklos Szeredi 17e28edc46SMiklos Szeredi struct ovl_lookup_data { 18e28edc46SMiklos Szeredi struct qstr name; 19e28edc46SMiklos Szeredi bool is_dir; 20e28edc46SMiklos Szeredi bool opaque; 21e28edc46SMiklos Szeredi bool stop; 22e28edc46SMiklos Szeredi bool last; 23*02b69b28SMiklos Szeredi char *redirect; 24e28edc46SMiklos Szeredi }; 25bbb1e54dSMiklos Szeredi 26*02b69b28SMiklos Szeredi static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, 27*02b69b28SMiklos Szeredi size_t prelen, const char *post) 28*02b69b28SMiklos Szeredi { 29*02b69b28SMiklos Szeredi int res; 30*02b69b28SMiklos Szeredi char *s, *next, *buf = NULL; 31*02b69b28SMiklos Szeredi 32*02b69b28SMiklos Szeredi res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0); 33*02b69b28SMiklos Szeredi if (res < 0) { 34*02b69b28SMiklos Szeredi if (res == -ENODATA || res == -EOPNOTSUPP) 35*02b69b28SMiklos Szeredi return 0; 36*02b69b28SMiklos Szeredi goto fail; 37*02b69b28SMiklos Szeredi } 38*02b69b28SMiklos Szeredi buf = kzalloc(prelen + res + strlen(post) + 1, GFP_TEMPORARY); 39*02b69b28SMiklos Szeredi if (!buf) 40*02b69b28SMiklos Szeredi return -ENOMEM; 41*02b69b28SMiklos Szeredi 42*02b69b28SMiklos Szeredi if (res == 0) 43*02b69b28SMiklos Szeredi goto invalid; 44*02b69b28SMiklos Szeredi 45*02b69b28SMiklos Szeredi res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res); 46*02b69b28SMiklos Szeredi if (res < 0) 47*02b69b28SMiklos Szeredi goto fail; 48*02b69b28SMiklos Szeredi if (res == 0) 49*02b69b28SMiklos Szeredi goto invalid; 50*02b69b28SMiklos Szeredi if (buf[0] == '/') { 51*02b69b28SMiklos Szeredi for (s = buf; *s++ == '/'; s = next) { 52*02b69b28SMiklos Szeredi next = strchrnul(s, '/'); 53*02b69b28SMiklos Szeredi if (s == next) 54*02b69b28SMiklos Szeredi goto invalid; 55*02b69b28SMiklos Szeredi } 56*02b69b28SMiklos Szeredi } else { 57*02b69b28SMiklos Szeredi if (strchr(buf, '/') != NULL) 58*02b69b28SMiklos Szeredi goto invalid; 59*02b69b28SMiklos Szeredi 60*02b69b28SMiklos Szeredi memmove(buf + prelen, buf, res); 61*02b69b28SMiklos Szeredi memcpy(buf, d->name.name, prelen); 62*02b69b28SMiklos Szeredi } 63*02b69b28SMiklos Szeredi 64*02b69b28SMiklos Szeredi strcat(buf, post); 65*02b69b28SMiklos Szeredi kfree(d->redirect); 66*02b69b28SMiklos Szeredi d->redirect = buf; 67*02b69b28SMiklos Szeredi d->name.name = d->redirect; 68*02b69b28SMiklos Szeredi d->name.len = strlen(d->redirect); 69*02b69b28SMiklos Szeredi 70*02b69b28SMiklos Szeredi return 0; 71*02b69b28SMiklos Szeredi 72*02b69b28SMiklos Szeredi err_free: 73*02b69b28SMiklos Szeredi kfree(buf); 74*02b69b28SMiklos Szeredi return 0; 75*02b69b28SMiklos Szeredi fail: 76*02b69b28SMiklos Szeredi pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res); 77*02b69b28SMiklos Szeredi goto err_free; 78*02b69b28SMiklos Szeredi invalid: 79*02b69b28SMiklos Szeredi pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf); 80*02b69b28SMiklos Szeredi goto err_free; 81*02b69b28SMiklos Szeredi } 82*02b69b28SMiklos Szeredi 83bbb1e54dSMiklos Szeredi static bool ovl_is_opaquedir(struct dentry *dentry) 84bbb1e54dSMiklos Szeredi { 85bbb1e54dSMiklos Szeredi int res; 86bbb1e54dSMiklos Szeredi char val; 87bbb1e54dSMiklos Szeredi 88bbb1e54dSMiklos Szeredi if (!d_is_dir(dentry)) 89bbb1e54dSMiklos Szeredi return false; 90bbb1e54dSMiklos Szeredi 91bbb1e54dSMiklos Szeredi res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1); 92bbb1e54dSMiklos Szeredi if (res == 1 && val == 'y') 93bbb1e54dSMiklos Szeredi return true; 94bbb1e54dSMiklos Szeredi 95bbb1e54dSMiklos Szeredi return false; 96bbb1e54dSMiklos Szeredi } 97bbb1e54dSMiklos Szeredi 98e28edc46SMiklos Szeredi static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, 99e28edc46SMiklos Szeredi const char *name, unsigned int namelen, 100*02b69b28SMiklos Szeredi size_t prelen, const char *post, 101e28edc46SMiklos Szeredi struct dentry **ret) 102e28edc46SMiklos Szeredi { 103e28edc46SMiklos Szeredi struct dentry *this; 104e28edc46SMiklos Szeredi int err; 105e28edc46SMiklos Szeredi 106e28edc46SMiklos Szeredi this = lookup_one_len_unlocked(name, base, namelen); 107e28edc46SMiklos Szeredi if (IS_ERR(this)) { 108e28edc46SMiklos Szeredi err = PTR_ERR(this); 109e28edc46SMiklos Szeredi this = NULL; 110e28edc46SMiklos Szeredi if (err == -ENOENT || err == -ENAMETOOLONG) 111e28edc46SMiklos Szeredi goto out; 112e28edc46SMiklos Szeredi goto out_err; 113e28edc46SMiklos Szeredi } 114e28edc46SMiklos Szeredi if (!this->d_inode) 115e28edc46SMiklos Szeredi goto put_and_out; 116e28edc46SMiklos Szeredi 117e28edc46SMiklos Szeredi if (ovl_dentry_weird(this)) { 118e28edc46SMiklos Szeredi /* Don't support traversing automounts and other weirdness */ 119e28edc46SMiklos Szeredi err = -EREMOTE; 120e28edc46SMiklos Szeredi goto out_err; 121e28edc46SMiklos Szeredi } 122e28edc46SMiklos Szeredi if (ovl_is_whiteout(this)) { 123e28edc46SMiklos Szeredi d->stop = d->opaque = true; 124e28edc46SMiklos Szeredi goto put_and_out; 125e28edc46SMiklos Szeredi } 126e28edc46SMiklos Szeredi if (!d_can_lookup(this)) { 127e28edc46SMiklos Szeredi d->stop = true; 128e28edc46SMiklos Szeredi if (d->is_dir) 129e28edc46SMiklos Szeredi goto put_and_out; 130e28edc46SMiklos Szeredi goto out; 131e28edc46SMiklos Szeredi } 132e28edc46SMiklos Szeredi d->is_dir = true; 133e28edc46SMiklos Szeredi if (!d->last && ovl_is_opaquedir(this)) { 134e28edc46SMiklos Szeredi d->stop = d->opaque = true; 135e28edc46SMiklos Szeredi goto out; 136e28edc46SMiklos Szeredi } 137*02b69b28SMiklos Szeredi err = ovl_check_redirect(this, d, prelen, post); 138*02b69b28SMiklos Szeredi if (err) 139*02b69b28SMiklos Szeredi goto out_err; 140e28edc46SMiklos Szeredi out: 141e28edc46SMiklos Szeredi *ret = this; 142e28edc46SMiklos Szeredi return 0; 143e28edc46SMiklos Szeredi 144e28edc46SMiklos Szeredi put_and_out: 145e28edc46SMiklos Szeredi dput(this); 146e28edc46SMiklos Szeredi this = NULL; 147e28edc46SMiklos Szeredi goto out; 148e28edc46SMiklos Szeredi 149e28edc46SMiklos Szeredi out_err: 150e28edc46SMiklos Szeredi dput(this); 151e28edc46SMiklos Szeredi return err; 152e28edc46SMiklos Szeredi } 153e28edc46SMiklos Szeredi 154e28edc46SMiklos Szeredi static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d, 155e28edc46SMiklos Szeredi struct dentry **ret) 156e28edc46SMiklos Szeredi { 157*02b69b28SMiklos Szeredi const char *s = d->name.name; 158*02b69b28SMiklos Szeredi struct dentry *dentry = NULL; 159*02b69b28SMiklos Szeredi int err; 160*02b69b28SMiklos Szeredi 161*02b69b28SMiklos Szeredi if (*s != '/') 162*02b69b28SMiklos Szeredi return ovl_lookup_single(base, d, d->name.name, d->name.len, 163*02b69b28SMiklos Szeredi 0, "", ret); 164*02b69b28SMiklos Szeredi 165*02b69b28SMiklos Szeredi while (*s++ == '/' && !IS_ERR_OR_NULL(base) && d_can_lookup(base)) { 166*02b69b28SMiklos Szeredi const char *next = strchrnul(s, '/'); 167*02b69b28SMiklos Szeredi size_t slen = strlen(s); 168*02b69b28SMiklos Szeredi 169*02b69b28SMiklos Szeredi if (WARN_ON(slen > d->name.len) || 170*02b69b28SMiklos Szeredi WARN_ON(strcmp(d->name.name + d->name.len - slen, s))) 171*02b69b28SMiklos Szeredi return -EIO; 172*02b69b28SMiklos Szeredi 173*02b69b28SMiklos Szeredi err = ovl_lookup_single(base, d, s, next - s, 174*02b69b28SMiklos Szeredi d->name.len - slen, next, &base); 175*02b69b28SMiklos Szeredi dput(dentry); 176*02b69b28SMiklos Szeredi if (err) 177*02b69b28SMiklos Szeredi return err; 178*02b69b28SMiklos Szeredi dentry = base; 179*02b69b28SMiklos Szeredi s = next; 180*02b69b28SMiklos Szeredi } 181*02b69b28SMiklos Szeredi *ret = dentry; 182*02b69b28SMiklos Szeredi return 0; 183e28edc46SMiklos Szeredi } 184e28edc46SMiklos Szeredi 185bbb1e54dSMiklos Szeredi /* 186bbb1e54dSMiklos Szeredi * Returns next layer in stack starting from top. 187bbb1e54dSMiklos Szeredi * Returns -1 if this is the last layer. 188bbb1e54dSMiklos Szeredi */ 189bbb1e54dSMiklos Szeredi int ovl_path_next(int idx, struct dentry *dentry, struct path *path) 190bbb1e54dSMiklos Szeredi { 191bbb1e54dSMiklos Szeredi struct ovl_entry *oe = dentry->d_fsdata; 192bbb1e54dSMiklos Szeredi 193bbb1e54dSMiklos Szeredi BUG_ON(idx < 0); 194bbb1e54dSMiklos Szeredi if (idx == 0) { 195bbb1e54dSMiklos Szeredi ovl_path_upper(dentry, path); 196bbb1e54dSMiklos Szeredi if (path->dentry) 197bbb1e54dSMiklos Szeredi return oe->numlower ? 1 : -1; 198bbb1e54dSMiklos Szeredi idx++; 199bbb1e54dSMiklos Szeredi } 200bbb1e54dSMiklos Szeredi BUG_ON(idx > oe->numlower); 201bbb1e54dSMiklos Szeredi *path = oe->lowerstack[idx - 1]; 202bbb1e54dSMiklos Szeredi 203bbb1e54dSMiklos Szeredi return (idx < oe->numlower) ? idx + 1 : -1; 204bbb1e54dSMiklos Szeredi } 205bbb1e54dSMiklos Szeredi 206bbb1e54dSMiklos Szeredi struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, 207bbb1e54dSMiklos Szeredi unsigned int flags) 208bbb1e54dSMiklos Szeredi { 209bbb1e54dSMiklos Szeredi struct ovl_entry *oe; 210bbb1e54dSMiklos Szeredi const struct cred *old_cred; 2116b2d5fe4SMiklos Szeredi struct ovl_fs *ofs = dentry->d_sb->s_fs_info; 212bbb1e54dSMiklos Szeredi struct ovl_entry *poe = dentry->d_parent->d_fsdata; 213bbb1e54dSMiklos Szeredi struct path *stack = NULL; 214bbb1e54dSMiklos Szeredi struct dentry *upperdir, *upperdentry = NULL; 215bbb1e54dSMiklos Szeredi unsigned int ctr = 0; 216bbb1e54dSMiklos Szeredi struct inode *inode = NULL; 217bbb1e54dSMiklos Szeredi bool upperopaque = false; 218*02b69b28SMiklos Szeredi char *upperredirect = NULL; 219bbb1e54dSMiklos Szeredi struct dentry *this; 220bbb1e54dSMiklos Szeredi unsigned int i; 221bbb1e54dSMiklos Szeredi int err; 222e28edc46SMiklos Szeredi struct ovl_lookup_data d = { 223e28edc46SMiklos Szeredi .name = dentry->d_name, 224e28edc46SMiklos Szeredi .is_dir = false, 225e28edc46SMiklos Szeredi .opaque = false, 226e28edc46SMiklos Szeredi .stop = false, 227e28edc46SMiklos Szeredi .last = !poe->numlower, 228*02b69b28SMiklos Szeredi .redirect = NULL, 229e28edc46SMiklos Szeredi }; 230bbb1e54dSMiklos Szeredi 2316b2d5fe4SMiklos Szeredi if (dentry->d_name.len > ofs->namelen) 2326b2d5fe4SMiklos Szeredi return ERR_PTR(-ENAMETOOLONG); 2336b2d5fe4SMiklos Szeredi 234bbb1e54dSMiklos Szeredi old_cred = ovl_override_creds(dentry->d_sb); 235bbb1e54dSMiklos Szeredi upperdir = ovl_upperdentry_dereference(poe); 236bbb1e54dSMiklos Szeredi if (upperdir) { 237e28edc46SMiklos Szeredi err = ovl_lookup_layer(upperdir, &d, &upperdentry); 238e28edc46SMiklos Szeredi if (err) 239bbb1e54dSMiklos Szeredi goto out; 240bbb1e54dSMiklos Szeredi 241e28edc46SMiklos Szeredi if (upperdentry && unlikely(ovl_dentry_remote(upperdentry))) { 242e28edc46SMiklos Szeredi dput(upperdentry); 243bbb1e54dSMiklos Szeredi err = -EREMOTE; 244bbb1e54dSMiklos Szeredi goto out; 245bbb1e54dSMiklos Szeredi } 246*02b69b28SMiklos Szeredi 247*02b69b28SMiklos Szeredi if (d.redirect) { 248*02b69b28SMiklos Szeredi upperredirect = kstrdup(d.redirect, GFP_KERNEL); 249*02b69b28SMiklos Szeredi if (!upperredirect) 250*02b69b28SMiklos Szeredi goto out_put_upper; 251*02b69b28SMiklos Szeredi if (d.redirect[0] == '/') 252*02b69b28SMiklos Szeredi poe = dentry->d_sb->s_root->d_fsdata; 253*02b69b28SMiklos Szeredi } 254e28edc46SMiklos Szeredi upperopaque = d.opaque; 255bbb1e54dSMiklos Szeredi } 256bbb1e54dSMiklos Szeredi 257e28edc46SMiklos Szeredi if (!d.stop && poe->numlower) { 258bbb1e54dSMiklos Szeredi err = -ENOMEM; 259*02b69b28SMiklos Szeredi stack = kcalloc(ofs->numlower, sizeof(struct path), 260e28edc46SMiklos Szeredi GFP_TEMPORARY); 261bbb1e54dSMiklos Szeredi if (!stack) 262bbb1e54dSMiklos Szeredi goto out_put_upper; 263bbb1e54dSMiklos Szeredi } 264bbb1e54dSMiklos Szeredi 265e28edc46SMiklos Szeredi for (i = 0; !d.stop && i < poe->numlower; i++) { 266bbb1e54dSMiklos Szeredi struct path lowerpath = poe->lowerstack[i]; 267bbb1e54dSMiklos Szeredi 268e28edc46SMiklos Szeredi d.last = i == poe->numlower - 1; 269e28edc46SMiklos Szeredi err = ovl_lookup_layer(lowerpath.dentry, &d, &this); 270e28edc46SMiklos Szeredi if (err) 271bbb1e54dSMiklos Szeredi goto out_put; 2726b2d5fe4SMiklos Szeredi 273bbb1e54dSMiklos Szeredi if (!this) 274bbb1e54dSMiklos Szeredi continue; 275bbb1e54dSMiklos Szeredi 276bbb1e54dSMiklos Szeredi stack[ctr].dentry = this; 277bbb1e54dSMiklos Szeredi stack[ctr].mnt = lowerpath.mnt; 278bbb1e54dSMiklos Szeredi ctr++; 279*02b69b28SMiklos Szeredi 280*02b69b28SMiklos Szeredi if (d.stop) 281*02b69b28SMiklos Szeredi break; 282*02b69b28SMiklos Szeredi 283*02b69b28SMiklos Szeredi if (d.redirect && 284*02b69b28SMiklos Szeredi d.redirect[0] == '/' && 285*02b69b28SMiklos Szeredi poe != dentry->d_sb->s_root->d_fsdata) { 286*02b69b28SMiklos Szeredi poe = dentry->d_sb->s_root->d_fsdata; 287*02b69b28SMiklos Szeredi 288*02b69b28SMiklos Szeredi /* Find the current layer on the root dentry */ 289*02b69b28SMiklos Szeredi for (i = 0; i < poe->numlower; i++) 290*02b69b28SMiklos Szeredi if (poe->lowerstack[i].mnt == lowerpath.mnt) 291*02b69b28SMiklos Szeredi break; 292*02b69b28SMiklos Szeredi if (WARN_ON(i == poe->numlower)) 293*02b69b28SMiklos Szeredi break; 294*02b69b28SMiklos Szeredi } 295bbb1e54dSMiklos Szeredi } 296bbb1e54dSMiklos Szeredi 297bbb1e54dSMiklos Szeredi oe = ovl_alloc_entry(ctr); 298bbb1e54dSMiklos Szeredi err = -ENOMEM; 299bbb1e54dSMiklos Szeredi if (!oe) 300bbb1e54dSMiklos Szeredi goto out_put; 301bbb1e54dSMiklos Szeredi 302bbb1e54dSMiklos Szeredi if (upperdentry || ctr) { 303bbb1e54dSMiklos Szeredi struct dentry *realdentry; 304bbb1e54dSMiklos Szeredi struct inode *realinode; 305bbb1e54dSMiklos Szeredi 306bbb1e54dSMiklos Szeredi realdentry = upperdentry ? upperdentry : stack[0].dentry; 307bbb1e54dSMiklos Szeredi realinode = d_inode(realdentry); 308bbb1e54dSMiklos Szeredi 309bbb1e54dSMiklos Szeredi err = -ENOMEM; 310bbb1e54dSMiklos Szeredi if (upperdentry && !d_is_dir(upperdentry)) { 311bbb1e54dSMiklos Szeredi inode = ovl_get_inode(dentry->d_sb, realinode); 312bbb1e54dSMiklos Szeredi } else { 313bbb1e54dSMiklos Szeredi inode = ovl_new_inode(dentry->d_sb, realinode->i_mode, 314bbb1e54dSMiklos Szeredi realinode->i_rdev); 315bbb1e54dSMiklos Szeredi if (inode) 316bbb1e54dSMiklos Szeredi ovl_inode_init(inode, realinode, !!upperdentry); 317bbb1e54dSMiklos Szeredi } 318bbb1e54dSMiklos Szeredi if (!inode) 319bbb1e54dSMiklos Szeredi goto out_free_oe; 320bbb1e54dSMiklos Szeredi ovl_copyattr(realdentry->d_inode, inode); 321bbb1e54dSMiklos Szeredi } 322bbb1e54dSMiklos Szeredi 323bbb1e54dSMiklos Szeredi revert_creds(old_cred); 324bbb1e54dSMiklos Szeredi oe->opaque = upperopaque; 325*02b69b28SMiklos Szeredi oe->redirect = upperredirect; 326bbb1e54dSMiklos Szeredi oe->__upperdentry = upperdentry; 327bbb1e54dSMiklos Szeredi memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); 328bbb1e54dSMiklos Szeredi kfree(stack); 329*02b69b28SMiklos Szeredi kfree(d.redirect); 330bbb1e54dSMiklos Szeredi dentry->d_fsdata = oe; 331bbb1e54dSMiklos Szeredi d_add(dentry, inode); 332bbb1e54dSMiklos Szeredi 333bbb1e54dSMiklos Szeredi return NULL; 334bbb1e54dSMiklos Szeredi 335bbb1e54dSMiklos Szeredi out_free_oe: 336bbb1e54dSMiklos Szeredi kfree(oe); 337bbb1e54dSMiklos Szeredi out_put: 338bbb1e54dSMiklos Szeredi for (i = 0; i < ctr; i++) 339bbb1e54dSMiklos Szeredi dput(stack[i].dentry); 340bbb1e54dSMiklos Szeredi kfree(stack); 341bbb1e54dSMiklos Szeredi out_put_upper: 342bbb1e54dSMiklos Szeredi dput(upperdentry); 343*02b69b28SMiklos Szeredi kfree(upperredirect); 344bbb1e54dSMiklos Szeredi out: 345*02b69b28SMiklos Szeredi kfree(d.redirect); 346bbb1e54dSMiklos Szeredi revert_creds(old_cred); 347bbb1e54dSMiklos Szeredi return ERR_PTR(err); 348bbb1e54dSMiklos Szeredi } 349bbb1e54dSMiklos Szeredi 350bbb1e54dSMiklos Szeredi bool ovl_lower_positive(struct dentry *dentry) 351bbb1e54dSMiklos Szeredi { 352bbb1e54dSMiklos Szeredi struct ovl_entry *oe = dentry->d_fsdata; 353bbb1e54dSMiklos Szeredi struct ovl_entry *poe = dentry->d_parent->d_fsdata; 354bbb1e54dSMiklos Szeredi const struct qstr *name = &dentry->d_name; 355bbb1e54dSMiklos Szeredi unsigned int i; 356bbb1e54dSMiklos Szeredi bool positive = false; 357bbb1e54dSMiklos Szeredi bool done = false; 358bbb1e54dSMiklos Szeredi 359bbb1e54dSMiklos Szeredi /* 360bbb1e54dSMiklos Szeredi * If dentry is negative, then lower is positive iff this is a 361bbb1e54dSMiklos Szeredi * whiteout. 362bbb1e54dSMiklos Szeredi */ 363bbb1e54dSMiklos Szeredi if (!dentry->d_inode) 364bbb1e54dSMiklos Szeredi return oe->opaque; 365bbb1e54dSMiklos Szeredi 366bbb1e54dSMiklos Szeredi /* Negative upper -> positive lower */ 367bbb1e54dSMiklos Szeredi if (!oe->__upperdentry) 368bbb1e54dSMiklos Szeredi return true; 369bbb1e54dSMiklos Szeredi 370bbb1e54dSMiklos Szeredi /* Positive upper -> have to look up lower to see whether it exists */ 371bbb1e54dSMiklos Szeredi for (i = 0; !done && !positive && i < poe->numlower; i++) { 372bbb1e54dSMiklos Szeredi struct dentry *this; 373bbb1e54dSMiklos Szeredi struct dentry *lowerdir = poe->lowerstack[i].dentry; 374bbb1e54dSMiklos Szeredi 375bbb1e54dSMiklos Szeredi this = lookup_one_len_unlocked(name->name, lowerdir, 376bbb1e54dSMiklos Szeredi name->len); 377bbb1e54dSMiklos Szeredi if (IS_ERR(this)) { 378bbb1e54dSMiklos Szeredi switch (PTR_ERR(this)) { 379bbb1e54dSMiklos Szeredi case -ENOENT: 380bbb1e54dSMiklos Szeredi case -ENAMETOOLONG: 381bbb1e54dSMiklos Szeredi break; 382bbb1e54dSMiklos Szeredi 383bbb1e54dSMiklos Szeredi default: 384bbb1e54dSMiklos Szeredi /* 385bbb1e54dSMiklos Szeredi * Assume something is there, we just couldn't 386bbb1e54dSMiklos Szeredi * access it. 387bbb1e54dSMiklos Szeredi */ 388bbb1e54dSMiklos Szeredi positive = true; 389bbb1e54dSMiklos Szeredi break; 390bbb1e54dSMiklos Szeredi } 391bbb1e54dSMiklos Szeredi } else { 392bbb1e54dSMiklos Szeredi if (this->d_inode) { 393bbb1e54dSMiklos Szeredi positive = !ovl_is_whiteout(this); 394bbb1e54dSMiklos Szeredi done = true; 395bbb1e54dSMiklos Szeredi } 396bbb1e54dSMiklos Szeredi dput(this); 397bbb1e54dSMiklos Szeredi } 398bbb1e54dSMiklos Szeredi } 399bbb1e54dSMiklos Szeredi 400bbb1e54dSMiklos Szeredi return positive; 401bbb1e54dSMiklos Szeredi } 402