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> 1302b69b28SMiklos 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; 2302b69b28SMiklos Szeredi char *redirect; 24e28edc46SMiklos Szeredi }; 25bbb1e54dSMiklos Szeredi 2602b69b28SMiklos Szeredi static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, 2702b69b28SMiklos Szeredi size_t prelen, const char *post) 2802b69b28SMiklos Szeredi { 2902b69b28SMiklos Szeredi int res; 3002b69b28SMiklos Szeredi char *s, *next, *buf = NULL; 3102b69b28SMiklos Szeredi 3202b69b28SMiklos Szeredi res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0); 3302b69b28SMiklos Szeredi if (res < 0) { 3402b69b28SMiklos Szeredi if (res == -ENODATA || res == -EOPNOTSUPP) 3502b69b28SMiklos Szeredi return 0; 3602b69b28SMiklos Szeredi goto fail; 3702b69b28SMiklos Szeredi } 3802b69b28SMiklos Szeredi buf = kzalloc(prelen + res + strlen(post) + 1, GFP_TEMPORARY); 3902b69b28SMiklos Szeredi if (!buf) 4002b69b28SMiklos Szeredi return -ENOMEM; 4102b69b28SMiklos Szeredi 4202b69b28SMiklos Szeredi if (res == 0) 4302b69b28SMiklos Szeredi goto invalid; 4402b69b28SMiklos Szeredi 4502b69b28SMiklos Szeredi res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res); 4602b69b28SMiklos Szeredi if (res < 0) 4702b69b28SMiklos Szeredi goto fail; 4802b69b28SMiklos Szeredi if (res == 0) 4902b69b28SMiklos Szeredi goto invalid; 5002b69b28SMiklos Szeredi if (buf[0] == '/') { 5102b69b28SMiklos Szeredi for (s = buf; *s++ == '/'; s = next) { 5202b69b28SMiklos Szeredi next = strchrnul(s, '/'); 5302b69b28SMiklos Szeredi if (s == next) 5402b69b28SMiklos Szeredi goto invalid; 5502b69b28SMiklos Szeredi } 5602b69b28SMiklos Szeredi } else { 5702b69b28SMiklos Szeredi if (strchr(buf, '/') != NULL) 5802b69b28SMiklos Szeredi goto invalid; 5902b69b28SMiklos Szeredi 6002b69b28SMiklos Szeredi memmove(buf + prelen, buf, res); 6102b69b28SMiklos Szeredi memcpy(buf, d->name.name, prelen); 6202b69b28SMiklos Szeredi } 6302b69b28SMiklos Szeredi 6402b69b28SMiklos Szeredi strcat(buf, post); 6502b69b28SMiklos Szeredi kfree(d->redirect); 6602b69b28SMiklos Szeredi d->redirect = buf; 6702b69b28SMiklos Szeredi d->name.name = d->redirect; 6802b69b28SMiklos Szeredi d->name.len = strlen(d->redirect); 6902b69b28SMiklos Szeredi 7002b69b28SMiklos Szeredi return 0; 7102b69b28SMiklos Szeredi 7202b69b28SMiklos Szeredi err_free: 7302b69b28SMiklos Szeredi kfree(buf); 7402b69b28SMiklos Szeredi return 0; 7502b69b28SMiklos Szeredi fail: 7602b69b28SMiklos Szeredi pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res); 7702b69b28SMiklos Szeredi goto err_free; 7802b69b28SMiklos Szeredi invalid: 7902b69b28SMiklos Szeredi pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf); 8002b69b28SMiklos Szeredi goto err_free; 8102b69b28SMiklos Szeredi } 8202b69b28SMiklos 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, 10002b69b28SMiklos 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 } 13702b69b28SMiklos Szeredi err = ovl_check_redirect(this, d, prelen, post); 13802b69b28SMiklos Szeredi if (err) 13902b69b28SMiklos 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*4c7d0c9cSAmir Goldstein /* Counting down from the end, since the prefix can change */ 158*4c7d0c9cSAmir Goldstein size_t rem = d->name.len - 1; 15902b69b28SMiklos Szeredi struct dentry *dentry = NULL; 16002b69b28SMiklos Szeredi int err; 16102b69b28SMiklos Szeredi 162*4c7d0c9cSAmir Goldstein if (d->name.name[0] != '/') 16302b69b28SMiklos Szeredi return ovl_lookup_single(base, d, d->name.name, d->name.len, 16402b69b28SMiklos Szeredi 0, "", ret); 16502b69b28SMiklos Szeredi 166*4c7d0c9cSAmir Goldstein while (!IS_ERR_OR_NULL(base) && d_can_lookup(base)) { 167*4c7d0c9cSAmir Goldstein const char *s = d->name.name + d->name.len - rem; 16802b69b28SMiklos Szeredi const char *next = strchrnul(s, '/'); 169*4c7d0c9cSAmir Goldstein size_t thislen = next - s; 170*4c7d0c9cSAmir Goldstein bool end = !next[0]; 17102b69b28SMiklos Szeredi 172*4c7d0c9cSAmir Goldstein /* Verify we did not go off the rails */ 173*4c7d0c9cSAmir Goldstein if (WARN_ON(s[-1] != '/')) 17402b69b28SMiklos Szeredi return -EIO; 17502b69b28SMiklos Szeredi 176*4c7d0c9cSAmir Goldstein err = ovl_lookup_single(base, d, s, thislen, 177*4c7d0c9cSAmir Goldstein d->name.len - rem, next, &base); 17802b69b28SMiklos Szeredi dput(dentry); 17902b69b28SMiklos Szeredi if (err) 18002b69b28SMiklos Szeredi return err; 18102b69b28SMiklos Szeredi dentry = base; 182*4c7d0c9cSAmir Goldstein if (end) 183*4c7d0c9cSAmir Goldstein break; 184*4c7d0c9cSAmir Goldstein 185*4c7d0c9cSAmir Goldstein rem -= thislen + 1; 186*4c7d0c9cSAmir Goldstein 187*4c7d0c9cSAmir Goldstein if (WARN_ON(rem >= d->name.len)) 188*4c7d0c9cSAmir Goldstein return -EIO; 18902b69b28SMiklos Szeredi } 19002b69b28SMiklos Szeredi *ret = dentry; 19102b69b28SMiklos Szeredi return 0; 192e28edc46SMiklos Szeredi } 193e28edc46SMiklos Szeredi 194bbb1e54dSMiklos Szeredi /* 195bbb1e54dSMiklos Szeredi * Returns next layer in stack starting from top. 196bbb1e54dSMiklos Szeredi * Returns -1 if this is the last layer. 197bbb1e54dSMiklos Szeredi */ 198bbb1e54dSMiklos Szeredi int ovl_path_next(int idx, struct dentry *dentry, struct path *path) 199bbb1e54dSMiklos Szeredi { 200bbb1e54dSMiklos Szeredi struct ovl_entry *oe = dentry->d_fsdata; 201bbb1e54dSMiklos Szeredi 202bbb1e54dSMiklos Szeredi BUG_ON(idx < 0); 203bbb1e54dSMiklos Szeredi if (idx == 0) { 204bbb1e54dSMiklos Szeredi ovl_path_upper(dentry, path); 205bbb1e54dSMiklos Szeredi if (path->dentry) 206bbb1e54dSMiklos Szeredi return oe->numlower ? 1 : -1; 207bbb1e54dSMiklos Szeredi idx++; 208bbb1e54dSMiklos Szeredi } 209bbb1e54dSMiklos Szeredi BUG_ON(idx > oe->numlower); 210bbb1e54dSMiklos Szeredi *path = oe->lowerstack[idx - 1]; 211bbb1e54dSMiklos Szeredi 212bbb1e54dSMiklos Szeredi return (idx < oe->numlower) ? idx + 1 : -1; 213bbb1e54dSMiklos Szeredi } 214bbb1e54dSMiklos Szeredi 215bbb1e54dSMiklos Szeredi struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, 216bbb1e54dSMiklos Szeredi unsigned int flags) 217bbb1e54dSMiklos Szeredi { 218bbb1e54dSMiklos Szeredi struct ovl_entry *oe; 219bbb1e54dSMiklos Szeredi const struct cred *old_cred; 2206b2d5fe4SMiklos Szeredi struct ovl_fs *ofs = dentry->d_sb->s_fs_info; 221bbb1e54dSMiklos Szeredi struct ovl_entry *poe = dentry->d_parent->d_fsdata; 222bbb1e54dSMiklos Szeredi struct path *stack = NULL; 223bbb1e54dSMiklos Szeredi struct dentry *upperdir, *upperdentry = NULL; 224bbb1e54dSMiklos Szeredi unsigned int ctr = 0; 225bbb1e54dSMiklos Szeredi struct inode *inode = NULL; 226bbb1e54dSMiklos Szeredi bool upperopaque = false; 22702b69b28SMiklos Szeredi char *upperredirect = NULL; 228bbb1e54dSMiklos Szeredi struct dentry *this; 229bbb1e54dSMiklos Szeredi unsigned int i; 230bbb1e54dSMiklos Szeredi int err; 231e28edc46SMiklos Szeredi struct ovl_lookup_data d = { 232e28edc46SMiklos Szeredi .name = dentry->d_name, 233e28edc46SMiklos Szeredi .is_dir = false, 234e28edc46SMiklos Szeredi .opaque = false, 235e28edc46SMiklos Szeredi .stop = false, 236e28edc46SMiklos Szeredi .last = !poe->numlower, 23702b69b28SMiklos Szeredi .redirect = NULL, 238e28edc46SMiklos Szeredi }; 239bbb1e54dSMiklos Szeredi 2406b2d5fe4SMiklos Szeredi if (dentry->d_name.len > ofs->namelen) 2416b2d5fe4SMiklos Szeredi return ERR_PTR(-ENAMETOOLONG); 2426b2d5fe4SMiklos Szeredi 243bbb1e54dSMiklos Szeredi old_cred = ovl_override_creds(dentry->d_sb); 244bbb1e54dSMiklos Szeredi upperdir = ovl_upperdentry_dereference(poe); 245bbb1e54dSMiklos Szeredi if (upperdir) { 246e28edc46SMiklos Szeredi err = ovl_lookup_layer(upperdir, &d, &upperdentry); 247e28edc46SMiklos Szeredi if (err) 248bbb1e54dSMiklos Szeredi goto out; 249bbb1e54dSMiklos Szeredi 250e28edc46SMiklos Szeredi if (upperdentry && unlikely(ovl_dentry_remote(upperdentry))) { 251e28edc46SMiklos Szeredi dput(upperdentry); 252bbb1e54dSMiklos Szeredi err = -EREMOTE; 253bbb1e54dSMiklos Szeredi goto out; 254bbb1e54dSMiklos Szeredi } 25502b69b28SMiklos Szeredi 25602b69b28SMiklos Szeredi if (d.redirect) { 25702b69b28SMiklos Szeredi upperredirect = kstrdup(d.redirect, GFP_KERNEL); 25802b69b28SMiklos Szeredi if (!upperredirect) 25902b69b28SMiklos Szeredi goto out_put_upper; 26002b69b28SMiklos Szeredi if (d.redirect[0] == '/') 26102b69b28SMiklos Szeredi poe = dentry->d_sb->s_root->d_fsdata; 26202b69b28SMiklos Szeredi } 263e28edc46SMiklos Szeredi upperopaque = d.opaque; 264bbb1e54dSMiklos Szeredi } 265bbb1e54dSMiklos Szeredi 266e28edc46SMiklos Szeredi if (!d.stop && poe->numlower) { 267bbb1e54dSMiklos Szeredi err = -ENOMEM; 26802b69b28SMiklos Szeredi stack = kcalloc(ofs->numlower, sizeof(struct path), 269e28edc46SMiklos Szeredi GFP_TEMPORARY); 270bbb1e54dSMiklos Szeredi if (!stack) 271bbb1e54dSMiklos Szeredi goto out_put_upper; 272bbb1e54dSMiklos Szeredi } 273bbb1e54dSMiklos Szeredi 274e28edc46SMiklos Szeredi for (i = 0; !d.stop && i < poe->numlower; i++) { 275bbb1e54dSMiklos Szeredi struct path lowerpath = poe->lowerstack[i]; 276bbb1e54dSMiklos Szeredi 277e28edc46SMiklos Szeredi d.last = i == poe->numlower - 1; 278e28edc46SMiklos Szeredi err = ovl_lookup_layer(lowerpath.dentry, &d, &this); 279e28edc46SMiklos Szeredi if (err) 280bbb1e54dSMiklos Szeredi goto out_put; 2816b2d5fe4SMiklos Szeredi 282bbb1e54dSMiklos Szeredi if (!this) 283bbb1e54dSMiklos Szeredi continue; 284bbb1e54dSMiklos Szeredi 285bbb1e54dSMiklos Szeredi stack[ctr].dentry = this; 286bbb1e54dSMiklos Szeredi stack[ctr].mnt = lowerpath.mnt; 287bbb1e54dSMiklos Szeredi ctr++; 28802b69b28SMiklos Szeredi 28902b69b28SMiklos Szeredi if (d.stop) 29002b69b28SMiklos Szeredi break; 29102b69b28SMiklos Szeredi 29202b69b28SMiklos Szeredi if (d.redirect && 29302b69b28SMiklos Szeredi d.redirect[0] == '/' && 29402b69b28SMiklos Szeredi poe != dentry->d_sb->s_root->d_fsdata) { 29502b69b28SMiklos Szeredi poe = dentry->d_sb->s_root->d_fsdata; 29602b69b28SMiklos Szeredi 29702b69b28SMiklos Szeredi /* Find the current layer on the root dentry */ 29802b69b28SMiklos Szeredi for (i = 0; i < poe->numlower; i++) 29902b69b28SMiklos Szeredi if (poe->lowerstack[i].mnt == lowerpath.mnt) 30002b69b28SMiklos Szeredi break; 30102b69b28SMiklos Szeredi if (WARN_ON(i == poe->numlower)) 30202b69b28SMiklos Szeredi break; 30302b69b28SMiklos Szeredi } 304bbb1e54dSMiklos Szeredi } 305bbb1e54dSMiklos Szeredi 306bbb1e54dSMiklos Szeredi oe = ovl_alloc_entry(ctr); 307bbb1e54dSMiklos Szeredi err = -ENOMEM; 308bbb1e54dSMiklos Szeredi if (!oe) 309bbb1e54dSMiklos Szeredi goto out_put; 310bbb1e54dSMiklos Szeredi 311bbb1e54dSMiklos Szeredi if (upperdentry || ctr) { 312bbb1e54dSMiklos Szeredi struct dentry *realdentry; 313bbb1e54dSMiklos Szeredi struct inode *realinode; 314bbb1e54dSMiklos Szeredi 315bbb1e54dSMiklos Szeredi realdentry = upperdentry ? upperdentry : stack[0].dentry; 316bbb1e54dSMiklos Szeredi realinode = d_inode(realdentry); 317bbb1e54dSMiklos Szeredi 318bbb1e54dSMiklos Szeredi err = -ENOMEM; 319bbb1e54dSMiklos Szeredi if (upperdentry && !d_is_dir(upperdentry)) { 320bbb1e54dSMiklos Szeredi inode = ovl_get_inode(dentry->d_sb, realinode); 321bbb1e54dSMiklos Szeredi } else { 322bbb1e54dSMiklos Szeredi inode = ovl_new_inode(dentry->d_sb, realinode->i_mode, 323bbb1e54dSMiklos Szeredi realinode->i_rdev); 324bbb1e54dSMiklos Szeredi if (inode) 325bbb1e54dSMiklos Szeredi ovl_inode_init(inode, realinode, !!upperdentry); 326bbb1e54dSMiklos Szeredi } 327bbb1e54dSMiklos Szeredi if (!inode) 328bbb1e54dSMiklos Szeredi goto out_free_oe; 329bbb1e54dSMiklos Szeredi ovl_copyattr(realdentry->d_inode, inode); 330bbb1e54dSMiklos Szeredi } 331bbb1e54dSMiklos Szeredi 332bbb1e54dSMiklos Szeredi revert_creds(old_cred); 333bbb1e54dSMiklos Szeredi oe->opaque = upperopaque; 33402b69b28SMiklos Szeredi oe->redirect = upperredirect; 335bbb1e54dSMiklos Szeredi oe->__upperdentry = upperdentry; 336bbb1e54dSMiklos Szeredi memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); 337bbb1e54dSMiklos Szeredi kfree(stack); 33802b69b28SMiklos Szeredi kfree(d.redirect); 339bbb1e54dSMiklos Szeredi dentry->d_fsdata = oe; 340bbb1e54dSMiklos Szeredi d_add(dentry, inode); 341bbb1e54dSMiklos Szeredi 342bbb1e54dSMiklos Szeredi return NULL; 343bbb1e54dSMiklos Szeredi 344bbb1e54dSMiklos Szeredi out_free_oe: 345bbb1e54dSMiklos Szeredi kfree(oe); 346bbb1e54dSMiklos Szeredi out_put: 347bbb1e54dSMiklos Szeredi for (i = 0; i < ctr; i++) 348bbb1e54dSMiklos Szeredi dput(stack[i].dentry); 349bbb1e54dSMiklos Szeredi kfree(stack); 350bbb1e54dSMiklos Szeredi out_put_upper: 351bbb1e54dSMiklos Szeredi dput(upperdentry); 35202b69b28SMiklos Szeredi kfree(upperredirect); 353bbb1e54dSMiklos Szeredi out: 35402b69b28SMiklos Szeredi kfree(d.redirect); 355bbb1e54dSMiklos Szeredi revert_creds(old_cred); 356bbb1e54dSMiklos Szeredi return ERR_PTR(err); 357bbb1e54dSMiklos Szeredi } 358bbb1e54dSMiklos Szeredi 359bbb1e54dSMiklos Szeredi bool ovl_lower_positive(struct dentry *dentry) 360bbb1e54dSMiklos Szeredi { 361bbb1e54dSMiklos Szeredi struct ovl_entry *oe = dentry->d_fsdata; 362bbb1e54dSMiklos Szeredi struct ovl_entry *poe = dentry->d_parent->d_fsdata; 363bbb1e54dSMiklos Szeredi const struct qstr *name = &dentry->d_name; 364bbb1e54dSMiklos Szeredi unsigned int i; 365bbb1e54dSMiklos Szeredi bool positive = false; 366bbb1e54dSMiklos Szeredi bool done = false; 367bbb1e54dSMiklos Szeredi 368bbb1e54dSMiklos Szeredi /* 369bbb1e54dSMiklos Szeredi * If dentry is negative, then lower is positive iff this is a 370bbb1e54dSMiklos Szeredi * whiteout. 371bbb1e54dSMiklos Szeredi */ 372bbb1e54dSMiklos Szeredi if (!dentry->d_inode) 373bbb1e54dSMiklos Szeredi return oe->opaque; 374bbb1e54dSMiklos Szeredi 375bbb1e54dSMiklos Szeredi /* Negative upper -> positive lower */ 376bbb1e54dSMiklos Szeredi if (!oe->__upperdentry) 377bbb1e54dSMiklos Szeredi return true; 378bbb1e54dSMiklos Szeredi 379bbb1e54dSMiklos Szeredi /* Positive upper -> have to look up lower to see whether it exists */ 380bbb1e54dSMiklos Szeredi for (i = 0; !done && !positive && i < poe->numlower; i++) { 381bbb1e54dSMiklos Szeredi struct dentry *this; 382bbb1e54dSMiklos Szeredi struct dentry *lowerdir = poe->lowerstack[i].dentry; 383bbb1e54dSMiklos Szeredi 384bbb1e54dSMiklos Szeredi this = lookup_one_len_unlocked(name->name, lowerdir, 385bbb1e54dSMiklos Szeredi name->len); 386bbb1e54dSMiklos Szeredi if (IS_ERR(this)) { 387bbb1e54dSMiklos Szeredi switch (PTR_ERR(this)) { 388bbb1e54dSMiklos Szeredi case -ENOENT: 389bbb1e54dSMiklos Szeredi case -ENAMETOOLONG: 390bbb1e54dSMiklos Szeredi break; 391bbb1e54dSMiklos Szeredi 392bbb1e54dSMiklos Szeredi default: 393bbb1e54dSMiklos Szeredi /* 394bbb1e54dSMiklos Szeredi * Assume something is there, we just couldn't 395bbb1e54dSMiklos Szeredi * access it. 396bbb1e54dSMiklos Szeredi */ 397bbb1e54dSMiklos Szeredi positive = true; 398bbb1e54dSMiklos Szeredi break; 399bbb1e54dSMiklos Szeredi } 400bbb1e54dSMiklos Szeredi } else { 401bbb1e54dSMiklos Szeredi if (this->d_inode) { 402bbb1e54dSMiklos Szeredi positive = !ovl_is_whiteout(this); 403bbb1e54dSMiklos Szeredi done = true; 404bbb1e54dSMiklos Szeredi } 405bbb1e54dSMiklos Szeredi dput(this); 406bbb1e54dSMiklos Szeredi } 407bbb1e54dSMiklos Szeredi } 408bbb1e54dSMiklos Szeredi 409bbb1e54dSMiklos Szeredi return positive; 410bbb1e54dSMiklos Szeredi } 411