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:
		
						commit
						f9ba7179ce
					
				| @ -75,19 +75,13 @@ static ssize_t fuse_conn_limit_write(struct file *file, const char __user *buf, | ||||
| 				     unsigned global_limit) | ||||
| { | ||||
| 	unsigned long t; | ||||
| 	char tmp[32]; | ||||
| 	unsigned limit = (1 << 16) - 1; | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (*ppos || count >= sizeof(tmp) - 1) | ||||
| 	if (*ppos) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (copy_from_user(tmp, buf, count)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	tmp[count] = '\0'; | ||||
| 
 | ||||
| 	err = strict_strtoul(tmp, 0, &t); | ||||
| 	err = kstrtoul_from_user(buf, count, 0, &t); | ||||
| 	if (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, | ||||
| 			  struct kstat *stat) | ||||
| { | ||||
| 	unsigned int blkbits; | ||||
| 
 | ||||
| 	stat->dev = inode->i_sb->s_dev; | ||||
| 	stat->ino = attr->ino; | ||||
| 	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->size = attr->size; | ||||
| 	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, | ||||
| @ -863,6 +871,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, | ||||
| 		if (stat) { | ||||
| 			generic_fillattr(inode, stat); | ||||
| 			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; | ||||
| } | ||||
| 
 | ||||
| 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 = { | ||||
| 	.llseek		= fuse_file_llseek, | ||||
| 	.read		= do_sync_read, | ||||
| @ -2190,6 +2228,7 @@ static const struct file_operations fuse_file_operations = { | ||||
| 	.unlocked_ioctl	= fuse_file_ioctl, | ||||
| 	.compat_ioctl	= fuse_file_compat_ioctl, | ||||
| 	.poll		= fuse_file_poll, | ||||
| 	.fallocate	= fuse_file_fallocate, | ||||
| }; | ||||
| 
 | ||||
| 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, | ||||
| 	.compat_ioctl	= fuse_file_compat_ioctl, | ||||
| 	.poll		= fuse_file_poll, | ||||
| 	.fallocate	= fuse_file_fallocate, | ||||
| 	/* no splice_read */ | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -82,6 +82,9 @@ struct fuse_inode { | ||||
| 	    preserve the original mode */ | ||||
| 	umode_t orig_i_mode; | ||||
| 
 | ||||
| 	/** 64 bit inode number */ | ||||
| 	u64 orig_ino; | ||||
| 
 | ||||
| 	/** Version of last attribute change */ | ||||
| 	u64 attr_version; | ||||
| 
 | ||||
| @ -478,6 +481,9 @@ struct fuse_conn { | ||||
| 	/** Are BSD file locking primitives not implemented by fs? */ | ||||
| 	unsigned no_flock:1; | ||||
| 
 | ||||
| 	/** Is fallocate not implemented by fs? */ | ||||
| 	unsigned no_fallocate:1; | ||||
| 
 | ||||
| 	/** The number of requests waiting for completion */ | ||||
| 	atomic_t num_waiting; | ||||
| 
 | ||||
|  | ||||
| @ -91,6 +91,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | ||||
| 	fi->nlookup = 0; | ||||
| 	fi->attr_version = 0; | ||||
| 	fi->writectr = 0; | ||||
| 	fi->orig_ino = 0; | ||||
| 	INIT_LIST_HEAD(&fi->write_files); | ||||
| 	INIT_LIST_HEAD(&fi->queued_writes); | ||||
| 	INIT_LIST_HEAD(&fi->writepages); | ||||
| @ -139,6 +140,18 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) | ||||
| 	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, | ||||
| 				   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->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); | ||||
| 	set_nlink(inode, attr->nlink); | ||||
| 	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; | ||||
| 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | ||||
| 		inode->i_mode &= ~S_ISVTX; | ||||
| 
 | ||||
| 	fi->orig_ino = attr->ino; | ||||
| } | ||||
| 
 | ||||
| void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | ||||
|  | ||||
| @ -54,6 +54,9 @@ | ||||
|  * 7.18 | ||||
|  *  - add FUSE_IOCTL_DIR flag | ||||
|  *  - add FUSE_NOTIFY_DELETE | ||||
|  * | ||||
|  * 7.19 | ||||
|  *  - add FUSE_FALLOCATE | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _LINUX_FUSE_H | ||||
| @ -85,7 +88,7 @@ | ||||
| #define FUSE_KERNEL_VERSION 7 | ||||
| 
 | ||||
| /** 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 */ | ||||
| #define FUSE_ROOT_ID 1 | ||||
| @ -278,6 +281,7 @@ enum fuse_opcode { | ||||
| 	FUSE_POLL          = 40, | ||||
| 	FUSE_NOTIFY_REPLY  = 41, | ||||
| 	FUSE_BATCH_FORGET  = 42, | ||||
| 	FUSE_FALLOCATE     = 43, | ||||
| 
 | ||||
| 	/* CUSE specific operations */ | ||||
| 	CUSE_INIT          = 4096, | ||||
| @ -571,6 +575,14 @@ struct fuse_notify_poll_wakeup_out { | ||||
| 	__u64	kh; | ||||
| }; | ||||
| 
 | ||||
| struct fuse_fallocate_in { | ||||
| 	__u64	fh; | ||||
| 	__u64	offset; | ||||
| 	__u64	length; | ||||
| 	__u32	mode; | ||||
| 	__u32	padding; | ||||
| }; | ||||
| 
 | ||||
| struct fuse_in_header { | ||||
| 	__u32	len; | ||||
| 	__u32	opcode; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user