aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-05 13:11:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-05 13:11:11 -0400
commitf9ba7179ce91fb77b2adf6eaab3676ab3a1f5a15 (patch)
tree2d02e7a4fd78083b78749d0c9c7466f0eb8e6f97 /fs
parent0b3e9f3f21c42d064f5f4088df4088e3d55755eb (diff)
parent203627bbc90377c509e32450c67c5d957ba2d989 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse updates from Miklos Szeredi. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: fuse: fix blksize calculation fuse: fix stat call on 32 bit platforms fuse: optimize fallocate on permanent failure fuse: add FALLOCATE operation fuse: Convert to kstrtoul_from_user
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/control.c10
-rw-r--r--fs/fuse/dir.c11
-rw-r--r--fs/fuse/file.c40
-rw-r--r--fs/fuse/fuse_i.h6
-rw-r--r--fs/fuse/inode.c17
5 files changed, 74 insertions, 10 deletions
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 42593c587d48..03ff5b1eba93 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -75,19 +75,13 @@ static ssize_t fuse_conn_limit_write(struct file *file, const char __user *buf,
75 unsigned global_limit) 75 unsigned global_limit)
76{ 76{
77 unsigned long t; 77 unsigned long t;
78 char tmp[32];
79 unsigned limit = (1 << 16) - 1; 78 unsigned limit = (1 << 16) - 1;
80 int err; 79 int err;
81 80
82 if (*ppos || count >= sizeof(tmp) - 1) 81 if (*ppos)
83 return -EINVAL;
84
85 if (copy_from_user(tmp, buf, count))
86 return -EINVAL; 82 return -EINVAL;
87 83
88 tmp[count] = '\0'; 84 err = kstrtoul_from_user(buf, count, 0, &t);
89
90 err = strict_strtoul(tmp, 0, &t);
91 if (err) 85 if (err)
92 return err; 86 return err;
93 87
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index df5ac048dc74..334e0b18a014 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -775,6 +775,8 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
775static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 775static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
776 struct kstat *stat) 776 struct kstat *stat)
777{ 777{
778 unsigned int blkbits;
779
778 stat->dev = inode->i_sb->s_dev; 780 stat->dev = inode->i_sb->s_dev;
779 stat->ino = attr->ino; 781 stat->ino = attr->ino;
780 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 782 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
@@ -790,7 +792,13 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
790 stat->ctime.tv_nsec = attr->ctimensec; 792 stat->ctime.tv_nsec = attr->ctimensec;
791 stat->size = attr->size; 793 stat->size = attr->size;
792 stat->blocks = attr->blocks; 794 stat->blocks = attr->blocks;
793 stat->blksize = (1 << inode->i_blkbits); 795
796 if (attr->blksize != 0)
797 blkbits = ilog2(attr->blksize);
798 else
799 blkbits = inode->i_sb->s_blocksize_bits;
800
801 stat->blksize = 1 << blkbits;
794} 802}
795 803
796static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 804static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
@@ -863,6 +871,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
863 if (stat) { 871 if (stat) {
864 generic_fillattr(inode, stat); 872 generic_fillattr(inode, stat);
865 stat->mode = fi->orig_i_mode; 873 stat->mode = fi->orig_i_mode;
874 stat->ino = fi->orig_ino;
866 } 875 }
867 } 876 }
868 877
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 9562109d3a87..b321a688cde7 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2173,6 +2173,44 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2173 return ret; 2173 return ret;
2174} 2174}
2175 2175
2176long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
2177 loff_t length)
2178{
2179 struct fuse_file *ff = file->private_data;
2180 struct fuse_conn *fc = ff->fc;
2181 struct fuse_req *req;
2182 struct fuse_fallocate_in inarg = {
2183 .fh = ff->fh,
2184 .offset = offset,
2185 .length = length,
2186 .mode = mode
2187 };
2188 int err;
2189
2190 if (fc->no_fallocate)
2191 return -EOPNOTSUPP;
2192
2193 req = fuse_get_req(fc);
2194 if (IS_ERR(req))
2195 return PTR_ERR(req);
2196
2197 req->in.h.opcode = FUSE_FALLOCATE;
2198 req->in.h.nodeid = ff->nodeid;
2199 req->in.numargs = 1;
2200 req->in.args[0].size = sizeof(inarg);
2201 req->in.args[0].value = &inarg;
2202 fuse_request_send(fc, req);
2203 err = req->out.h.error;
2204 if (err == -ENOSYS) {
2205 fc->no_fallocate = 1;
2206 err = -EOPNOTSUPP;
2207 }
2208 fuse_put_request(fc, req);
2209
2210 return err;
2211}
2212EXPORT_SYMBOL_GPL(fuse_file_fallocate);
2213
2176static const struct file_operations fuse_file_operations = { 2214static const struct file_operations fuse_file_operations = {
2177 .llseek = fuse_file_llseek, 2215 .llseek = fuse_file_llseek,
2178 .read = do_sync_read, 2216 .read = do_sync_read,
@@ -2190,6 +2228,7 @@ static const struct file_operations fuse_file_operations = {
2190 .unlocked_ioctl = fuse_file_ioctl, 2228 .unlocked_ioctl = fuse_file_ioctl,
2191 .compat_ioctl = fuse_file_compat_ioctl, 2229 .compat_ioctl = fuse_file_compat_ioctl,
2192 .poll = fuse_file_poll, 2230 .poll = fuse_file_poll,
2231 .fallocate = fuse_file_fallocate,
2193}; 2232};
2194 2233
2195static const struct file_operations fuse_direct_io_file_operations = { 2234static const struct file_operations fuse_direct_io_file_operations = {
@@ -2206,6 +2245,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
2206 .unlocked_ioctl = fuse_file_ioctl, 2245 .unlocked_ioctl = fuse_file_ioctl,
2207 .compat_ioctl = fuse_file_compat_ioctl, 2246 .compat_ioctl = fuse_file_compat_ioctl,
2208 .poll = fuse_file_poll, 2247 .poll = fuse_file_poll,
2248 .fallocate = fuse_file_fallocate,
2209 /* no splice_read */ 2249 /* no splice_read */
2210}; 2250};
2211 2251
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 572cefc78012..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
@@ -478,6 +481,9 @@ struct fuse_conn {
478 /** Are BSD file locking primitives not implemented by fs? */ 481 /** Are BSD file locking primitives not implemented by fs? */
479 unsigned no_flock:1; 482 unsigned no_flock:1;
480 483
484 /** Is fallocate not implemented by fs? */
485 unsigned no_fallocate:1;
486
481 /** The number of requests waiting for completion */ 487 /** The number of requests waiting for completion */
482 atomic_t num_waiting; 488 atomic_t num_waiting;
483 489
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 42678a33b7bb..1cd61652018c 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,