Skip to content

Commit f9ba717

Browse files
committed
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
2 parents 0b3e9f3 + 203627b commit f9ba717

File tree

6 files changed

+87
-11
lines changed

6 files changed

+87
-11
lines changed

fs/fuse/control.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,13 @@ static ssize_t fuse_conn_limit_write(struct file *file, const char __user *buf,
7575
unsigned global_limit)
7676
{
7777
unsigned long t;
78-
char tmp[32];
7978
unsigned limit = (1 << 16) - 1;
8079
int err;
8180

82-
if (*ppos || count >= sizeof(tmp) - 1)
83-
return -EINVAL;
84-
85-
if (copy_from_user(tmp, buf, count))
81+
if (*ppos)
8682
return -EINVAL;
8783

88-
tmp[count] = '\0';
89-
90-
err = strict_strtoul(tmp, 0, &t);
84+
err = kstrtoul_from_user(buf, count, 0, &t);
9185
if (err)
9286
return err;
9387

fs/fuse/dir.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,8 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
775775
static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
776776
struct kstat *stat)
777777
{
778+
unsigned int blkbits;
779+
778780
stat->dev = inode->i_sb->s_dev;
779781
stat->ino = attr->ino;
780782
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,
790792
stat->ctime.tv_nsec = attr->ctimensec;
791793
stat->size = attr->size;
792794
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;
794802
}
795803

796804
static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
@@ -863,6 +871,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
863871
if (stat) {
864872
generic_fillattr(inode, stat);
865873
stat->mode = fi->orig_i_mode;
874+
stat->ino = fi->orig_ino;
866875
}
867876
}
868877

fs/fuse/file.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,6 +2173,44 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
21732173
return ret;
21742174
}
21752175

2176+
long 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+
}
2212+
EXPORT_SYMBOL_GPL(fuse_file_fallocate);
2213+
21762214
static const struct file_operations fuse_file_operations = {
21772215
.llseek = fuse_file_llseek,
21782216
.read = do_sync_read,
@@ -2190,6 +2228,7 @@ static const struct file_operations fuse_file_operations = {
21902228
.unlocked_ioctl = fuse_file_ioctl,
21912229
.compat_ioctl = fuse_file_compat_ioctl,
21922230
.poll = fuse_file_poll,
2231+
.fallocate = fuse_file_fallocate,
21932232
};
21942233

21952234
static const struct file_operations fuse_direct_io_file_operations = {
@@ -2206,6 +2245,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
22062245
.unlocked_ioctl = fuse_file_ioctl,
22072246
.compat_ioctl = fuse_file_compat_ioctl,
22082247
.poll = fuse_file_poll,
2248+
.fallocate = fuse_file_fallocate,
22092249
/* no splice_read */
22102250
};
22112251

fs/fuse/fuse_i.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ struct fuse_inode {
8282
preserve the original mode */
8383
umode_t orig_i_mode;
8484

85+
/** 64 bit inode number */
86+
u64 orig_ino;
87+
8588
/** Version of last attribute change */
8689
u64 attr_version;
8790

@@ -478,6 +481,9 @@ struct fuse_conn {
478481
/** Are BSD file locking primitives not implemented by fs? */
479482
unsigned no_flock:1;
480483

484+
/** Is fallocate not implemented by fs? */
485+
unsigned no_fallocate:1;
486+
481487
/** The number of requests waiting for completion */
482488
atomic_t num_waiting;
483489

fs/fuse/inode.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
9191
fi->nlookup = 0;
9292
fi->attr_version = 0;
9393
fi->writectr = 0;
94+
fi->orig_ino = 0;
9495
INIT_LIST_HEAD(&fi->write_files);
9596
INIT_LIST_HEAD(&fi->queued_writes);
9697
INIT_LIST_HEAD(&fi->writepages);
@@ -139,6 +140,18 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
139140
return 0;
140141
}
141142

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+
*/
147+
static 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+
142155
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
143156
u64 attr_valid)
144157
{
@@ -148,7 +161,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
148161
fi->attr_version = ++fc->attr_version;
149162
fi->i_time = attr_valid;
150163

151-
inode->i_ino = attr->ino;
164+
inode->i_ino = fuse_squash_ino(attr->ino);
152165
inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
153166
set_nlink(inode, attr->nlink);
154167
inode->i_uid = attr->uid;
@@ -174,6 +187,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
174187
fi->orig_i_mode = inode->i_mode;
175188
if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
176189
inode->i_mode &= ~S_ISVTX;
190+
191+
fi->orig_ino = attr->ino;
177192
}
178193

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

include/linux/fuse.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454
* 7.18
5555
* - add FUSE_IOCTL_DIR flag
5656
* - add FUSE_NOTIFY_DELETE
57+
*
58+
* 7.19
59+
* - add FUSE_FALLOCATE
5760
*/
5861

5962
#ifndef _LINUX_FUSE_H
@@ -85,7 +88,7 @@
8588
#define FUSE_KERNEL_VERSION 7
8689

8790
/** Minor version number of this interface */
88-
#define FUSE_KERNEL_MINOR_VERSION 18
91+
#define FUSE_KERNEL_MINOR_VERSION 19
8992

9093
/** The node ID of the root inode */
9194
#define FUSE_ROOT_ID 1
@@ -278,6 +281,7 @@ enum fuse_opcode {
278281
FUSE_POLL = 40,
279282
FUSE_NOTIFY_REPLY = 41,
280283
FUSE_BATCH_FORGET = 42,
284+
FUSE_FALLOCATE = 43,
281285

282286
/* CUSE specific operations */
283287
CUSE_INIT = 4096,
@@ -571,6 +575,14 @@ struct fuse_notify_poll_wakeup_out {
571575
__u64 kh;
572576
};
573577

578+
struct fuse_fallocate_in {
579+
__u64 fh;
580+
__u64 offset;
581+
__u64 length;
582+
__u32 mode;
583+
__u32 padding;
584+
};
585+
574586
struct fuse_in_header {
575587
__u32 len;
576588
__u32 opcode;

0 commit comments

Comments
 (0)