Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45c72cd7 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Miklos Szeredi
Browse files

fuse: fix stat call on 32 bit platforms



Now we store attr->ino at inode->i_ino, return attr->ino at the
first time and then return inode->i_ino if the attribute timeout
isn't expired. That's wrong on 32 bit platforms because attr->ino
is 64 bit and inode->i_ino is 32 bit in this case.

Fix this by saving 64 bit ino in fuse_inode structure and returning
it every time we call getattr. Also squash attr->ino into inode->i_ino
explicitly.

Signed-off-by: default avatarPavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
parent 519c6040
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -863,6 +863,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
		if (stat) {
		if (stat) {
			generic_fillattr(inode, stat);
			generic_fillattr(inode, stat);
			stat->mode = fi->orig_i_mode;
			stat->mode = fi->orig_i_mode;
			stat->ino = fi->orig_ino;
		}
		}
	}
	}


+3 −0
Original line number Original line Diff line number Diff line
@@ -82,6 +82,9 @@ struct fuse_inode {
	    preserve the original mode */
	    preserve the original mode */
	umode_t orig_i_mode;
	umode_t orig_i_mode;


	/** 64 bit inode number */
	u64 orig_ino;

	/** Version of last attribute change */
	/** Version of last attribute change */
	u64 attr_version;
	u64 attr_version;


+16 −1
Original line number Original line Diff line number Diff line
@@ -91,6 +91,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
	fi->nlookup = 0;
	fi->nlookup = 0;
	fi->attr_version = 0;
	fi->attr_version = 0;
	fi->writectr = 0;
	fi->writectr = 0;
	fi->orig_ino = 0;
	INIT_LIST_HEAD(&fi->write_files);
	INIT_LIST_HEAD(&fi->write_files);
	INIT_LIST_HEAD(&fi->queued_writes);
	INIT_LIST_HEAD(&fi->queued_writes);
	INIT_LIST_HEAD(&fi->writepages);
	INIT_LIST_HEAD(&fi->writepages);
@@ -139,6 +140,18 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
	return 0;
	return 0;
}
}


/*
 * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
 * so that it will fit.
 */
static ino_t fuse_squash_ino(u64 ino64)
{
	ino_t ino = (ino_t) ino64;
	if (sizeof(ino_t) < sizeof(u64))
		ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8;
	return ino;
}

void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
				   u64 attr_valid)
				   u64 attr_valid)
{
{
@@ -148,7 +161,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
	fi->attr_version = ++fc->attr_version;
	fi->attr_version = ++fc->attr_version;
	fi->i_time = attr_valid;
	fi->i_time = attr_valid;


	inode->i_ino     = attr->ino;
	inode->i_ino     = fuse_squash_ino(attr->ino);
	inode->i_mode    = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
	inode->i_mode    = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
	set_nlink(inode, attr->nlink);
	set_nlink(inode, attr->nlink);
	inode->i_uid     = attr->uid;
	inode->i_uid     = attr->uid;
@@ -174,6 +187,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
	fi->orig_i_mode = inode->i_mode;
	fi->orig_i_mode = inode->i_mode;
	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
		inode->i_mode &= ~S_ISVTX;
		inode->i_mode &= ~S_ISVTX;

	fi->orig_ino = attr->ino;
}
}


void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,