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
This commit is contained in:
@@ -75,19 +75,13 @@ static ssize_t fuse_conn_limit_write(struct file *file, const char __user *buf,
|
|||||||
unsigned global_limit)
|
unsigned global_limit)
|
||||||
{
|
{
|
||||||
unsigned long t;
|
unsigned long t;
|
||||||
char tmp[32];
|
|
||||||
unsigned limit = (1 << 16) - 1;
|
unsigned limit = (1 << 16) - 1;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (*ppos || count >= sizeof(tmp) - 1)
|
if (*ppos)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (copy_from_user(tmp, buf, count))
|
err = kstrtoul_from_user(buf, count, 0, &t);
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
tmp[count] = '\0';
|
|
||||||
|
|
||||||
err = strict_strtoul(tmp, 0, &t);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@@ -775,6 +775,8 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
|
|||||||
static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
|
static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
|
||||||
struct kstat *stat)
|
struct kstat *stat)
|
||||||
{
|
{
|
||||||
|
unsigned int blkbits;
|
||||||
|
|
||||||
stat->dev = inode->i_sb->s_dev;
|
stat->dev = inode->i_sb->s_dev;
|
||||||
stat->ino = attr->ino;
|
stat->ino = attr->ino;
|
||||||
stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
|
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,
|
|||||||
stat->ctime.tv_nsec = attr->ctimensec;
|
stat->ctime.tv_nsec = attr->ctimensec;
|
||||||
stat->size = attr->size;
|
stat->size = attr->size;
|
||||||
stat->blocks = attr->blocks;
|
stat->blocks = attr->blocks;
|
||||||
stat->blksize = (1 << inode->i_blkbits);
|
|
||||||
|
if (attr->blksize != 0)
|
||||||
|
blkbits = ilog2(attr->blksize);
|
||||||
|
else
|
||||||
|
blkbits = inode->i_sb->s_blocksize_bits;
|
||||||
|
|
||||||
|
stat->blksize = 1 << blkbits;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
|
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,
|
|||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2173,6 +2173,44 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
|
||||||
|
loff_t length)
|
||||||
|
{
|
||||||
|
struct fuse_file *ff = file->private_data;
|
||||||
|
struct fuse_conn *fc = ff->fc;
|
||||||
|
struct fuse_req *req;
|
||||||
|
struct fuse_fallocate_in inarg = {
|
||||||
|
.fh = ff->fh,
|
||||||
|
.offset = offset,
|
||||||
|
.length = length,
|
||||||
|
.mode = mode
|
||||||
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (fc->no_fallocate)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
req = fuse_get_req(fc);
|
||||||
|
if (IS_ERR(req))
|
||||||
|
return PTR_ERR(req);
|
||||||
|
|
||||||
|
req->in.h.opcode = FUSE_FALLOCATE;
|
||||||
|
req->in.h.nodeid = ff->nodeid;
|
||||||
|
req->in.numargs = 1;
|
||||||
|
req->in.args[0].size = sizeof(inarg);
|
||||||
|
req->in.args[0].value = &inarg;
|
||||||
|
fuse_request_send(fc, req);
|
||||||
|
err = req->out.h.error;
|
||||||
|
if (err == -ENOSYS) {
|
||||||
|
fc->no_fallocate = 1;
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
fuse_put_request(fc, req);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(fuse_file_fallocate);
|
||||||
|
|
||||||
static const struct file_operations fuse_file_operations = {
|
static const struct file_operations fuse_file_operations = {
|
||||||
.llseek = fuse_file_llseek,
|
.llseek = fuse_file_llseek,
|
||||||
.read = do_sync_read,
|
.read = do_sync_read,
|
||||||
@@ -2190,6 +2228,7 @@ static const struct file_operations fuse_file_operations = {
|
|||||||
.unlocked_ioctl = fuse_file_ioctl,
|
.unlocked_ioctl = fuse_file_ioctl,
|
||||||
.compat_ioctl = fuse_file_compat_ioctl,
|
.compat_ioctl = fuse_file_compat_ioctl,
|
||||||
.poll = fuse_file_poll,
|
.poll = fuse_file_poll,
|
||||||
|
.fallocate = fuse_file_fallocate,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct file_operations fuse_direct_io_file_operations = {
|
static const struct file_operations fuse_direct_io_file_operations = {
|
||||||
@@ -2206,6 +2245,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
|
|||||||
.unlocked_ioctl = fuse_file_ioctl,
|
.unlocked_ioctl = fuse_file_ioctl,
|
||||||
.compat_ioctl = fuse_file_compat_ioctl,
|
.compat_ioctl = fuse_file_compat_ioctl,
|
||||||
.poll = fuse_file_poll,
|
.poll = fuse_file_poll,
|
||||||
|
.fallocate = fuse_file_fallocate,
|
||||||
/* no splice_read */
|
/* no splice_read */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
@@ -478,6 +481,9 @@ struct fuse_conn {
|
|||||||
/** Are BSD file locking primitives not implemented by fs? */
|
/** Are BSD file locking primitives not implemented by fs? */
|
||||||
unsigned no_flock:1;
|
unsigned no_flock:1;
|
||||||
|
|
||||||
|
/** Is fallocate not implemented by fs? */
|
||||||
|
unsigned no_fallocate:1;
|
||||||
|
|
||||||
/** The number of requests waiting for completion */
|
/** The number of requests waiting for completion */
|
||||||
atomic_t num_waiting;
|
atomic_t num_waiting;
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
|
@@ -54,6 +54,9 @@
|
|||||||
* 7.18
|
* 7.18
|
||||||
* - add FUSE_IOCTL_DIR flag
|
* - add FUSE_IOCTL_DIR flag
|
||||||
* - add FUSE_NOTIFY_DELETE
|
* - add FUSE_NOTIFY_DELETE
|
||||||
|
*
|
||||||
|
* 7.19
|
||||||
|
* - add FUSE_FALLOCATE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LINUX_FUSE_H
|
#ifndef _LINUX_FUSE_H
|
||||||
@@ -85,7 +88,7 @@
|
|||||||
#define FUSE_KERNEL_VERSION 7
|
#define FUSE_KERNEL_VERSION 7
|
||||||
|
|
||||||
/** Minor version number of this interface */
|
/** Minor version number of this interface */
|
||||||
#define FUSE_KERNEL_MINOR_VERSION 18
|
#define FUSE_KERNEL_MINOR_VERSION 19
|
||||||
|
|
||||||
/** The node ID of the root inode */
|
/** The node ID of the root inode */
|
||||||
#define FUSE_ROOT_ID 1
|
#define FUSE_ROOT_ID 1
|
||||||
@@ -278,6 +281,7 @@ enum fuse_opcode {
|
|||||||
FUSE_POLL = 40,
|
FUSE_POLL = 40,
|
||||||
FUSE_NOTIFY_REPLY = 41,
|
FUSE_NOTIFY_REPLY = 41,
|
||||||
FUSE_BATCH_FORGET = 42,
|
FUSE_BATCH_FORGET = 42,
|
||||||
|
FUSE_FALLOCATE = 43,
|
||||||
|
|
||||||
/* CUSE specific operations */
|
/* CUSE specific operations */
|
||||||
CUSE_INIT = 4096,
|
CUSE_INIT = 4096,
|
||||||
@@ -571,6 +575,14 @@ struct fuse_notify_poll_wakeup_out {
|
|||||||
__u64 kh;
|
__u64 kh;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fuse_fallocate_in {
|
||||||
|
__u64 fh;
|
||||||
|
__u64 offset;
|
||||||
|
__u64 length;
|
||||||
|
__u32 mode;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
struct fuse_in_header {
|
struct fuse_in_header {
|
||||||
__u32 len;
|
__u32 len;
|
||||||
__u32 opcode;
|
__u32 opcode;
|
||||||
|
Reference in New Issue
Block a user