aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2012-05-10 11:49:38 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2012-05-14 11:06:42 -0400
commit45c72cd73c788dd18c8113d4a404d6b4a01decf1 (patch)
tree49e28ba927e9485b6feadad7b60ec05d9bb6cff7 /fs
parent519c6040ce04474bc893774f866fd8d907b20429 (diff)
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: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dir.c1
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/fuse/inode.c17
3 files changed, 20 insertions, 1 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index df5ac048dc74..bc438320cac5 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -863,6 +863,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
863 if (stat) { 863 if (stat) {
864 generic_fillattr(inode, stat); 864 generic_fillattr(inode, stat);
865 stat->mode = fi->orig_i_mode; 865 stat->mode = fi->orig_i_mode;
866 stat->ino = fi->orig_ino;
866 } 867 }
867 } 868 }
868 869
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index f38fb795f03c..771fb6322c07 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -82,6 +82,9 @@ struct fuse_inode {
82 preserve the original mode */ 82 preserve the original mode */
83 umode_t orig_i_mode; 83 umode_t orig_i_mode;
84 84
85 /** 64 bit inode number */
86 u64 orig_ino;
87
85 /** Version of last attribute change */ 88 /** Version of last attribute change */
86 u64 attr_version; 89 u64 attr_version;
87 90
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 26783eb2b1fc..a59cf5e673d7 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -91,6 +91,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
91 fi->nlookup = 0; 91 fi->nlookup = 0;
92 fi->attr_version = 0; 92 fi->attr_version = 0;
93 fi->writectr = 0; 93 fi->writectr = 0;
94 fi->orig_ino = 0;
94 INIT_LIST_HEAD(&fi->write_files); 95 INIT_LIST_HEAD(&fi->write_files);
95 INIT_LIST_HEAD(&fi->queued_writes); 96 INIT_LIST_HEAD(&fi->queued_writes);
96 INIT_LIST_HEAD(&fi->writepages); 97 INIT_LIST_HEAD(&fi->writepages);
@@ -139,6 +140,18 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
139 return 0; 140 return 0;
140} 141}
141 142
143/*
144 * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
145 * so that it will fit.
146 */
147static ino_t fuse_squash_ino(u64 ino64)
148{
149 ino_t ino = (ino_t) ino64;
150 if (sizeof(ino_t) < sizeof(u64))
151 ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8;
152 return ino;
153}
154
142void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 155void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
143 u64 attr_valid) 156 u64 attr_valid)
144{ 157{
@@ -148,7 +161,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
148 fi->attr_version = ++fc->attr_version; 161 fi->attr_version = ++fc->attr_version;
149 fi->i_time = attr_valid; 162 fi->i_time = attr_valid;
150 163
151 inode->i_ino = attr->ino; 164 inode->i_ino = fuse_squash_ino(attr->ino);
152 inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 165 inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
153 set_nlink(inode, attr->nlink); 166 set_nlink(inode, attr->nlink);
154 inode->i_uid = attr->uid; 167 inode->i_uid = attr->uid;
@@ -174,6 +187,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
174 fi->orig_i_mode = inode->i_mode; 187 fi->orig_i_mode = inode->i_mode;
175 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 188 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
176 inode->i_mode &= ~S_ISVTX; 189 inode->i_mode &= ~S_ISVTX;
190
191 fi->orig_ino = attr->ino;
177} 192}
178 193
179void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, 194void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,