18ed5eec9SAmir Goldstein /* 28ed5eec9SAmir Goldstein * Overlayfs NFS export support. 38ed5eec9SAmir Goldstein * 48ed5eec9SAmir Goldstein * Amir Goldstein <amir73il@gmail.com> 58ed5eec9SAmir Goldstein * 68ed5eec9SAmir Goldstein * Copyright (C) 2017-2018 CTERA Networks. All Rights Reserved. 78ed5eec9SAmir Goldstein * 88ed5eec9SAmir Goldstein * This program is free software; you can redistribute it and/or modify it 98ed5eec9SAmir Goldstein * under the terms of the GNU General Public License version 2 as published by 108ed5eec9SAmir Goldstein * the Free Software Foundation. 118ed5eec9SAmir Goldstein */ 128ed5eec9SAmir Goldstein 138ed5eec9SAmir Goldstein #include <linux/fs.h> 148ed5eec9SAmir Goldstein #include <linux/cred.h> 158ed5eec9SAmir Goldstein #include <linux/mount.h> 168ed5eec9SAmir Goldstein #include <linux/namei.h> 178ed5eec9SAmir Goldstein #include <linux/xattr.h> 188ed5eec9SAmir Goldstein #include <linux/exportfs.h> 198ed5eec9SAmir Goldstein #include <linux/ratelimit.h> 208ed5eec9SAmir Goldstein #include "overlayfs.h" 218ed5eec9SAmir Goldstein 22b305e844SAmir Goldstein /* 23b305e844SAmir Goldstein * We only need to encode origin if there is a chance that the same object was 24b305e844SAmir Goldstein * encoded pre copy up and then we need to stay consistent with the same 25b305e844SAmir Goldstein * encoding also after copy up. If non-pure upper is not indexed, then it was 26b305e844SAmir Goldstein * copied up before NFS export was enabled. In that case we don't need to worry 27b305e844SAmir Goldstein * about staying consistent with pre copy up encoding and we encode an upper 28b305e844SAmir Goldstein * file handle. Overlay root dentry is a private case of non-indexed upper. 29b305e844SAmir Goldstein * 30b305e844SAmir Goldstein * The following table summarizes the different file handle encodings used for 31b305e844SAmir Goldstein * different overlay object types: 32b305e844SAmir Goldstein * 33b305e844SAmir Goldstein * Object type | Encoding 34b305e844SAmir Goldstein * -------------------------------- 35b305e844SAmir Goldstein * Pure upper | U 36b305e844SAmir Goldstein * Non-indexed upper | U 3705e1f118SAmir Goldstein * Indexed upper | L (*) 3805e1f118SAmir Goldstein * Non-upper | L (*) 39b305e844SAmir Goldstein * 40b305e844SAmir Goldstein * U = upper file handle 41b305e844SAmir Goldstein * L = lower file handle 4205e1f118SAmir Goldstein * 4305e1f118SAmir Goldstein * (*) Connecting an overlay dir from real lower dentry is not always 4405e1f118SAmir Goldstein * possible when there are redirects in lower layers. To mitigate this case, 4505e1f118SAmir Goldstein * we copy up the lower dir first and then encode an upper dir file handle. 46b305e844SAmir Goldstein */ 47b305e844SAmir Goldstein static bool ovl_should_encode_origin(struct dentry *dentry) 48b305e844SAmir Goldstein { 4905e1f118SAmir Goldstein struct ovl_fs *ofs = dentry->d_sb->s_fs_info; 5005e1f118SAmir Goldstein 51b305e844SAmir Goldstein if (!ovl_dentry_lower(dentry)) 52b305e844SAmir Goldstein return false; 53b305e844SAmir Goldstein 5405e1f118SAmir Goldstein /* 5505e1f118SAmir Goldstein * Decoding a merge dir, whose origin's parent is under a redirected 5605e1f118SAmir Goldstein * lower dir is not always possible. As a simple aproximation, we do 5705e1f118SAmir Goldstein * not encode lower dir file handles when overlay has multiple lower 5805e1f118SAmir Goldstein * layers and origin is below the topmost lower layer. 5905e1f118SAmir Goldstein * 6005e1f118SAmir Goldstein * TODO: copy up only the parent that is under redirected lower. 6105e1f118SAmir Goldstein */ 6205e1f118SAmir Goldstein if (d_is_dir(dentry) && ofs->upper_mnt && 6305e1f118SAmir Goldstein OVL_E(dentry)->lowerstack[0].layer->idx > 1) 6405e1f118SAmir Goldstein return false; 6505e1f118SAmir Goldstein 66b305e844SAmir Goldstein /* Decoding a non-indexed upper from origin is not implemented */ 67b305e844SAmir Goldstein if (ovl_dentry_upper(dentry) && 68b305e844SAmir Goldstein !ovl_test_flag(OVL_INDEX, d_inode(dentry))) 69b305e844SAmir Goldstein return false; 70b305e844SAmir Goldstein 71b305e844SAmir Goldstein return true; 72b305e844SAmir Goldstein } 73b305e844SAmir Goldstein 7405e1f118SAmir Goldstein static int ovl_encode_maybe_copy_up(struct dentry *dentry) 7505e1f118SAmir Goldstein { 7605e1f118SAmir Goldstein int err; 7705e1f118SAmir Goldstein 7805e1f118SAmir Goldstein if (ovl_dentry_upper(dentry)) 7905e1f118SAmir Goldstein return 0; 8005e1f118SAmir Goldstein 8105e1f118SAmir Goldstein err = ovl_want_write(dentry); 8205e1f118SAmir Goldstein if (err) 8305e1f118SAmir Goldstein return err; 8405e1f118SAmir Goldstein 8505e1f118SAmir Goldstein err = ovl_copy_up(dentry); 8605e1f118SAmir Goldstein 8705e1f118SAmir Goldstein ovl_drop_write(dentry); 8805e1f118SAmir Goldstein return err; 8905e1f118SAmir Goldstein } 9005e1f118SAmir Goldstein 918ed5eec9SAmir Goldstein static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen) 928ed5eec9SAmir Goldstein { 938ed5eec9SAmir Goldstein struct dentry *origin = ovl_dentry_lower(dentry); 948ed5eec9SAmir Goldstein struct ovl_fh *fh = NULL; 958ed5eec9SAmir Goldstein int err; 968ed5eec9SAmir Goldstein 9705e1f118SAmir Goldstein /* 9805e1f118SAmir Goldstein * If we should not encode a lower dir file handle, copy up and encode 9905e1f118SAmir Goldstein * an upper dir file handle. 10005e1f118SAmir Goldstein */ 10105e1f118SAmir Goldstein if (!ovl_should_encode_origin(dentry)) { 10205e1f118SAmir Goldstein err = ovl_encode_maybe_copy_up(dentry); 10305e1f118SAmir Goldstein if (err) 10405e1f118SAmir Goldstein goto fail; 1058ed5eec9SAmir Goldstein 10605e1f118SAmir Goldstein origin = NULL; 10705e1f118SAmir Goldstein } 10805e1f118SAmir Goldstein 10903e1c584SAmir Goldstein /* Encode an upper or origin file handle */ 11003e1c584SAmir Goldstein fh = ovl_encode_fh(origin ?: ovl_dentry_upper(dentry), !origin); 1118ed5eec9SAmir Goldstein 1128ed5eec9SAmir Goldstein err = -EOVERFLOW; 1138ed5eec9SAmir Goldstein if (fh->len > buflen) 1148ed5eec9SAmir Goldstein goto fail; 1158ed5eec9SAmir Goldstein 1168ed5eec9SAmir Goldstein memcpy(buf, (char *)fh, fh->len); 1178ed5eec9SAmir Goldstein err = fh->len; 1188ed5eec9SAmir Goldstein 1198ed5eec9SAmir Goldstein out: 1208ed5eec9SAmir Goldstein kfree(fh); 1218ed5eec9SAmir Goldstein return err; 1228ed5eec9SAmir Goldstein 1238ed5eec9SAmir Goldstein fail: 1248ed5eec9SAmir Goldstein pr_warn_ratelimited("overlayfs: failed to encode file handle (%pd2, err=%i, buflen=%d, len=%d, type=%d)\n", 1258ed5eec9SAmir Goldstein dentry, err, buflen, fh ? (int)fh->len : 0, 1268ed5eec9SAmir Goldstein fh ? fh->type : 0); 1278ed5eec9SAmir Goldstein goto out; 1288ed5eec9SAmir Goldstein } 1298ed5eec9SAmir Goldstein 1308ed5eec9SAmir Goldstein static int ovl_dentry_to_fh(struct dentry *dentry, u32 *fid, int *max_len) 1318ed5eec9SAmir Goldstein { 1328ed5eec9SAmir Goldstein int res, len = *max_len << 2; 1338ed5eec9SAmir Goldstein 1348ed5eec9SAmir Goldstein res = ovl_d_to_fh(dentry, (char *)fid, len); 1358ed5eec9SAmir Goldstein if (res <= 0) 1368ed5eec9SAmir Goldstein return FILEID_INVALID; 1378ed5eec9SAmir Goldstein 1388ed5eec9SAmir Goldstein len = res; 1398ed5eec9SAmir Goldstein 1408ed5eec9SAmir Goldstein /* Round up to dwords */ 1418ed5eec9SAmir Goldstein *max_len = (len + 3) >> 2; 1428ed5eec9SAmir Goldstein return OVL_FILEID; 1438ed5eec9SAmir Goldstein } 1448ed5eec9SAmir Goldstein 1458ed5eec9SAmir Goldstein static int ovl_encode_inode_fh(struct inode *inode, u32 *fid, int *max_len, 1468ed5eec9SAmir Goldstein struct inode *parent) 1478ed5eec9SAmir Goldstein { 1488ed5eec9SAmir Goldstein struct dentry *dentry; 1498ed5eec9SAmir Goldstein int type; 1508ed5eec9SAmir Goldstein 1518ed5eec9SAmir Goldstein /* TODO: encode connectable file handles */ 1528ed5eec9SAmir Goldstein if (parent) 1538ed5eec9SAmir Goldstein return FILEID_INVALID; 1548ed5eec9SAmir Goldstein 1558ed5eec9SAmir Goldstein dentry = d_find_any_alias(inode); 1568ed5eec9SAmir Goldstein if (WARN_ON(!dentry)) 1578ed5eec9SAmir Goldstein return FILEID_INVALID; 1588ed5eec9SAmir Goldstein 1598ed5eec9SAmir Goldstein type = ovl_dentry_to_fh(dentry, fid, max_len); 1608ed5eec9SAmir Goldstein 1618ed5eec9SAmir Goldstein dput(dentry); 1628ed5eec9SAmir Goldstein return type; 1638ed5eec9SAmir Goldstein } 1648ed5eec9SAmir Goldstein 1658556a420SAmir Goldstein /* 166f71bd9cfSAmir Goldstein * Find or instantiate an overlay dentry from real dentries and index. 1678556a420SAmir Goldstein */ 1688556a420SAmir Goldstein static struct dentry *ovl_obtain_alias(struct super_block *sb, 169f71bd9cfSAmir Goldstein struct dentry *upper_alias, 170f71bd9cfSAmir Goldstein struct ovl_path *lowerpath, 171f71bd9cfSAmir Goldstein struct dentry *index) 1728556a420SAmir Goldstein { 173f941866fSAmir Goldstein struct dentry *lower = lowerpath ? lowerpath->dentry : NULL; 174f71bd9cfSAmir Goldstein struct dentry *upper = upper_alias ?: index; 1758556a420SAmir Goldstein struct dentry *dentry; 176f941866fSAmir Goldstein struct inode *inode; 1778556a420SAmir Goldstein struct ovl_entry *oe; 1788556a420SAmir Goldstein 179f71bd9cfSAmir Goldstein /* We get overlay directory dentries with ovl_lookup_real() */ 180f71bd9cfSAmir Goldstein if (d_is_dir(upper ?: lower)) 1818556a420SAmir Goldstein return ERR_PTR(-EIO); 1828556a420SAmir Goldstein 183f71bd9cfSAmir Goldstein inode = ovl_get_inode(sb, dget(upper), lower, index, !!lower); 1848556a420SAmir Goldstein if (IS_ERR(inode)) { 1858556a420SAmir Goldstein dput(upper); 1868556a420SAmir Goldstein return ERR_CAST(inode); 1878556a420SAmir Goldstein } 1888556a420SAmir Goldstein 189f71bd9cfSAmir Goldstein if (index) 190f71bd9cfSAmir Goldstein ovl_set_flag(OVL_INDEX, inode); 191f71bd9cfSAmir Goldstein 1928556a420SAmir Goldstein dentry = d_find_any_alias(inode); 1938556a420SAmir Goldstein if (!dentry) { 1948556a420SAmir Goldstein dentry = d_alloc_anon(inode->i_sb); 1958556a420SAmir Goldstein if (!dentry) 1968556a420SAmir Goldstein goto nomem; 197f941866fSAmir Goldstein oe = ovl_alloc_entry(lower ? 1 : 0); 1988556a420SAmir Goldstein if (!oe) 1998556a420SAmir Goldstein goto nomem; 2008556a420SAmir Goldstein 201f941866fSAmir Goldstein if (lower) { 202f941866fSAmir Goldstein oe->lowerstack->dentry = dget(lower); 203f941866fSAmir Goldstein oe->lowerstack->layer = lowerpath->layer; 204f941866fSAmir Goldstein } 2058556a420SAmir Goldstein dentry->d_fsdata = oe; 206f71bd9cfSAmir Goldstein if (upper_alias) 2078556a420SAmir Goldstein ovl_dentry_set_upper_alias(dentry); 2088556a420SAmir Goldstein } 2098556a420SAmir Goldstein 2108556a420SAmir Goldstein return d_instantiate_anon(dentry, inode); 2118556a420SAmir Goldstein 2128556a420SAmir Goldstein nomem: 2138556a420SAmir Goldstein iput(inode); 2148556a420SAmir Goldstein dput(dentry); 2158556a420SAmir Goldstein return ERR_PTR(-ENOMEM); 2168556a420SAmir Goldstein } 2178556a420SAmir Goldstein 2183985b70aSAmir Goldstein /* 2193985b70aSAmir Goldstein * Lookup a child overlay dentry to get a connected overlay dentry whose real 2203985b70aSAmir Goldstein * dentry is @real. If @real is on upper layer, we lookup a child overlay 2213985b70aSAmir Goldstein * dentry with the same name as the real dentry. Otherwise, we need to consult 2223985b70aSAmir Goldstein * index for lookup. 2233985b70aSAmir Goldstein */ 2243985b70aSAmir Goldstein static struct dentry *ovl_lookup_real_one(struct dentry *connected, 2253985b70aSAmir Goldstein struct dentry *real, 2263985b70aSAmir Goldstein struct ovl_layer *layer) 2273985b70aSAmir Goldstein { 2283985b70aSAmir Goldstein struct inode *dir = d_inode(connected); 2293985b70aSAmir Goldstein struct dentry *this, *parent = NULL; 2303985b70aSAmir Goldstein struct name_snapshot name; 2313985b70aSAmir Goldstein int err; 2323985b70aSAmir Goldstein 2333985b70aSAmir Goldstein /* TODO: lookup by lower real dentry */ 2343985b70aSAmir Goldstein if (layer->idx) 2353985b70aSAmir Goldstein return ERR_PTR(-EACCES); 2363985b70aSAmir Goldstein 2373985b70aSAmir Goldstein /* 2383985b70aSAmir Goldstein * Lookup child overlay dentry by real name. The dir mutex protects us 2393985b70aSAmir Goldstein * from racing with overlay rename. If the overlay dentry that is above 2403985b70aSAmir Goldstein * real has already been moved to a parent that is not under the 2413985b70aSAmir Goldstein * connected overlay dir, we return -ECHILD and restart the lookup of 2423985b70aSAmir Goldstein * connected real path from the top. 2433985b70aSAmir Goldstein */ 2443985b70aSAmir Goldstein inode_lock_nested(dir, I_MUTEX_PARENT); 2453985b70aSAmir Goldstein err = -ECHILD; 2463985b70aSAmir Goldstein parent = dget_parent(real); 2473985b70aSAmir Goldstein if (ovl_dentry_upper(connected) != parent) 2483985b70aSAmir Goldstein goto fail; 2493985b70aSAmir Goldstein 2503985b70aSAmir Goldstein /* 2513985b70aSAmir Goldstein * We also need to take a snapshot of real dentry name to protect us 2523985b70aSAmir Goldstein * from racing with underlying layer rename. In this case, we don't 2533985b70aSAmir Goldstein * care about returning ESTALE, only from dereferencing a free name 2543985b70aSAmir Goldstein * pointer because we hold no lock on the real dentry. 2553985b70aSAmir Goldstein */ 2563985b70aSAmir Goldstein take_dentry_name_snapshot(&name, real); 2573985b70aSAmir Goldstein this = lookup_one_len(name.name, connected, strlen(name.name)); 2583985b70aSAmir Goldstein err = PTR_ERR(this); 2593985b70aSAmir Goldstein if (IS_ERR(this)) { 2603985b70aSAmir Goldstein goto fail; 2613985b70aSAmir Goldstein } else if (!this || !this->d_inode) { 2623985b70aSAmir Goldstein dput(this); 2633985b70aSAmir Goldstein err = -ENOENT; 2643985b70aSAmir Goldstein goto fail; 2653985b70aSAmir Goldstein } else if (ovl_dentry_upper(this) != real) { 2663985b70aSAmir Goldstein dput(this); 2673985b70aSAmir Goldstein err = -ESTALE; 2683985b70aSAmir Goldstein goto fail; 2693985b70aSAmir Goldstein } 2703985b70aSAmir Goldstein 2713985b70aSAmir Goldstein out: 2723985b70aSAmir Goldstein release_dentry_name_snapshot(&name); 2733985b70aSAmir Goldstein dput(parent); 2743985b70aSAmir Goldstein inode_unlock(dir); 2753985b70aSAmir Goldstein return this; 2763985b70aSAmir Goldstein 2773985b70aSAmir Goldstein fail: 2783985b70aSAmir Goldstein pr_warn_ratelimited("overlayfs: failed to lookup one by real (%pd2, layer=%d, connected=%pd2, err=%i)\n", 2793985b70aSAmir Goldstein real, layer->idx, connected, err); 2803985b70aSAmir Goldstein this = ERR_PTR(err); 2813985b70aSAmir Goldstein goto out; 2823985b70aSAmir Goldstein } 2833985b70aSAmir Goldstein 2843985b70aSAmir Goldstein /* 2853985b70aSAmir Goldstein * Lookup a connected overlay dentry whose real dentry is @real. 2863985b70aSAmir Goldstein * If @real is on upper layer, we lookup a child overlay dentry with the same 2873985b70aSAmir Goldstein * path the real dentry. Otherwise, we need to consult index for lookup. 2883985b70aSAmir Goldstein */ 2893985b70aSAmir Goldstein static struct dentry *ovl_lookup_real(struct super_block *sb, 2903985b70aSAmir Goldstein struct dentry *real, 2913985b70aSAmir Goldstein struct ovl_layer *layer) 2923985b70aSAmir Goldstein { 2933985b70aSAmir Goldstein struct dentry *connected; 2943985b70aSAmir Goldstein int err = 0; 2953985b70aSAmir Goldstein 2963985b70aSAmir Goldstein /* TODO: use index when looking up by lower real dentry */ 2973985b70aSAmir Goldstein if (layer->idx) 2983985b70aSAmir Goldstein return ERR_PTR(-EACCES); 2993985b70aSAmir Goldstein 3003985b70aSAmir Goldstein connected = dget(sb->s_root); 3013985b70aSAmir Goldstein while (!err) { 3023985b70aSAmir Goldstein struct dentry *next, *this; 3033985b70aSAmir Goldstein struct dentry *parent = NULL; 3043985b70aSAmir Goldstein struct dentry *real_connected = ovl_dentry_upper(connected); 3053985b70aSAmir Goldstein 3063985b70aSAmir Goldstein if (real_connected == real) 3073985b70aSAmir Goldstein break; 3083985b70aSAmir Goldstein 3093985b70aSAmir Goldstein /* Find the topmost dentry not yet connected */ 3103985b70aSAmir Goldstein next = dget(real); 3113985b70aSAmir Goldstein for (;;) { 3123985b70aSAmir Goldstein parent = dget_parent(next); 3133985b70aSAmir Goldstein 3143985b70aSAmir Goldstein if (parent == real_connected) 3153985b70aSAmir Goldstein break; 3163985b70aSAmir Goldstein 3173985b70aSAmir Goldstein /* 3183985b70aSAmir Goldstein * If real has been moved out of 'real_connected', 3193985b70aSAmir Goldstein * we will not find 'real_connected' and hit the layer 3203985b70aSAmir Goldstein * root. In that case, we need to restart connecting. 3213985b70aSAmir Goldstein * This game can go on forever in the worst case. We 3223985b70aSAmir Goldstein * may want to consider taking s_vfs_rename_mutex if 3233985b70aSAmir Goldstein * this happens more than once. 3243985b70aSAmir Goldstein */ 3253985b70aSAmir Goldstein if (parent == layer->mnt->mnt_root) { 3263985b70aSAmir Goldstein dput(connected); 3273985b70aSAmir Goldstein connected = dget(sb->s_root); 3283985b70aSAmir Goldstein break; 3293985b70aSAmir Goldstein } 3303985b70aSAmir Goldstein 3313985b70aSAmir Goldstein /* 3323985b70aSAmir Goldstein * If real file has been moved out of the layer root 3333985b70aSAmir Goldstein * directory, we will eventully hit the real fs root. 3343985b70aSAmir Goldstein * This cannot happen by legit overlay rename, so we 3353985b70aSAmir Goldstein * return error in that case. 3363985b70aSAmir Goldstein */ 3373985b70aSAmir Goldstein if (parent == next) { 3383985b70aSAmir Goldstein err = -EXDEV; 3393985b70aSAmir Goldstein break; 3403985b70aSAmir Goldstein } 3413985b70aSAmir Goldstein 3423985b70aSAmir Goldstein dput(next); 3433985b70aSAmir Goldstein next = parent; 3443985b70aSAmir Goldstein } 3453985b70aSAmir Goldstein 3463985b70aSAmir Goldstein if (!err) { 3473985b70aSAmir Goldstein this = ovl_lookup_real_one(connected, next, layer); 3483985b70aSAmir Goldstein if (IS_ERR(this)) 3493985b70aSAmir Goldstein err = PTR_ERR(this); 3503985b70aSAmir Goldstein 3513985b70aSAmir Goldstein /* 3523985b70aSAmir Goldstein * Lookup of child in overlay can fail when racing with 3533985b70aSAmir Goldstein * overlay rename of child away from 'connected' parent. 3543985b70aSAmir Goldstein * In this case, we need to restart the lookup from the 3553985b70aSAmir Goldstein * top, because we cannot trust that 'real_connected' is 3563985b70aSAmir Goldstein * still an ancestor of 'real'. 3573985b70aSAmir Goldstein */ 3583985b70aSAmir Goldstein if (err == -ECHILD) { 3593985b70aSAmir Goldstein this = dget(sb->s_root); 3603985b70aSAmir Goldstein err = 0; 3613985b70aSAmir Goldstein } 3623985b70aSAmir Goldstein if (!err) { 3633985b70aSAmir Goldstein dput(connected); 3643985b70aSAmir Goldstein connected = this; 3653985b70aSAmir Goldstein } 3663985b70aSAmir Goldstein } 3673985b70aSAmir Goldstein 3683985b70aSAmir Goldstein dput(parent); 3693985b70aSAmir Goldstein dput(next); 3703985b70aSAmir Goldstein } 3713985b70aSAmir Goldstein 3723985b70aSAmir Goldstein if (err) 3733985b70aSAmir Goldstein goto fail; 3743985b70aSAmir Goldstein 3753985b70aSAmir Goldstein return connected; 3763985b70aSAmir Goldstein 3773985b70aSAmir Goldstein fail: 3783985b70aSAmir Goldstein pr_warn_ratelimited("overlayfs: failed to lookup by real (%pd2, layer=%d, connected=%pd2, err=%i)\n", 3793985b70aSAmir Goldstein real, layer->idx, connected, err); 3803985b70aSAmir Goldstein dput(connected); 3813985b70aSAmir Goldstein return ERR_PTR(err); 3823985b70aSAmir Goldstein } 3833985b70aSAmir Goldstein 3843985b70aSAmir Goldstein /* 385f71bd9cfSAmir Goldstein * Get an overlay dentry from upper/lower real dentries and index. 3863985b70aSAmir Goldstein */ 3873985b70aSAmir Goldstein static struct dentry *ovl_get_dentry(struct super_block *sb, 3883985b70aSAmir Goldstein struct dentry *upper, 389f71bd9cfSAmir Goldstein struct ovl_path *lowerpath, 390f71bd9cfSAmir Goldstein struct dentry *index) 3913985b70aSAmir Goldstein { 3923985b70aSAmir Goldstein struct ovl_fs *ofs = sb->s_fs_info; 3933985b70aSAmir Goldstein struct ovl_layer upper_layer = { .mnt = ofs->upper_mnt }; 394f71bd9cfSAmir Goldstein struct dentry *real = upper ?: (index ?: lowerpath->dentry); 3953985b70aSAmir Goldstein 396f941866fSAmir Goldstein /* 397f71bd9cfSAmir Goldstein * Obtain a disconnected overlay dentry from a non-dir real dentry 398f71bd9cfSAmir Goldstein * and index. 399f941866fSAmir Goldstein */ 400f71bd9cfSAmir Goldstein if (!d_is_dir(real)) 401f71bd9cfSAmir Goldstein return ovl_obtain_alias(sb, upper, lowerpath, index); 402f941866fSAmir Goldstein 403f941866fSAmir Goldstein /* TODO: lookup connected dir from real lower dir */ 4043985b70aSAmir Goldstein if (!upper) 4053985b70aSAmir Goldstein return ERR_PTR(-EACCES); 4063985b70aSAmir Goldstein 4073985b70aSAmir Goldstein /* Removed empty directory? */ 4083985b70aSAmir Goldstein if ((upper->d_flags & DCACHE_DISCONNECTED) || d_unhashed(upper)) 4093985b70aSAmir Goldstein return ERR_PTR(-ENOENT); 4103985b70aSAmir Goldstein 4113985b70aSAmir Goldstein /* 4123985b70aSAmir Goldstein * If real upper dentry is connected and hashed, get a connected 4133985b70aSAmir Goldstein * overlay dentry with the same path as the real upper dentry. 4143985b70aSAmir Goldstein */ 4153985b70aSAmir Goldstein return ovl_lookup_real(sb, upper, &upper_layer); 4163985b70aSAmir Goldstein } 4173985b70aSAmir Goldstein 4188556a420SAmir Goldstein static struct dentry *ovl_upper_fh_to_d(struct super_block *sb, 4198556a420SAmir Goldstein struct ovl_fh *fh) 4208556a420SAmir Goldstein { 4218556a420SAmir Goldstein struct ovl_fs *ofs = sb->s_fs_info; 4228556a420SAmir Goldstein struct dentry *dentry; 4238556a420SAmir Goldstein struct dentry *upper; 4248556a420SAmir Goldstein 4258556a420SAmir Goldstein if (!ofs->upper_mnt) 4268556a420SAmir Goldstein return ERR_PTR(-EACCES); 4278556a420SAmir Goldstein 4288556a420SAmir Goldstein upper = ovl_decode_fh(fh, ofs->upper_mnt); 4298556a420SAmir Goldstein if (IS_ERR_OR_NULL(upper)) 4308556a420SAmir Goldstein return upper; 4318556a420SAmir Goldstein 432f71bd9cfSAmir Goldstein dentry = ovl_get_dentry(sb, upper, NULL, NULL); 4338556a420SAmir Goldstein dput(upper); 4348556a420SAmir Goldstein 4358556a420SAmir Goldstein return dentry; 4368556a420SAmir Goldstein } 4378556a420SAmir Goldstein 438f941866fSAmir Goldstein static struct dentry *ovl_lower_fh_to_d(struct super_block *sb, 439f941866fSAmir Goldstein struct ovl_fh *fh) 440f941866fSAmir Goldstein { 441f941866fSAmir Goldstein struct ovl_fs *ofs = sb->s_fs_info; 442f941866fSAmir Goldstein struct ovl_path origin = { }; 443f941866fSAmir Goldstein struct ovl_path *stack = &origin; 444f941866fSAmir Goldstein struct dentry *dentry = NULL; 445f71bd9cfSAmir Goldstein struct dentry *index = NULL; 4469436a1a3SAmir Goldstein struct inode *inode = NULL; 4479436a1a3SAmir Goldstein bool is_deleted = false; 448f941866fSAmir Goldstein int err; 449f941866fSAmir Goldstein 450f71bd9cfSAmir Goldstein /* First lookup indexed upper by fh */ 451f71bd9cfSAmir Goldstein if (ofs->indexdir) { 452f71bd9cfSAmir Goldstein index = ovl_get_index_fh(ofs, fh); 453f71bd9cfSAmir Goldstein err = PTR_ERR(index); 4549436a1a3SAmir Goldstein if (IS_ERR(index)) { 4559436a1a3SAmir Goldstein if (err != -ESTALE) 456f941866fSAmir Goldstein return ERR_PTR(err); 4579436a1a3SAmir Goldstein 4589436a1a3SAmir Goldstein /* Found a whiteout index - treat as deleted inode */ 4599436a1a3SAmir Goldstein is_deleted = true; 4609436a1a3SAmir Goldstein index = NULL; 4619436a1a3SAmir Goldstein } 462f71bd9cfSAmir Goldstein } 463f941866fSAmir Goldstein 464f71bd9cfSAmir Goldstein /* Then lookup origin by fh */ 465f71bd9cfSAmir Goldstein err = ovl_check_origin_fh(ofs, fh, NULL, &stack); 466f71bd9cfSAmir Goldstein if (err) { 467f71bd9cfSAmir Goldstein goto out_err; 468f71bd9cfSAmir Goldstein } else if (index) { 469f71bd9cfSAmir Goldstein err = ovl_verify_origin(index, origin.dentry, false); 470f71bd9cfSAmir Goldstein if (err) 471f71bd9cfSAmir Goldstein goto out_err; 4729436a1a3SAmir Goldstein } else if (is_deleted) { 4739436a1a3SAmir Goldstein /* Lookup deleted non-dir by origin inode */ 4749436a1a3SAmir Goldstein if (!d_is_dir(origin.dentry)) 4759436a1a3SAmir Goldstein inode = ovl_lookup_inode(sb, origin.dentry); 4769436a1a3SAmir Goldstein err = -ESTALE; 4779436a1a3SAmir Goldstein if (!inode || atomic_read(&inode->i_count) == 1) 4789436a1a3SAmir Goldstein goto out_err; 4799436a1a3SAmir Goldstein 4809436a1a3SAmir Goldstein /* Deleted but still open? */ 4819436a1a3SAmir Goldstein index = dget(ovl_i_dentry_upper(inode)); 482f71bd9cfSAmir Goldstein } 483f71bd9cfSAmir Goldstein 484f71bd9cfSAmir Goldstein dentry = ovl_get_dentry(sb, NULL, &origin, index); 485f71bd9cfSAmir Goldstein 486f71bd9cfSAmir Goldstein out: 487f941866fSAmir Goldstein dput(origin.dentry); 488f71bd9cfSAmir Goldstein dput(index); 4899436a1a3SAmir Goldstein iput(inode); 490f941866fSAmir Goldstein return dentry; 491f71bd9cfSAmir Goldstein 492f71bd9cfSAmir Goldstein out_err: 493f71bd9cfSAmir Goldstein dentry = ERR_PTR(err); 494f71bd9cfSAmir Goldstein goto out; 495f941866fSAmir Goldstein } 496f941866fSAmir Goldstein 4978556a420SAmir Goldstein static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid, 4988556a420SAmir Goldstein int fh_len, int fh_type) 4998556a420SAmir Goldstein { 5008556a420SAmir Goldstein struct dentry *dentry = NULL; 5018556a420SAmir Goldstein struct ovl_fh *fh = (struct ovl_fh *) fid; 5028556a420SAmir Goldstein int len = fh_len << 2; 5038556a420SAmir Goldstein unsigned int flags = 0; 5048556a420SAmir Goldstein int err; 5058556a420SAmir Goldstein 5068556a420SAmir Goldstein err = -EINVAL; 5078556a420SAmir Goldstein if (fh_type != OVL_FILEID) 5088556a420SAmir Goldstein goto out_err; 5098556a420SAmir Goldstein 5108556a420SAmir Goldstein err = ovl_check_fh_len(fh, len); 5118556a420SAmir Goldstein if (err) 5128556a420SAmir Goldstein goto out_err; 5138556a420SAmir Goldstein 5148556a420SAmir Goldstein flags = fh->flags; 515f941866fSAmir Goldstein dentry = (flags & OVL_FH_FLAG_PATH_UPPER) ? 516f941866fSAmir Goldstein ovl_upper_fh_to_d(sb, fh) : 517f941866fSAmir Goldstein ovl_lower_fh_to_d(sb, fh); 5188556a420SAmir Goldstein err = PTR_ERR(dentry); 5198556a420SAmir Goldstein if (IS_ERR(dentry) && err != -ESTALE) 5208556a420SAmir Goldstein goto out_err; 5218556a420SAmir Goldstein 5228556a420SAmir Goldstein return dentry; 5238556a420SAmir Goldstein 5248556a420SAmir Goldstein out_err: 5258556a420SAmir Goldstein pr_warn_ratelimited("overlayfs: failed to decode file handle (len=%d, type=%d, flags=%x, err=%i)\n", 5268556a420SAmir Goldstein len, fh_type, flags, err); 5278556a420SAmir Goldstein return ERR_PTR(err); 5288556a420SAmir Goldstein } 5298556a420SAmir Goldstein 5303985b70aSAmir Goldstein static struct dentry *ovl_fh_to_parent(struct super_block *sb, struct fid *fid, 5313985b70aSAmir Goldstein int fh_len, int fh_type) 5323985b70aSAmir Goldstein { 5333985b70aSAmir Goldstein pr_warn_ratelimited("overlayfs: connectable file handles not supported; use 'no_subtree_check' exportfs option.\n"); 5343985b70aSAmir Goldstein return ERR_PTR(-EACCES); 5353985b70aSAmir Goldstein } 5363985b70aSAmir Goldstein 5373985b70aSAmir Goldstein static int ovl_get_name(struct dentry *parent, char *name, 5383985b70aSAmir Goldstein struct dentry *child) 5393985b70aSAmir Goldstein { 5403985b70aSAmir Goldstein /* 5413985b70aSAmir Goldstein * ovl_fh_to_dentry() returns connected dir overlay dentries and 5423985b70aSAmir Goldstein * ovl_fh_to_parent() is not implemented, so we should not get here. 5433985b70aSAmir Goldstein */ 5443985b70aSAmir Goldstein WARN_ON_ONCE(1); 5453985b70aSAmir Goldstein return -EIO; 5463985b70aSAmir Goldstein } 5473985b70aSAmir Goldstein 5483985b70aSAmir Goldstein static struct dentry *ovl_get_parent(struct dentry *dentry) 5493985b70aSAmir Goldstein { 5503985b70aSAmir Goldstein /* 5513985b70aSAmir Goldstein * ovl_fh_to_dentry() returns connected dir overlay dentries, so we 5523985b70aSAmir Goldstein * should not get here. 5533985b70aSAmir Goldstein */ 5543985b70aSAmir Goldstein WARN_ON_ONCE(1); 5553985b70aSAmir Goldstein return ERR_PTR(-EIO); 5563985b70aSAmir Goldstein } 5573985b70aSAmir Goldstein 5588ed5eec9SAmir Goldstein const struct export_operations ovl_export_operations = { 5598ed5eec9SAmir Goldstein .encode_fh = ovl_encode_inode_fh, 5608556a420SAmir Goldstein .fh_to_dentry = ovl_fh_to_dentry, 5613985b70aSAmir Goldstein .fh_to_parent = ovl_fh_to_parent, 5623985b70aSAmir Goldstein .get_name = ovl_get_name, 5633985b70aSAmir Goldstein .get_parent = ovl_get_parent, 5648ed5eec9SAmir Goldstein }; 565