868 lines · 22.3 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * Overlayfs NFS export support. * * Amir Goldstein <amir73il@gmail.com> * * Copyright (C) 2017-2018 CTERA Networks. All Rights Reserved. */ #include <linux/fs.h>#include <linux/cred.h>#include <linux/mount.h>#include <linux/namei.h>#include <linux/xattr.h>#include <linux/exportfs.h>#include <linux/ratelimit.h>#include "overlayfs.h" static int ovl_encode_maybe_copy_up(struct dentry *dentry){	int err; 	if (ovl_dentry_upper(dentry))		return 0; 	err = ovl_copy_up(dentry);	if (err) {		pr_warn_ratelimited("failed to copy up on encode (%pd2, err=%i)\n",				    dentry, err);	} 	return err;} /* * Before encoding a non-upper directory file handle from real layer N, we need * to check if it will be possible to reconnect an overlay dentry from the real * lower decoded dentry. This is done by following the overlay ancestry up to a * "layer N connected" ancestor and verifying that all parents along the way are * "layer N connectable". If an ancestor that is NOT "layer N connectable" is * found, we need to copy up an ancestor, which is "layer N connectable", thus * making that ancestor "layer N connected". For example: * * layer 1: /a * layer 2: /a/b/c * * The overlay dentry /a is NOT "layer 2 connectable", because if dir /a is * copied up and renamed, upper dir /a will be indexed by lower dir /a from * layer 1. The dir /a from layer 2 will never be indexed, so the algorithm (*) * in ovl_lookup_real_ancestor() will not be able to lookup a connected overlay * dentry from the connected lower dentry /a/b/c. * * To avoid this problem on decode time, we need to copy up an ancestor of * /a/b/c, which is "layer 2 connectable", on encode time. That ancestor is * /a/b. After copy up (and index) of /a/b, it will become "layer 2 connected" * and when the time comes to decode the file handle from lower dentry /a/b/c, * ovl_lookup_real_ancestor() will find the indexed ancestor /a/b and decoding * a connected overlay dentry will be accomplished. * * (*) the algorithm in ovl_lookup_real_ancestor() can be improved to lookup an * entry /a in the lower layers above layer N and find the indexed dir /a from * layer 1. If that improvement is made, then the check for "layer N connected" * will need to verify there are no redirects in lower layers above N. In the * example above, /a will be "layer 2 connectable". However, if layer 2 dir /a * is a target of a layer 1 redirect, then /a will NOT be "layer 2 connectable": * * layer 1: /A (redirect = /a) * layer 2: /a/b/c */ /* Return the lowest layer for encoding a connectable file handle */static int ovl_connectable_layer(struct dentry *dentry){	struct ovl_entry *oe = OVL_E(dentry); 	/* We can get overlay root from root of any layer */	if (dentry == dentry->d_sb->s_root)		return ovl_numlower(oe); 	/*	 * If it's an unindexed merge dir, then it's not connectable with any	 * lower layer	 */	if (ovl_dentry_upper(dentry) &&	    !ovl_test_flag(OVL_INDEX, d_inode(dentry)))		return 0; 	/* We can get upper/overlay path from indexed/lower dentry */	return ovl_lowerstack(oe)->layer->idx;} /* * @dentry is "connected" if all ancestors up to root or a "connected" ancestor * have the same uppermost lower layer as the origin's layer. We may need to * copy up a "connectable" ancestor to make it "connected". A "connected" dentry * cannot become non "connected", so cache positive result in dentry flags. * * Return the connected origin layer or < 0 on error. */static int ovl_connect_layer(struct dentry *dentry){	struct dentry *next, *parent = NULL;	struct ovl_entry *oe = OVL_E(dentry);	int origin_layer;	int err = 0; 	if (WARN_ON(dentry == dentry->d_sb->s_root) ||	    WARN_ON(!ovl_dentry_lower(dentry)))		return -EIO; 	origin_layer = ovl_lowerstack(oe)->layer->idx;	if (ovl_dentry_test_flag(OVL_E_CONNECTED, dentry))		return origin_layer; 	/* Find the topmost origin layer connectable ancestor of @dentry */	next = dget(dentry);	for (;;) {		parent = dget_parent(next);		if (WARN_ON(parent == next)) {			err = -EIO;			break;		} 		/*		 * If @parent is not origin layer connectable, then copy up		 * @next which is origin layer connectable and we are done.		 */		if (ovl_connectable_layer(parent) < origin_layer) {			err = ovl_encode_maybe_copy_up(next);			break;		} 		/* If @parent is connected or indexed we are done */		if (ovl_dentry_test_flag(OVL_E_CONNECTED, parent) ||		    ovl_test_flag(OVL_INDEX, d_inode(parent)))			break; 		dput(next);		next = parent;	} 	dput(parent);	dput(next); 	if (!err)		ovl_dentry_set_flag(OVL_E_CONNECTED, dentry); 	return err ?: origin_layer;} /* * We only need to encode origin if there is a chance that the same object was * encoded pre copy up and then we need to stay consistent with the same * encoding also after copy up. If non-pure upper is not indexed, then it was * copied up before NFS export was enabled. In that case we don't need to worry * about staying consistent with pre copy up encoding and we encode an upper * file handle. Overlay root dentry is a private case of non-indexed upper. * * The following table summarizes the different file handle encodings used for * different overlay object types: * *  Object type		| Encoding * -------------------------------- *  Pure upper		| U *  Non-indexed upper	| U *  Indexed upper	| L (*) *  Non-upper		| L (*) * * U = upper file handle * L = lower file handle * * (*) Decoding a connected overlay dir from real lower dentry is not always * possible when there are redirects in lower layers and non-indexed merge dirs. * To mitigate those case, we may copy up the lower dir ancestor before encode * of a decodable file handle for non-upper dir. * * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error. */static int ovl_check_encode_origin(struct inode *inode){	struct ovl_fs *ofs = OVL_FS(inode->i_sb);	bool decodable = ofs->config.nfs_export;	struct dentry *dentry;	int err; 	/* No upper layer? */	if (!ovl_upper_mnt(ofs))		return 1; 	/* Lower file handle for non-upper non-decodable */	if (!ovl_inode_upper(inode) && !decodable)		return 1; 	/* Upper file handle for pure upper */	if (!ovl_inode_lower(inode))		return 0; 	/*	 * Root is never indexed, so if there's an upper layer, encode upper for	 * root.	 */	if (inode == d_inode(inode->i_sb->s_root))		return 0; 	/*	 * Upper decodable file handle for non-indexed upper.	 */	if (ovl_inode_upper(inode) && decodable &&	    !ovl_test_flag(OVL_INDEX, inode))		return 0; 	/*	 * Decoding a merge dir, whose origin's ancestor is under a redirected	 * lower dir or under a non-indexed upper is not always possible.	 * ovl_connect_layer() will try to make origin's layer "connected" by	 * copying up a "connectable" ancestor.	 */	if (!decodable || !S_ISDIR(inode->i_mode))		return 1; 	dentry = d_find_any_alias(inode);	if (!dentry)		return -ENOENT; 	err = ovl_connect_layer(dentry);	dput(dentry);	if (err < 0)		return err; 	/* Lower file handle for indexed and non-upper dir/non-dir */	return 1;} static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode,			     u32 *fid, int buflen){	struct ovl_fh *fh = NULL;	int err, enc_lower;	int len; 	/*	 * Check if we should encode a lower or upper file handle and maybe	 * copy up an ancestor to make lower file handle connectable.	 */	err = enc_lower = ovl_check_encode_origin(inode);	if (enc_lower < 0)		goto fail; 	/* Encode an upper or lower file handle */	fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_inode_lower(inode) :				ovl_inode_upper(inode), !enc_lower);	if (IS_ERR(fh))		return PTR_ERR(fh); 	len = OVL_FH_LEN(fh);	if (len <= buflen)		memcpy(fid, fh, len);	err = len; out:	kfree(fh);	return err; fail:	pr_warn_ratelimited("failed to encode file handle (ino=%llu, err=%i)\n",			    inode->i_ino, err);	goto out;} static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,			 struct inode *parent){	struct ovl_fs *ofs = OVL_FS(inode->i_sb);	int bytes, buflen = *max_len << 2; 	/* TODO: encode connectable file handles */	if (parent)		return FILEID_INVALID; 	bytes = ovl_dentry_to_fid(ofs, inode, fid, buflen);	if (bytes <= 0)		return FILEID_INVALID; 	*max_len = bytes >> 2;	if (bytes > buflen)		return FILEID_INVALID; 	return OVL_FILEID_V1;} /* * Find or instantiate an overlay dentry from real dentries and index. */static struct dentry *ovl_obtain_alias(struct super_block *sb,				       struct dentry *upper_alias,				       struct ovl_path *lowerpath,				       struct dentry *index){	struct dentry *lower = lowerpath ? lowerpath->dentry : NULL;	struct dentry *upper = upper_alias ?: index;	struct inode *inode = NULL;	struct ovl_entry *oe;	struct ovl_inode_params oip = {		.index = index,	}; 	/* We get overlay directory dentries with ovl_lookup_real() */	if (d_is_dir(upper ?: lower))		return ERR_PTR(-EIO); 	oe = ovl_alloc_entry(!!lower);	if (!oe)		return ERR_PTR(-ENOMEM); 	oip.upperdentry = dget(upper);	if (lower) {		ovl_lowerstack(oe)->dentry = dget(lower);		ovl_lowerstack(oe)->layer = lowerpath->layer;	}	oip.oe = oe;	inode = ovl_get_inode(sb, &oip);	if (IS_ERR(inode)) {		ovl_free_entry(oe);		dput(upper);		return ERR_CAST(inode);	} 	if (upper)		ovl_set_flag(OVL_UPPERDATA, inode); 	return d_obtain_alias(inode);} /* Get the upper or lower dentry in stack whose on layer @idx */static struct dentry *ovl_dentry_real_at(struct dentry *dentry, int idx){	struct ovl_entry *oe = OVL_E(dentry);	struct ovl_path *lowerstack = ovl_lowerstack(oe);	int i; 	if (!idx)		return ovl_dentry_upper(dentry); 	for (i = 0; i < ovl_numlower(oe); i++) {		if (lowerstack[i].layer->idx == idx)			return lowerstack[i].dentry;	} 	return NULL;} /** * ovl_lookup_real_one -  Lookup a child overlay dentry to get an overlay dentry whose real dentry is given * @connected: parent overlay dentry * @real: given child real dentry * @layer: layer in which @real exists * * * Lookup a child overlay dentry in @connected with the same name as the @real * dentry.  Then check that the parent of the result is the real dentry for * @connected, and @real is the real dentry for the result. * * Returns: *   %-ECHILD if the parent of @real is no longer the real dentry for @connected. *   %-ESTALE if @real is not the real dentry of the found dentry. *   Otherwise the found dentry is returned. */static struct dentry *ovl_lookup_real_one(struct dentry *connected,					  struct dentry *real,					  const struct ovl_layer *layer){	struct dentry *this;	struct name_snapshot name;	int err; 	/*	 * We need to take a snapshot of real dentry name to protect us	 * from racing with underlying layer rename. In this case, we don't	 * care about returning ESTALE, only from dereferencing a free name	 * pointer because we hold no lock on the real dentry.	 */	take_dentry_name_snapshot(&name, real);	this = lookup_noperm_unlocked(&name.name, connected);	release_dentry_name_snapshot(&name); 	err = -ECHILD;	if (ovl_dentry_real_at(connected, layer->idx) != real->d_parent)		goto fail; 	err = PTR_ERR(this);	if (IS_ERR(this))		goto fail; 	err = -ENOENT;	if (!this || !this->d_inode)		goto fail; 	err = -ESTALE;	if (ovl_dentry_real_at(this, layer->idx) != real)		goto fail; 	return this; fail:	pr_warn_ratelimited("failed to lookup one by real (%pd2, layer=%d, connected=%pd2, err=%i)\n",			    real, layer->idx, connected, err);	if (!IS_ERR(this))		dput(this);	return ERR_PTR(err);} static struct dentry *ovl_lookup_real(struct super_block *sb,				      struct dentry *real,				      const struct ovl_layer *layer); /* * Lookup an indexed or hashed overlay dentry by real inode. */static struct dentry *ovl_lookup_real_inode(struct super_block *sb,					    struct dentry *real,					    const struct ovl_layer *layer){	struct ovl_fs *ofs = OVL_FS(sb);	struct dentry *index = NULL;	struct dentry *this = NULL;	struct inode *inode; 	/*	 * Decoding upper dir from index is expensive, so first try to lookup	 * overlay dentry in inode/dcache.	 */	inode = ovl_lookup_inode(sb, real, !layer->idx);	if (IS_ERR(inode))		return ERR_CAST(inode);	if (inode) {		this = d_find_any_alias(inode);		iput(inode);	} 	/*	 * For decoded lower dir file handle, lookup index by origin to check	 * if lower dir was copied up and and/or removed.	 */	if (!this && layer->idx && ovl_indexdir(sb) && !WARN_ON(!d_is_dir(real))) {		index = ovl_lookup_index(ofs, NULL, real, false);		if (IS_ERR(index))			return index;	} 	/* Get connected upper overlay dir from index */	if (index) {		struct dentry *upper = ovl_index_upper(ofs, index, true); 		dput(index);		if (IS_ERR_OR_NULL(upper))			return upper; 		/*		 * ovl_lookup_real() in lower layer may call recursively once to		 * ovl_lookup_real() in upper layer. The first level call walks		 * back lower parents to the topmost indexed parent. The second		 * recursive call walks back from indexed upper to the topmost		 * connected/hashed upper parent (or up to root).		 */		this = ovl_lookup_real(sb, upper, &ofs->layers[0]);		dput(upper);	} 	if (IS_ERR_OR_NULL(this))		return this; 	if (ovl_dentry_real_at(this, layer->idx) != real) {		dput(this);		this = ERR_PTR(-EIO);	} 	return this;} /* * Lookup an indexed or hashed overlay dentry, whose real dentry is an * ancestor of @real. */static struct dentry *ovl_lookup_real_ancestor(struct super_block *sb,					       struct dentry *real,					       const struct ovl_layer *layer){	struct dentry *next, *parent = NULL;	struct dentry *ancestor = ERR_PTR(-EIO); 	if (real == layer->mnt->mnt_root)		return dget(sb->s_root); 	/* Find the topmost indexed or hashed ancestor */	next = dget(real);	for (;;) {		parent = dget_parent(next); 		/*		 * Lookup a matching overlay dentry in inode/dentry

Lines 1–500 of 868.