162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Overlayfs NFS export support. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Amir Goldstein <amir73il@gmail.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2017-2018 CTERA Networks. All Rights Reserved. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/cred.h> 1262306a36Sopenharmony_ci#include <linux/mount.h> 1362306a36Sopenharmony_ci#include <linux/namei.h> 1462306a36Sopenharmony_ci#include <linux/xattr.h> 1562306a36Sopenharmony_ci#include <linux/exportfs.h> 1662306a36Sopenharmony_ci#include <linux/ratelimit.h> 1762306a36Sopenharmony_ci#include "overlayfs.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic int ovl_encode_maybe_copy_up(struct dentry *dentry) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci int err; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci if (ovl_dentry_upper(dentry)) 2462306a36Sopenharmony_ci return 0; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci err = ovl_want_write(dentry); 2762306a36Sopenharmony_ci if (!err) { 2862306a36Sopenharmony_ci err = ovl_copy_up(dentry); 2962306a36Sopenharmony_ci ovl_drop_write(dentry); 3062306a36Sopenharmony_ci } 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci if (err) { 3362306a36Sopenharmony_ci pr_warn_ratelimited("failed to copy up on encode (%pd2, err=%i)\n", 3462306a36Sopenharmony_ci dentry, err); 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci return err; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci * Before encoding a non-upper directory file handle from real layer N, we need 4262306a36Sopenharmony_ci * to check if it will be possible to reconnect an overlay dentry from the real 4362306a36Sopenharmony_ci * lower decoded dentry. This is done by following the overlay ancestry up to a 4462306a36Sopenharmony_ci * "layer N connected" ancestor and verifying that all parents along the way are 4562306a36Sopenharmony_ci * "layer N connectable". If an ancestor that is NOT "layer N connectable" is 4662306a36Sopenharmony_ci * found, we need to copy up an ancestor, which is "layer N connectable", thus 4762306a36Sopenharmony_ci * making that ancestor "layer N connected". For example: 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * layer 1: /a 5062306a36Sopenharmony_ci * layer 2: /a/b/c 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * The overlay dentry /a is NOT "layer 2 connectable", because if dir /a is 5362306a36Sopenharmony_ci * copied up and renamed, upper dir /a will be indexed by lower dir /a from 5462306a36Sopenharmony_ci * layer 1. The dir /a from layer 2 will never be indexed, so the algorithm (*) 5562306a36Sopenharmony_ci * in ovl_lookup_real_ancestor() will not be able to lookup a connected overlay 5662306a36Sopenharmony_ci * dentry from the connected lower dentry /a/b/c. 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * To avoid this problem on decode time, we need to copy up an ancestor of 5962306a36Sopenharmony_ci * /a/b/c, which is "layer 2 connectable", on encode time. That ancestor is 6062306a36Sopenharmony_ci * /a/b. After copy up (and index) of /a/b, it will become "layer 2 connected" 6162306a36Sopenharmony_ci * and when the time comes to decode the file handle from lower dentry /a/b/c, 6262306a36Sopenharmony_ci * ovl_lookup_real_ancestor() will find the indexed ancestor /a/b and decoding 6362306a36Sopenharmony_ci * a connected overlay dentry will be accomplished. 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * (*) the algorithm in ovl_lookup_real_ancestor() can be improved to lookup an 6662306a36Sopenharmony_ci * entry /a in the lower layers above layer N and find the indexed dir /a from 6762306a36Sopenharmony_ci * layer 1. If that improvement is made, then the check for "layer N connected" 6862306a36Sopenharmony_ci * will need to verify there are no redirects in lower layers above N. In the 6962306a36Sopenharmony_ci * example above, /a will be "layer 2 connectable". However, if layer 2 dir /a 7062306a36Sopenharmony_ci * is a target of a layer 1 redirect, then /a will NOT be "layer 2 connectable": 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * layer 1: /A (redirect = /a) 7362306a36Sopenharmony_ci * layer 2: /a/b/c 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* Return the lowest layer for encoding a connectable file handle */ 7762306a36Sopenharmony_cistatic int ovl_connectable_layer(struct dentry *dentry) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct ovl_entry *oe = OVL_E(dentry); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* We can get overlay root from root of any layer */ 8262306a36Sopenharmony_ci if (dentry == dentry->d_sb->s_root) 8362306a36Sopenharmony_ci return ovl_numlower(oe); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* 8662306a36Sopenharmony_ci * If it's an unindexed merge dir, then it's not connectable with any 8762306a36Sopenharmony_ci * lower layer 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci if (ovl_dentry_upper(dentry) && 9062306a36Sopenharmony_ci !ovl_test_flag(OVL_INDEX, d_inode(dentry))) 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* We can get upper/overlay path from indexed/lower dentry */ 9462306a36Sopenharmony_ci return ovl_lowerstack(oe)->layer->idx; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* 9862306a36Sopenharmony_ci * @dentry is "connected" if all ancestors up to root or a "connected" ancestor 9962306a36Sopenharmony_ci * have the same uppermost lower layer as the origin's layer. We may need to 10062306a36Sopenharmony_ci * copy up a "connectable" ancestor to make it "connected". A "connected" dentry 10162306a36Sopenharmony_ci * cannot become non "connected", so cache positive result in dentry flags. 10262306a36Sopenharmony_ci * 10362306a36Sopenharmony_ci * Return the connected origin layer or < 0 on error. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_cistatic int ovl_connect_layer(struct dentry *dentry) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct dentry *next, *parent = NULL; 10862306a36Sopenharmony_ci struct ovl_entry *oe = OVL_E(dentry); 10962306a36Sopenharmony_ci int origin_layer; 11062306a36Sopenharmony_ci int err = 0; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if (WARN_ON(dentry == dentry->d_sb->s_root) || 11362306a36Sopenharmony_ci WARN_ON(!ovl_dentry_lower(dentry))) 11462306a36Sopenharmony_ci return -EIO; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci origin_layer = ovl_lowerstack(oe)->layer->idx; 11762306a36Sopenharmony_ci if (ovl_dentry_test_flag(OVL_E_CONNECTED, dentry)) 11862306a36Sopenharmony_ci return origin_layer; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* Find the topmost origin layer connectable ancestor of @dentry */ 12162306a36Sopenharmony_ci next = dget(dentry); 12262306a36Sopenharmony_ci for (;;) { 12362306a36Sopenharmony_ci parent = dget_parent(next); 12462306a36Sopenharmony_ci if (WARN_ON(parent == next)) { 12562306a36Sopenharmony_ci err = -EIO; 12662306a36Sopenharmony_ci break; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* 13062306a36Sopenharmony_ci * If @parent is not origin layer connectable, then copy up 13162306a36Sopenharmony_ci * @next which is origin layer connectable and we are done. 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_ci if (ovl_connectable_layer(parent) < origin_layer) { 13462306a36Sopenharmony_ci err = ovl_encode_maybe_copy_up(next); 13562306a36Sopenharmony_ci break; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* If @parent is connected or indexed we are done */ 13962306a36Sopenharmony_ci if (ovl_dentry_test_flag(OVL_E_CONNECTED, parent) || 14062306a36Sopenharmony_ci ovl_test_flag(OVL_INDEX, d_inode(parent))) 14162306a36Sopenharmony_ci break; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci dput(next); 14462306a36Sopenharmony_ci next = parent; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci dput(parent); 14862306a36Sopenharmony_ci dput(next); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (!err) 15162306a36Sopenharmony_ci ovl_dentry_set_flag(OVL_E_CONNECTED, dentry); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci return err ?: origin_layer; 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci/* 15762306a36Sopenharmony_ci * We only need to encode origin if there is a chance that the same object was 15862306a36Sopenharmony_ci * encoded pre copy up and then we need to stay consistent with the same 15962306a36Sopenharmony_ci * encoding also after copy up. If non-pure upper is not indexed, then it was 16062306a36Sopenharmony_ci * copied up before NFS export was enabled. In that case we don't need to worry 16162306a36Sopenharmony_ci * about staying consistent with pre copy up encoding and we encode an upper 16262306a36Sopenharmony_ci * file handle. Overlay root dentry is a private case of non-indexed upper. 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * The following table summarizes the different file handle encodings used for 16562306a36Sopenharmony_ci * different overlay object types: 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * Object type | Encoding 16862306a36Sopenharmony_ci * -------------------------------- 16962306a36Sopenharmony_ci * Pure upper | U 17062306a36Sopenharmony_ci * Non-indexed upper | U 17162306a36Sopenharmony_ci * Indexed upper | L (*) 17262306a36Sopenharmony_ci * Non-upper | L (*) 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * U = upper file handle 17562306a36Sopenharmony_ci * L = lower file handle 17662306a36Sopenharmony_ci * 17762306a36Sopenharmony_ci * (*) Decoding a connected overlay dir from real lower dentry is not always 17862306a36Sopenharmony_ci * possible when there are redirects in lower layers and non-indexed merge dirs. 17962306a36Sopenharmony_ci * To mitigate those case, we may copy up the lower dir ancestor before encode 18062306a36Sopenharmony_ci * of a decodable file handle for non-upper dir. 18162306a36Sopenharmony_ci * 18262306a36Sopenharmony_ci * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_cistatic int ovl_check_encode_origin(struct dentry *dentry) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct ovl_fs *ofs = OVL_FS(dentry->d_sb); 18762306a36Sopenharmony_ci bool decodable = ofs->config.nfs_export; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* Lower file handle for non-upper non-decodable */ 19062306a36Sopenharmony_ci if (!ovl_dentry_upper(dentry) && !decodable) 19162306a36Sopenharmony_ci return 1; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* Upper file handle for pure upper */ 19462306a36Sopenharmony_ci if (!ovl_dentry_lower(dentry)) 19562306a36Sopenharmony_ci return 0; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* 19862306a36Sopenharmony_ci * Root is never indexed, so if there's an upper layer, encode upper for 19962306a36Sopenharmony_ci * root. 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ci if (dentry == dentry->d_sb->s_root) 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* 20562306a36Sopenharmony_ci * Upper decodable file handle for non-indexed upper. 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ci if (ovl_dentry_upper(dentry) && decodable && 20862306a36Sopenharmony_ci !ovl_test_flag(OVL_INDEX, d_inode(dentry))) 20962306a36Sopenharmony_ci return 0; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* 21262306a36Sopenharmony_ci * Decoding a merge dir, whose origin's ancestor is under a redirected 21362306a36Sopenharmony_ci * lower dir or under a non-indexed upper is not always possible. 21462306a36Sopenharmony_ci * ovl_connect_layer() will try to make origin's layer "connected" by 21562306a36Sopenharmony_ci * copying up a "connectable" ancestor. 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_ci if (d_is_dir(dentry) && ovl_upper_mnt(ofs) && decodable) 21862306a36Sopenharmony_ci return ovl_connect_layer(dentry); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* Lower file handle for indexed and non-upper dir/non-dir */ 22162306a36Sopenharmony_ci return 1; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, 22562306a36Sopenharmony_ci u32 *fid, int buflen) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci struct ovl_fh *fh = NULL; 22862306a36Sopenharmony_ci int err, enc_lower; 22962306a36Sopenharmony_ci int len; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* 23262306a36Sopenharmony_ci * Check if we should encode a lower or upper file handle and maybe 23362306a36Sopenharmony_ci * copy up an ancestor to make lower file handle connectable. 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ci err = enc_lower = ovl_check_encode_origin(dentry); 23662306a36Sopenharmony_ci if (enc_lower < 0) 23762306a36Sopenharmony_ci goto fail; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Encode an upper or lower file handle */ 24062306a36Sopenharmony_ci fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_dentry_lower(dentry) : 24162306a36Sopenharmony_ci ovl_dentry_upper(dentry), !enc_lower); 24262306a36Sopenharmony_ci if (IS_ERR(fh)) 24362306a36Sopenharmony_ci return PTR_ERR(fh); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci len = OVL_FH_LEN(fh); 24662306a36Sopenharmony_ci if (len <= buflen) 24762306a36Sopenharmony_ci memcpy(fid, fh, len); 24862306a36Sopenharmony_ci err = len; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ciout: 25162306a36Sopenharmony_ci kfree(fh); 25262306a36Sopenharmony_ci return err; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cifail: 25562306a36Sopenharmony_ci pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n", 25662306a36Sopenharmony_ci dentry, err); 25762306a36Sopenharmony_ci goto out; 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistatic int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len, 26162306a36Sopenharmony_ci struct inode *parent) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci struct ovl_fs *ofs = OVL_FS(inode->i_sb); 26462306a36Sopenharmony_ci struct dentry *dentry; 26562306a36Sopenharmony_ci int bytes, buflen = *max_len << 2; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* TODO: encode connectable file handles */ 26862306a36Sopenharmony_ci if (parent) 26962306a36Sopenharmony_ci return FILEID_INVALID; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci dentry = d_find_any_alias(inode); 27262306a36Sopenharmony_ci if (!dentry) 27362306a36Sopenharmony_ci return FILEID_INVALID; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen); 27662306a36Sopenharmony_ci dput(dentry); 27762306a36Sopenharmony_ci if (bytes <= 0) 27862306a36Sopenharmony_ci return FILEID_INVALID; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci *max_len = bytes >> 2; 28162306a36Sopenharmony_ci if (bytes > buflen) 28262306a36Sopenharmony_ci return FILEID_INVALID; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci return OVL_FILEID_V1; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci/* 28862306a36Sopenharmony_ci * Find or instantiate an overlay dentry from real dentries and index. 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_cistatic struct dentry *ovl_obtain_alias(struct super_block *sb, 29162306a36Sopenharmony_ci struct dentry *upper_alias, 29262306a36Sopenharmony_ci struct ovl_path *lowerpath, 29362306a36Sopenharmony_ci struct dentry *index) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci struct dentry *lower = lowerpath ? lowerpath->dentry : NULL; 29662306a36Sopenharmony_ci struct dentry *upper = upper_alias ?: index; 29762306a36Sopenharmony_ci struct dentry *dentry; 29862306a36Sopenharmony_ci struct inode *inode = NULL; 29962306a36Sopenharmony_ci struct ovl_entry *oe; 30062306a36Sopenharmony_ci struct ovl_inode_params oip = { 30162306a36Sopenharmony_ci .index = index, 30262306a36Sopenharmony_ci }; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* We get overlay directory dentries with ovl_lookup_real() */ 30562306a36Sopenharmony_ci if (d_is_dir(upper ?: lower)) 30662306a36Sopenharmony_ci return ERR_PTR(-EIO); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci oe = ovl_alloc_entry(!!lower); 30962306a36Sopenharmony_ci if (!oe) 31062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci oip.upperdentry = dget(upper); 31362306a36Sopenharmony_ci if (lower) { 31462306a36Sopenharmony_ci ovl_lowerstack(oe)->dentry = dget(lower); 31562306a36Sopenharmony_ci ovl_lowerstack(oe)->layer = lowerpath->layer; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci oip.oe = oe; 31862306a36Sopenharmony_ci inode = ovl_get_inode(sb, &oip); 31962306a36Sopenharmony_ci if (IS_ERR(inode)) { 32062306a36Sopenharmony_ci ovl_free_entry(oe); 32162306a36Sopenharmony_ci dput(upper); 32262306a36Sopenharmony_ci return ERR_CAST(inode); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (upper) 32662306a36Sopenharmony_ci ovl_set_flag(OVL_UPPERDATA, inode); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci dentry = d_find_any_alias(inode); 32962306a36Sopenharmony_ci if (dentry) 33062306a36Sopenharmony_ci goto out_iput; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci dentry = d_alloc_anon(inode->i_sb); 33362306a36Sopenharmony_ci if (unlikely(!dentry)) 33462306a36Sopenharmony_ci goto nomem; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (upper_alias) 33762306a36Sopenharmony_ci ovl_dentry_set_upper_alias(dentry); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci ovl_dentry_init_reval(dentry, upper, OVL_I_E(inode)); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci return d_instantiate_anon(dentry, inode); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cinomem: 34462306a36Sopenharmony_ci dput(dentry); 34562306a36Sopenharmony_ci dentry = ERR_PTR(-ENOMEM); 34662306a36Sopenharmony_ciout_iput: 34762306a36Sopenharmony_ci iput(inode); 34862306a36Sopenharmony_ci return dentry; 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/* Get the upper or lower dentry in stack whose on layer @idx */ 35262306a36Sopenharmony_cistatic struct dentry *ovl_dentry_real_at(struct dentry *dentry, int idx) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci struct ovl_entry *oe = OVL_E(dentry); 35562306a36Sopenharmony_ci struct ovl_path *lowerstack = ovl_lowerstack(oe); 35662306a36Sopenharmony_ci int i; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if (!idx) 35962306a36Sopenharmony_ci return ovl_dentry_upper(dentry); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci for (i = 0; i < ovl_numlower(oe); i++) { 36262306a36Sopenharmony_ci if (lowerstack[i].layer->idx == idx) 36362306a36Sopenharmony_ci return lowerstack[i].dentry; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci return NULL; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci/* 37062306a36Sopenharmony_ci * Lookup a child overlay dentry to get a connected overlay dentry whose real 37162306a36Sopenharmony_ci * dentry is @real. If @real is on upper layer, we lookup a child overlay 37262306a36Sopenharmony_ci * dentry with the same name as the real dentry. Otherwise, we need to consult 37362306a36Sopenharmony_ci * index for lookup. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_cistatic struct dentry *ovl_lookup_real_one(struct dentry *connected, 37662306a36Sopenharmony_ci struct dentry *real, 37762306a36Sopenharmony_ci const struct ovl_layer *layer) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci struct inode *dir = d_inode(connected); 38062306a36Sopenharmony_ci struct dentry *this, *parent = NULL; 38162306a36Sopenharmony_ci struct name_snapshot name; 38262306a36Sopenharmony_ci int err; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci /* 38562306a36Sopenharmony_ci * Lookup child overlay dentry by real name. The dir mutex protects us 38662306a36Sopenharmony_ci * from racing with overlay rename. If the overlay dentry that is above 38762306a36Sopenharmony_ci * real has already been moved to a parent that is not under the 38862306a36Sopenharmony_ci * connected overlay dir, we return -ECHILD and restart the lookup of 38962306a36Sopenharmony_ci * connected real path from the top. 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ci inode_lock_nested(dir, I_MUTEX_PARENT); 39262306a36Sopenharmony_ci err = -ECHILD; 39362306a36Sopenharmony_ci parent = dget_parent(real); 39462306a36Sopenharmony_ci if (ovl_dentry_real_at(connected, layer->idx) != parent) 39562306a36Sopenharmony_ci goto fail; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci /* 39862306a36Sopenharmony_ci * We also need to take a snapshot of real dentry name to protect us 39962306a36Sopenharmony_ci * from racing with underlying layer rename. In this case, we don't 40062306a36Sopenharmony_ci * care about returning ESTALE, only from dereferencing a free name 40162306a36Sopenharmony_ci * pointer because we hold no lock on the real dentry. 40262306a36Sopenharmony_ci */ 40362306a36Sopenharmony_ci take_dentry_name_snapshot(&name, real); 40462306a36Sopenharmony_ci /* 40562306a36Sopenharmony_ci * No idmap handling here: it's an internal lookup. Could skip 40662306a36Sopenharmony_ci * permission checking altogether, but for now just use non-idmap 40762306a36Sopenharmony_ci * transformed ids. 40862306a36Sopenharmony_ci */ 40962306a36Sopenharmony_ci this = lookup_one_len(name.name.name, connected, name.name.len); 41062306a36Sopenharmony_ci release_dentry_name_snapshot(&name); 41162306a36Sopenharmony_ci err = PTR_ERR(this); 41262306a36Sopenharmony_ci if (IS_ERR(this)) { 41362306a36Sopenharmony_ci goto fail; 41462306a36Sopenharmony_ci } else if (!this || !this->d_inode) { 41562306a36Sopenharmony_ci dput(this); 41662306a36Sopenharmony_ci err = -ENOENT; 41762306a36Sopenharmony_ci goto fail; 41862306a36Sopenharmony_ci } else if (ovl_dentry_real_at(this, layer->idx) != real) { 41962306a36Sopenharmony_ci dput(this); 42062306a36Sopenharmony_ci err = -ESTALE; 42162306a36Sopenharmony_ci goto fail; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ciout: 42562306a36Sopenharmony_ci dput(parent); 42662306a36Sopenharmony_ci inode_unlock(dir); 42762306a36Sopenharmony_ci return this; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cifail: 43062306a36Sopenharmony_ci pr_warn_ratelimited("failed to lookup one by real (%pd2, layer=%d, connected=%pd2, err=%i)\n", 43162306a36Sopenharmony_ci real, layer->idx, connected, err); 43262306a36Sopenharmony_ci this = ERR_PTR(err); 43362306a36Sopenharmony_ci goto out; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic struct dentry *ovl_lookup_real(struct super_block *sb, 43762306a36Sopenharmony_ci struct dentry *real, 43862306a36Sopenharmony_ci const struct ovl_layer *layer); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci/* 44162306a36Sopenharmony_ci * Lookup an indexed or hashed overlay dentry by real inode. 44262306a36Sopenharmony_ci */ 44362306a36Sopenharmony_cistatic struct dentry *ovl_lookup_real_inode(struct super_block *sb, 44462306a36Sopenharmony_ci struct dentry *real, 44562306a36Sopenharmony_ci const struct ovl_layer *layer) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct ovl_fs *ofs = OVL_FS(sb); 44862306a36Sopenharmony_ci struct dentry *index = NULL; 44962306a36Sopenharmony_ci struct dentry *this = NULL; 45062306a36Sopenharmony_ci struct inode *inode; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /* 45362306a36Sopenharmony_ci * Decoding upper dir from index is expensive, so first try to lookup 45462306a36Sopenharmony_ci * overlay dentry in inode/dcache. 45562306a36Sopenharmony_ci */ 45662306a36Sopenharmony_ci inode = ovl_lookup_inode(sb, real, !layer->idx); 45762306a36Sopenharmony_ci if (IS_ERR(inode)) 45862306a36Sopenharmony_ci return ERR_CAST(inode); 45962306a36Sopenharmony_ci if (inode) { 46062306a36Sopenharmony_ci this = d_find_any_alias(inode); 46162306a36Sopenharmony_ci iput(inode); 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci /* 46562306a36Sopenharmony_ci * For decoded lower dir file handle, lookup index by origin to check 46662306a36Sopenharmony_ci * if lower dir was copied up and and/or removed. 46762306a36Sopenharmony_ci */ 46862306a36Sopenharmony_ci if (!this && layer->idx && ofs->indexdir && !WARN_ON(!d_is_dir(real))) { 46962306a36Sopenharmony_ci index = ovl_lookup_index(ofs, NULL, real, false); 47062306a36Sopenharmony_ci if (IS_ERR(index)) 47162306a36Sopenharmony_ci return index; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* Get connected upper overlay dir from index */ 47562306a36Sopenharmony_ci if (index) { 47662306a36Sopenharmony_ci struct dentry *upper = ovl_index_upper(ofs, index, true); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci dput(index); 47962306a36Sopenharmony_ci if (IS_ERR_OR_NULL(upper)) 48062306a36Sopenharmony_ci return upper; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* 48362306a36Sopenharmony_ci * ovl_lookup_real() in lower layer may call recursively once to 48462306a36Sopenharmony_ci * ovl_lookup_real() in upper layer. The first level call walks 48562306a36Sopenharmony_ci * back lower parents to the topmost indexed parent. The second 48662306a36Sopenharmony_ci * recursive call walks back from indexed upper to the topmost 48762306a36Sopenharmony_ci * connected/hashed upper parent (or up to root). 48862306a36Sopenharmony_ci */ 48962306a36Sopenharmony_ci this = ovl_lookup_real(sb, upper, &ofs->layers[0]); 49062306a36Sopenharmony_ci dput(upper); 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if (IS_ERR_OR_NULL(this)) 49462306a36Sopenharmony_ci return this; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci if (ovl_dentry_real_at(this, layer->idx) != real) { 49762306a36Sopenharmony_ci dput(this); 49862306a36Sopenharmony_ci this = ERR_PTR(-EIO); 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci return this; 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci/* 50562306a36Sopenharmony_ci * Lookup an indexed or hashed overlay dentry, whose real dentry is an 50662306a36Sopenharmony_ci * ancestor of @real. 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_cistatic struct dentry *ovl_lookup_real_ancestor(struct super_block *sb, 50962306a36Sopenharmony_ci struct dentry *real, 51062306a36Sopenharmony_ci const struct ovl_layer *layer) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci struct dentry *next, *parent = NULL; 51362306a36Sopenharmony_ci struct dentry *ancestor = ERR_PTR(-EIO); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci if (real == layer->mnt->mnt_root) 51662306a36Sopenharmony_ci return dget(sb->s_root); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* Find the topmost indexed or hashed ancestor */ 51962306a36Sopenharmony_ci next = dget(real); 52062306a36Sopenharmony_ci for (;;) { 52162306a36Sopenharmony_ci parent = dget_parent(next); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci /* 52462306a36Sopenharmony_ci * Lookup a matching overlay dentry in inode/dentry 52562306a36Sopenharmony_ci * cache or in index by real inode. 52662306a36Sopenharmony_ci */ 52762306a36Sopenharmony_ci ancestor = ovl_lookup_real_inode(sb, next, layer); 52862306a36Sopenharmony_ci if (ancestor) 52962306a36Sopenharmony_ci break; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci if (parent == layer->mnt->mnt_root) { 53262306a36Sopenharmony_ci ancestor = dget(sb->s_root); 53362306a36Sopenharmony_ci break; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci /* 53762306a36Sopenharmony_ci * If @real has been moved out of the layer root directory, 53862306a36Sopenharmony_ci * we will eventully hit the real fs root. This cannot happen 53962306a36Sopenharmony_ci * by legit overlay rename, so we return error in that case. 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_ci if (parent == next) { 54262306a36Sopenharmony_ci ancestor = ERR_PTR(-EXDEV); 54362306a36Sopenharmony_ci break; 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci dput(next); 54762306a36Sopenharmony_ci next = parent; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci dput(parent); 55162306a36Sopenharmony_ci dput(next); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci return ancestor; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci/* 55762306a36Sopenharmony_ci * Lookup a connected overlay dentry whose real dentry is @real. 55862306a36Sopenharmony_ci * If @real is on upper layer, we lookup a child overlay dentry with the same 55962306a36Sopenharmony_ci * path the real dentry. Otherwise, we need to consult index for lookup. 56062306a36Sopenharmony_ci */ 56162306a36Sopenharmony_cistatic struct dentry *ovl_lookup_real(struct super_block *sb, 56262306a36Sopenharmony_ci struct dentry *real, 56362306a36Sopenharmony_ci const struct ovl_layer *layer) 56462306a36Sopenharmony_ci{ 56562306a36Sopenharmony_ci struct dentry *connected; 56662306a36Sopenharmony_ci int err = 0; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci connected = ovl_lookup_real_ancestor(sb, real, layer); 56962306a36Sopenharmony_ci if (IS_ERR(connected)) 57062306a36Sopenharmony_ci return connected; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci while (!err) { 57362306a36Sopenharmony_ci struct dentry *next, *this; 57462306a36Sopenharmony_ci struct dentry *parent = NULL; 57562306a36Sopenharmony_ci struct dentry *real_connected = ovl_dentry_real_at(connected, 57662306a36Sopenharmony_ci layer->idx); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (real_connected == real) 57962306a36Sopenharmony_ci break; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci /* Find the topmost dentry not yet connected */ 58262306a36Sopenharmony_ci next = dget(real); 58362306a36Sopenharmony_ci for (;;) { 58462306a36Sopenharmony_ci parent = dget_parent(next); 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (parent == real_connected) 58762306a36Sopenharmony_ci break; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci /* 59062306a36Sopenharmony_ci * If real has been moved out of 'real_connected', 59162306a36Sopenharmony_ci * we will not find 'real_connected' and hit the layer 59262306a36Sopenharmony_ci * root. In that case, we need to restart connecting. 59362306a36Sopenharmony_ci * This game can go on forever in the worst case. We 59462306a36Sopenharmony_ci * may want to consider taking s_vfs_rename_mutex if 59562306a36Sopenharmony_ci * this happens more than once. 59662306a36Sopenharmony_ci */ 59762306a36Sopenharmony_ci if (parent == layer->mnt->mnt_root) { 59862306a36Sopenharmony_ci dput(connected); 59962306a36Sopenharmony_ci connected = dget(sb->s_root); 60062306a36Sopenharmony_ci break; 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* 60462306a36Sopenharmony_ci * If real file has been moved out of the layer root 60562306a36Sopenharmony_ci * directory, we will eventully hit the real fs root. 60662306a36Sopenharmony_ci * This cannot happen by legit overlay rename, so we 60762306a36Sopenharmony_ci * return error in that case. 60862306a36Sopenharmony_ci */ 60962306a36Sopenharmony_ci if (parent == next) { 61062306a36Sopenharmony_ci err = -EXDEV; 61162306a36Sopenharmony_ci break; 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci dput(next); 61562306a36Sopenharmony_ci next = parent; 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (!err) { 61962306a36Sopenharmony_ci this = ovl_lookup_real_one(connected, next, layer); 62062306a36Sopenharmony_ci if (IS_ERR(this)) 62162306a36Sopenharmony_ci err = PTR_ERR(this); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* 62462306a36Sopenharmony_ci * Lookup of child in overlay can fail when racing with 62562306a36Sopenharmony_ci * overlay rename of child away from 'connected' parent. 62662306a36Sopenharmony_ci * In this case, we need to restart the lookup from the 62762306a36Sopenharmony_ci * top, because we cannot trust that 'real_connected' is 62862306a36Sopenharmony_ci * still an ancestor of 'real'. There is a good chance 62962306a36Sopenharmony_ci * that the renamed overlay ancestor is now in cache, so 63062306a36Sopenharmony_ci * ovl_lookup_real_ancestor() will find it and we can 63162306a36Sopenharmony_ci * continue to connect exactly from where lookup failed. 63262306a36Sopenharmony_ci */ 63362306a36Sopenharmony_ci if (err == -ECHILD) { 63462306a36Sopenharmony_ci this = ovl_lookup_real_ancestor(sb, real, 63562306a36Sopenharmony_ci layer); 63662306a36Sopenharmony_ci err = PTR_ERR_OR_ZERO(this); 63762306a36Sopenharmony_ci } 63862306a36Sopenharmony_ci if (!err) { 63962306a36Sopenharmony_ci dput(connected); 64062306a36Sopenharmony_ci connected = this; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci } 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci dput(parent); 64562306a36Sopenharmony_ci dput(next); 64662306a36Sopenharmony_ci } 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci if (err) 64962306a36Sopenharmony_ci goto fail; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci return connected; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_cifail: 65462306a36Sopenharmony_ci pr_warn_ratelimited("failed to lookup by real (%pd2, layer=%d, connected=%pd2, err=%i)\n", 65562306a36Sopenharmony_ci real, layer->idx, connected, err); 65662306a36Sopenharmony_ci dput(connected); 65762306a36Sopenharmony_ci return ERR_PTR(err); 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci/* 66162306a36Sopenharmony_ci * Get an overlay dentry from upper/lower real dentries and index. 66262306a36Sopenharmony_ci */ 66362306a36Sopenharmony_cistatic struct dentry *ovl_get_dentry(struct super_block *sb, 66462306a36Sopenharmony_ci struct dentry *upper, 66562306a36Sopenharmony_ci struct ovl_path *lowerpath, 66662306a36Sopenharmony_ci struct dentry *index) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci struct ovl_fs *ofs = OVL_FS(sb); 66962306a36Sopenharmony_ci const struct ovl_layer *layer = upper ? &ofs->layers[0] : lowerpath->layer; 67062306a36Sopenharmony_ci struct dentry *real = upper ?: (index ?: lowerpath->dentry); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci /* 67362306a36Sopenharmony_ci * Obtain a disconnected overlay dentry from a non-dir real dentry 67462306a36Sopenharmony_ci * and index. 67562306a36Sopenharmony_ci */ 67662306a36Sopenharmony_ci if (!d_is_dir(real)) 67762306a36Sopenharmony_ci return ovl_obtain_alias(sb, upper, lowerpath, index); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci /* Removed empty directory? */ 68062306a36Sopenharmony_ci if ((real->d_flags & DCACHE_DISCONNECTED) || d_unhashed(real)) 68162306a36Sopenharmony_ci return ERR_PTR(-ENOENT); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci /* 68462306a36Sopenharmony_ci * If real dentry is connected and hashed, get a connected overlay 68562306a36Sopenharmony_ci * dentry whose real dentry is @real. 68662306a36Sopenharmony_ci */ 68762306a36Sopenharmony_ci return ovl_lookup_real(sb, real, layer); 68862306a36Sopenharmony_ci} 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_cistatic struct dentry *ovl_upper_fh_to_d(struct super_block *sb, 69162306a36Sopenharmony_ci struct ovl_fh *fh) 69262306a36Sopenharmony_ci{ 69362306a36Sopenharmony_ci struct ovl_fs *ofs = OVL_FS(sb); 69462306a36Sopenharmony_ci struct dentry *dentry; 69562306a36Sopenharmony_ci struct dentry *upper; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci if (!ovl_upper_mnt(ofs)) 69862306a36Sopenharmony_ci return ERR_PTR(-EACCES); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci upper = ovl_decode_real_fh(ofs, fh, ovl_upper_mnt(ofs), true); 70162306a36Sopenharmony_ci if (IS_ERR_OR_NULL(upper)) 70262306a36Sopenharmony_ci return upper; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci dentry = ovl_get_dentry(sb, upper, NULL, NULL); 70562306a36Sopenharmony_ci dput(upper); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci return dentry; 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic struct dentry *ovl_lower_fh_to_d(struct super_block *sb, 71162306a36Sopenharmony_ci struct ovl_fh *fh) 71262306a36Sopenharmony_ci{ 71362306a36Sopenharmony_ci struct ovl_fs *ofs = OVL_FS(sb); 71462306a36Sopenharmony_ci struct ovl_path origin = { }; 71562306a36Sopenharmony_ci struct ovl_path *stack = &origin; 71662306a36Sopenharmony_ci struct dentry *dentry = NULL; 71762306a36Sopenharmony_ci struct dentry *index = NULL; 71862306a36Sopenharmony_ci struct inode *inode; 71962306a36Sopenharmony_ci int err; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci /* First lookup overlay inode in inode cache by origin fh */ 72262306a36Sopenharmony_ci err = ovl_check_origin_fh(ofs, fh, false, NULL, &stack); 72362306a36Sopenharmony_ci if (err) 72462306a36Sopenharmony_ci return ERR_PTR(err); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci if (!d_is_dir(origin.dentry) || 72762306a36Sopenharmony_ci !(origin.dentry->d_flags & DCACHE_DISCONNECTED)) { 72862306a36Sopenharmony_ci inode = ovl_lookup_inode(sb, origin.dentry, false); 72962306a36Sopenharmony_ci err = PTR_ERR(inode); 73062306a36Sopenharmony_ci if (IS_ERR(inode)) 73162306a36Sopenharmony_ci goto out_err; 73262306a36Sopenharmony_ci if (inode) { 73362306a36Sopenharmony_ci dentry = d_find_any_alias(inode); 73462306a36Sopenharmony_ci iput(inode); 73562306a36Sopenharmony_ci if (dentry) 73662306a36Sopenharmony_ci goto out; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci } 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci /* Then lookup indexed upper/whiteout by origin fh */ 74162306a36Sopenharmony_ci if (ofs->indexdir) { 74262306a36Sopenharmony_ci index = ovl_get_index_fh(ofs, fh); 74362306a36Sopenharmony_ci err = PTR_ERR(index); 74462306a36Sopenharmony_ci if (IS_ERR(index)) { 74562306a36Sopenharmony_ci index = NULL; 74662306a36Sopenharmony_ci goto out_err; 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci /* Then try to get a connected upper dir by index */ 75162306a36Sopenharmony_ci if (index && d_is_dir(index)) { 75262306a36Sopenharmony_ci struct dentry *upper = ovl_index_upper(ofs, index, true); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci err = PTR_ERR(upper); 75562306a36Sopenharmony_ci if (IS_ERR_OR_NULL(upper)) 75662306a36Sopenharmony_ci goto out_err; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci dentry = ovl_get_dentry(sb, upper, NULL, NULL); 75962306a36Sopenharmony_ci dput(upper); 76062306a36Sopenharmony_ci goto out; 76162306a36Sopenharmony_ci } 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci /* Find origin.dentry again with ovl_acceptable() layer check */ 76462306a36Sopenharmony_ci if (d_is_dir(origin.dentry)) { 76562306a36Sopenharmony_ci dput(origin.dentry); 76662306a36Sopenharmony_ci origin.dentry = NULL; 76762306a36Sopenharmony_ci err = ovl_check_origin_fh(ofs, fh, true, NULL, &stack); 76862306a36Sopenharmony_ci if (err) 76962306a36Sopenharmony_ci goto out_err; 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci if (index) { 77262306a36Sopenharmony_ci err = ovl_verify_origin(ofs, index, origin.dentry, false); 77362306a36Sopenharmony_ci if (err) 77462306a36Sopenharmony_ci goto out_err; 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci /* Get a connected non-upper dir or disconnected non-dir */ 77862306a36Sopenharmony_ci dentry = ovl_get_dentry(sb, NULL, &origin, index); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ciout: 78162306a36Sopenharmony_ci dput(origin.dentry); 78262306a36Sopenharmony_ci dput(index); 78362306a36Sopenharmony_ci return dentry; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ciout_err: 78662306a36Sopenharmony_ci dentry = ERR_PTR(err); 78762306a36Sopenharmony_ci goto out; 78862306a36Sopenharmony_ci} 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_cistatic struct ovl_fh *ovl_fid_to_fh(struct fid *fid, int buflen, int fh_type) 79162306a36Sopenharmony_ci{ 79262306a36Sopenharmony_ci struct ovl_fh *fh; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /* If on-wire inner fid is aligned - nothing to do */ 79562306a36Sopenharmony_ci if (fh_type == OVL_FILEID_V1) 79662306a36Sopenharmony_ci return (struct ovl_fh *)fid; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci if (fh_type != OVL_FILEID_V0) 79962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (buflen <= OVL_FH_WIRE_OFFSET) 80262306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci fh = kzalloc(buflen, GFP_KERNEL); 80562306a36Sopenharmony_ci if (!fh) 80662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci /* Copy unaligned inner fh into aligned buffer */ 80962306a36Sopenharmony_ci memcpy(fh->buf, fid, buflen - OVL_FH_WIRE_OFFSET); 81062306a36Sopenharmony_ci return fh; 81162306a36Sopenharmony_ci} 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_cistatic struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid, 81462306a36Sopenharmony_ci int fh_len, int fh_type) 81562306a36Sopenharmony_ci{ 81662306a36Sopenharmony_ci struct dentry *dentry = NULL; 81762306a36Sopenharmony_ci struct ovl_fh *fh = NULL; 81862306a36Sopenharmony_ci int len = fh_len << 2; 81962306a36Sopenharmony_ci unsigned int flags = 0; 82062306a36Sopenharmony_ci int err; 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci fh = ovl_fid_to_fh(fid, len, fh_type); 82362306a36Sopenharmony_ci err = PTR_ERR(fh); 82462306a36Sopenharmony_ci if (IS_ERR(fh)) 82562306a36Sopenharmony_ci goto out_err; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci err = ovl_check_fh_len(fh, len); 82862306a36Sopenharmony_ci if (err) 82962306a36Sopenharmony_ci goto out_err; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci flags = fh->fb.flags; 83262306a36Sopenharmony_ci dentry = (flags & OVL_FH_FLAG_PATH_UPPER) ? 83362306a36Sopenharmony_ci ovl_upper_fh_to_d(sb, fh) : 83462306a36Sopenharmony_ci ovl_lower_fh_to_d(sb, fh); 83562306a36Sopenharmony_ci err = PTR_ERR(dentry); 83662306a36Sopenharmony_ci if (IS_ERR(dentry) && err != -ESTALE) 83762306a36Sopenharmony_ci goto out_err; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ciout: 84062306a36Sopenharmony_ci /* We may have needed to re-align OVL_FILEID_V0 */ 84162306a36Sopenharmony_ci if (!IS_ERR_OR_NULL(fh) && fh != (void *)fid) 84262306a36Sopenharmony_ci kfree(fh); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci return dentry; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ciout_err: 84762306a36Sopenharmony_ci pr_warn_ratelimited("failed to decode file handle (len=%d, type=%d, flags=%x, err=%i)\n", 84862306a36Sopenharmony_ci fh_len, fh_type, flags, err); 84962306a36Sopenharmony_ci dentry = ERR_PTR(err); 85062306a36Sopenharmony_ci goto out; 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_cistatic struct dentry *ovl_fh_to_parent(struct super_block *sb, struct fid *fid, 85462306a36Sopenharmony_ci int fh_len, int fh_type) 85562306a36Sopenharmony_ci{ 85662306a36Sopenharmony_ci pr_warn_ratelimited("connectable file handles not supported; use 'no_subtree_check' exportfs option.\n"); 85762306a36Sopenharmony_ci return ERR_PTR(-EACCES); 85862306a36Sopenharmony_ci} 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_cistatic int ovl_get_name(struct dentry *parent, char *name, 86162306a36Sopenharmony_ci struct dentry *child) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci /* 86462306a36Sopenharmony_ci * ovl_fh_to_dentry() returns connected dir overlay dentries and 86562306a36Sopenharmony_ci * ovl_fh_to_parent() is not implemented, so we should not get here. 86662306a36Sopenharmony_ci */ 86762306a36Sopenharmony_ci WARN_ON_ONCE(1); 86862306a36Sopenharmony_ci return -EIO; 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_cistatic struct dentry *ovl_get_parent(struct dentry *dentry) 87262306a36Sopenharmony_ci{ 87362306a36Sopenharmony_ci /* 87462306a36Sopenharmony_ci * ovl_fh_to_dentry() returns connected dir overlay dentries, so we 87562306a36Sopenharmony_ci * should not get here. 87662306a36Sopenharmony_ci */ 87762306a36Sopenharmony_ci WARN_ON_ONCE(1); 87862306a36Sopenharmony_ci return ERR_PTR(-EIO); 87962306a36Sopenharmony_ci} 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ciconst struct export_operations ovl_export_operations = { 88262306a36Sopenharmony_ci .encode_fh = ovl_encode_fh, 88362306a36Sopenharmony_ci .fh_to_dentry = ovl_fh_to_dentry, 88462306a36Sopenharmony_ci .fh_to_parent = ovl_fh_to_parent, 88562306a36Sopenharmony_ci .get_name = ovl_get_name, 88662306a36Sopenharmony_ci .get_parent = ovl_get_parent, 88762306a36Sopenharmony_ci}; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci/* encode_fh() encodes non-decodable file handles with nfs_export=off */ 89062306a36Sopenharmony_ciconst struct export_operations ovl_export_fid_operations = { 89162306a36Sopenharmony_ci .encode_fh = ovl_encode_fh, 89262306a36Sopenharmony_ci}; 893