Re: Stable inode numbers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Jul 22, 2016 at 01:55:56PM -0700, Vito Caputo wrote:

> The patch eliminates the errors from tar in the test I've been using
> to reproduce the user-reported issues.  However, I'm doubtful of it
> being a satisfactory general solution because the inode number of a
> pre-existing directory which undergoes copy-up spuriously changes.
> 
> There's probably a scenario where this still upsets tar when
> extracting over an partial tree pre-existing in the lower layer,
> adding names to existing directories, causing their inode numbers to
> change.
> 
> The relevant code where tar detects these shenanigans may be seen here:
> http://git.savannah.gnu.org/cgit/tar.git/tree/src/extract.c#n867
> 
> Perhaps we can come up with a better, more general solution without
> adding substantial complexity or overhead?

Here's another try.  It's simple enough, as to overhead, please let me know if
you are comfortable with this.

Thanks,
Miklos

---
From: Miklos Szeredi <mszeredi@xxxxxxxxxx>
Subject: ovl: optionally copy up directory on getattr

This is to make directory dev/ino stable.

Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxxxxx>
---
 fs/overlayfs/dir.c       |   15 +++++++++++++--
 fs/overlayfs/overlayfs.h |    6 ++++++
 fs/overlayfs/super.c     |   19 +++++++++++++++++++
 3 files changed, 38 insertions(+), 2 deletions(-)

--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -139,6 +139,15 @@ static int ovl_dir_getattr(struct vfsmou
 	enum ovl_path_type type;
 	struct path realpath;
 	const struct cred *old_cred;
+	bool devino_from_ovl = true;
+
+	if (ovl_copy_up_type(dentry) == OVL_COPY_UP_ON_GETATTR) {
+		err = ovl_copy_up(dentry);
+		if (err)
+			return err;
+
+		devino_from_ovl = false;
+	}
 
 	type = ovl_path_real(dentry, &realpath);
 	old_cred = ovl_override_creds(dentry->d_sb);
@@ -147,8 +156,10 @@ static int ovl_dir_getattr(struct vfsmou
 	if (err)
 		return err;
 
-	stat->dev = dentry->d_sb->s_dev;
-	stat->ino = dentry->d_inode->i_ino;
+	if (devino_from_ovl) {
+		stat->dev = dentry->d_sb->s_dev;
+		stat->ino = dentry->d_inode->i_ino;
+	}
 
 	/*
 	 * It's probably not worth it to count subdirs to get the
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -24,6 +24,11 @@ enum ovl_path_type {
 	(OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type))
 
 
+enum ovl_copy_up_type {
+	OVL_COPY_UP_ON_MODIF,
+	OVL_COPY_UP_ON_GETATTR,
+};
+
 #define OVL_XATTR_PREFIX XATTR_TRUSTED_PREFIX "overlay"
 #define OVL_XATTR_OPAQUE OVL_XATTR_PREFIX ".opaque"
 
@@ -172,6 +177,7 @@ struct file *ovl_path_open(struct path *
 
 struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry,
 				struct kstat *stat, const char *link);
+enum ovl_copy_up_type ovl_copy_up_type(struct dentry *dentry);
 
 /* readdir.c */
 extern const struct file_operations ovl_dir_operations;
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -31,6 +31,7 @@ struct ovl_config {
 	char *upperdir;
 	char *workdir;
 	bool default_permissions;
+	enum ovl_copy_up_type dir_copy_up_type;
 };
 
 /* private information held for overlayfs's superblock */
@@ -203,6 +204,16 @@ struct dentry *ovl_workdir(struct dentry
 	return ofs->workdir;
 }
 
+enum ovl_copy_up_type ovl_copy_up_type(struct dentry *dentry)
+{
+	struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+
+	if (d_is_dir(dentry))
+		return ofs->config.dir_copy_up_type;
+
+	return OVL_COPY_UP_ON_MODIF;
+}
+
 bool ovl_dentry_is_opaque(struct dentry *dentry)
 {
 	struct ovl_entry *oe = dentry->d_fsdata;
@@ -681,6 +692,8 @@ static int ovl_show_options(struct seq_f
 	}
 	if (ufs->config.default_permissions)
 		seq_puts(m, ",default_permissions");
+	if (ufs->config.dir_copy_up_type == OVL_COPY_UP_ON_GETATTR)
+		seq_puts(m, ",dir_copy_up_on=getattr");
 	return 0;
 }
 
@@ -707,6 +720,7 @@ enum {
 	OPT_UPPERDIR,
 	OPT_WORKDIR,
 	OPT_DEFAULT_PERMISSIONS,
+	OPT_DIR_COPY_UP_ON_GETATTR,
 	OPT_ERR,
 };
 
@@ -715,6 +729,7 @@ static const match_table_t ovl_tokens =
 	{OPT_UPPERDIR,			"upperdir=%s"},
 	{OPT_WORKDIR,			"workdir=%s"},
 	{OPT_DEFAULT_PERMISSIONS,	"default_permissions"},
+	{OPT_DIR_COPY_UP_ON_GETATTR,	"dir_copy_up_on=getattr"},
 	{OPT_ERR,			NULL}
 };
 
@@ -779,6 +794,10 @@ static int ovl_parse_opt(char *opt, stru
 			config->default_permissions = true;
 			break;
 
+		case OPT_DIR_COPY_UP_ON_GETATTR:
+			config->dir_copy_up_type = OVL_COPY_UP_ON_GETATTR;
+			break;
+
 		default:
 			pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
 			return -EINVAL;
--
To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux