Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+87 -11
+2 -8
fs/fuse/control.c
··· 75 75 unsigned global_limit) 76 76 { 77 77 unsigned long t; 78 - char tmp[32]; 79 78 unsigned limit = (1 << 16) - 1; 80 79 int err; 81 80 82 - if (*ppos || count >= sizeof(tmp) - 1) 81 + if (*ppos) 83 82 return -EINVAL; 84 83 85 - if (copy_from_user(tmp, buf, count)) 86 - return -EINVAL; 87 - 88 - tmp[count] = '\0'; 89 - 90 - err = strict_strtoul(tmp, 0, &t); 84 + err = kstrtoul_from_user(buf, count, 0, &t); 91 85 if (err) 92 86 return err; 93 87
+10 -1
fs/fuse/dir.c
··· 775 775 static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 776 776 struct kstat *stat) 777 777 { 778 + unsigned int blkbits; 779 + 778 780 stat->dev = inode->i_sb->s_dev; 779 781 stat->ino = attr->ino; 780 782 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); ··· 792 790 stat->ctime.tv_nsec = attr->ctimensec; 793 791 stat->size = attr->size; 794 792 stat->blocks = attr->blocks; 795 - stat->blksize = (1 << inode->i_blkbits); 793 + 794 + if (attr->blksize != 0) 795 + blkbits = ilog2(attr->blksize); 796 + else 797 + blkbits = inode->i_sb->s_blocksize_bits; 798 + 799 + stat->blksize = 1 << blkbits; 796 800 } 797 801 798 802 static int fuse_do_getattr(struct inode *inode, struct kstat *stat, ··· 871 863 if (stat) { 872 864 generic_fillattr(inode, stat); 873 865 stat->mode = fi->orig_i_mode; 866 + stat->ino = fi->orig_ino; 874 867 } 875 868 } 876 869
+40
fs/fuse/file.c
··· 2173 2173 return ret; 2174 2174 } 2175 2175 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 + 2176 2214 static const struct file_operations fuse_file_operations = { 2177 2215 .llseek = fuse_file_llseek, 2178 2216 .read = do_sync_read, ··· 2228 2190 .unlocked_ioctl = fuse_file_ioctl, 2229 2191 .compat_ioctl = fuse_file_compat_ioctl, 2230 2192 .poll = fuse_file_poll, 2193 + .fallocate = fuse_file_fallocate, 2231 2194 }; 2232 2195 2233 2196 static const struct file_operations fuse_direct_io_file_operations = { ··· 2245 2206 .unlocked_ioctl = fuse_file_ioctl, 2246 2207 .compat_ioctl = fuse_file_compat_ioctl, 2247 2208 .poll = fuse_file_poll, 2209 + .fallocate = fuse_file_fallocate, 2248 2210 /* no splice_read */ 2249 2211 }; 2250 2212
+6
fs/fuse/fuse_i.h
··· 82 82 preserve the original mode */ 83 83 umode_t orig_i_mode; 84 84 85 + /** 64 bit inode number */ 86 + u64 orig_ino; 87 + 85 88 /** Version of last attribute change */ 86 89 u64 attr_version; 87 90 ··· 480 477 481 478 /** Are BSD file locking primitives not implemented by fs? */ 482 479 unsigned no_flock:1; 480 + 481 + /** Is fallocate not implemented by fs? */ 482 + unsigned no_fallocate:1; 483 483 484 484 /** The number of requests waiting for completion */ 485 485 atomic_t num_waiting;
+16 -1
fs/fuse/inode.c
··· 91 91 fi->nlookup = 0; 92 92 fi->attr_version = 0; 93 93 fi->writectr = 0; 94 + fi->orig_ino = 0; 94 95 INIT_LIST_HEAD(&fi->write_files); 95 96 INIT_LIST_HEAD(&fi->queued_writes); 96 97 INIT_LIST_HEAD(&fi->writepages); ··· 140 139 return 0; 141 140 } 142 141 142 + /* 143 + * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down 144 + * so that it will fit. 145 + */ 146 + static ino_t fuse_squash_ino(u64 ino64) 147 + { 148 + ino_t ino = (ino_t) ino64; 149 + if (sizeof(ino_t) < sizeof(u64)) 150 + ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; 151 + return ino; 152 + } 153 + 143 154 void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 144 155 u64 attr_valid) 145 156 { ··· 161 148 fi->attr_version = ++fc->attr_version; 162 149 fi->i_time = attr_valid; 163 150 164 - inode->i_ino = attr->ino; 151 + inode->i_ino = fuse_squash_ino(attr->ino); 165 152 inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 166 153 set_nlink(inode, attr->nlink); 167 154 inode->i_uid = attr->uid; ··· 187 174 fi->orig_i_mode = inode->i_mode; 188 175 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 189 176 inode->i_mode &= ~S_ISVTX; 177 + 178 + fi->orig_ino = attr->ino; 190 179 } 191 180 192 181 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+13 -1
include/linux/fuse.h
··· 54 54 * 7.18 55 55 * - add FUSE_IOCTL_DIR flag 56 56 * - add FUSE_NOTIFY_DELETE 57 + * 58 + * 7.19 59 + * - add FUSE_FALLOCATE 57 60 */ 58 61 59 62 #ifndef _LINUX_FUSE_H ··· 88 85 #define FUSE_KERNEL_VERSION 7 89 86 90 87 /** Minor version number of this interface */ 91 - #define FUSE_KERNEL_MINOR_VERSION 18 88 + #define FUSE_KERNEL_MINOR_VERSION 19 92 89 93 90 /** The node ID of the root inode */ 94 91 #define FUSE_ROOT_ID 1 ··· 281 278 FUSE_POLL = 40, 282 279 FUSE_NOTIFY_REPLY = 41, 283 280 FUSE_BATCH_FORGET = 42, 281 + FUSE_FALLOCATE = 43, 284 282 285 283 /* CUSE specific operations */ 286 284 CUSE_INIT = 4096, ··· 573 569 574 570 struct fuse_notify_poll_wakeup_out { 575 571 __u64 kh; 572 + }; 573 + 574 + struct fuse_fallocate_in { 575 + __u64 fh; 576 + __u64 offset; 577 + __u64 length; 578 + __u32 mode; 579 + __u32 padding; 576 580 }; 577 581 578 582 struct fuse_in_header {