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

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
FUSE: Notifying the kernel of deletion.
fuse: support ioctl on directories
fuse: Use kcalloc instead of kzalloc to allocate array
fuse: llseek optimize SEEK_CUR and SEEK_SET

+149 -50
+56 -1
fs/fuse/dev.c
··· 1378 1378 down_read(&fc->killsb); 1379 1379 err = -ENOENT; 1380 1380 if (fc->sb) 1381 - err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name); 1381 + err = fuse_reverse_inval_entry(fc->sb, outarg.parent, 0, &name); 1382 + up_read(&fc->killsb); 1383 + kfree(buf); 1384 + return err; 1385 + 1386 + err: 1387 + kfree(buf); 1388 + fuse_copy_finish(cs); 1389 + return err; 1390 + } 1391 + 1392 + static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size, 1393 + struct fuse_copy_state *cs) 1394 + { 1395 + struct fuse_notify_delete_out outarg; 1396 + int err = -ENOMEM; 1397 + char *buf; 1398 + struct qstr name; 1399 + 1400 + buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); 1401 + if (!buf) 1402 + goto err; 1403 + 1404 + err = -EINVAL; 1405 + if (size < sizeof(outarg)) 1406 + goto err; 1407 + 1408 + err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 1409 + if (err) 1410 + goto err; 1411 + 1412 + err = -ENAMETOOLONG; 1413 + if (outarg.namelen > FUSE_NAME_MAX) 1414 + goto err; 1415 + 1416 + err = -EINVAL; 1417 + if (size != sizeof(outarg) + outarg.namelen + 1) 1418 + goto err; 1419 + 1420 + name.name = buf; 1421 + name.len = outarg.namelen; 1422 + err = fuse_copy_one(cs, buf, outarg.namelen + 1); 1423 + if (err) 1424 + goto err; 1425 + fuse_copy_finish(cs); 1426 + buf[outarg.namelen] = 0; 1427 + name.hash = full_name_hash(name.name, name.len); 1428 + 1429 + down_read(&fc->killsb); 1430 + err = -ENOENT; 1431 + if (fc->sb) 1432 + err = fuse_reverse_inval_entry(fc->sb, outarg.parent, 1433 + outarg.child, &name); 1382 1434 up_read(&fc->killsb); 1383 1435 kfree(buf); 1384 1436 return err; ··· 1648 1596 1649 1597 case FUSE_NOTIFY_RETRIEVE: 1650 1598 return fuse_notify_retrieve(fc, size, cs); 1599 + 1600 + case FUSE_NOTIFY_DELETE: 1601 + return fuse_notify_delete(fc, size, cs); 1651 1602 1652 1603 default: 1653 1604 fuse_copy_finish(cs);
+56 -2
fs/fuse/dir.c
··· 868 868 } 869 869 870 870 int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 871 - struct qstr *name) 871 + u64 child_nodeid, struct qstr *name) 872 872 { 873 873 int err = -ENOTDIR; 874 874 struct inode *parent; ··· 895 895 896 896 fuse_invalidate_attr(parent); 897 897 fuse_invalidate_entry(entry); 898 + 899 + if (child_nodeid != 0 && entry->d_inode) { 900 + mutex_lock(&entry->d_inode->i_mutex); 901 + if (get_node_id(entry->d_inode) != child_nodeid) { 902 + err = -ENOENT; 903 + goto badentry; 904 + } 905 + if (d_mountpoint(entry)) { 906 + err = -EBUSY; 907 + goto badentry; 908 + } 909 + if (S_ISDIR(entry->d_inode->i_mode)) { 910 + shrink_dcache_parent(entry); 911 + if (!simple_empty(entry)) { 912 + err = -ENOTEMPTY; 913 + goto badentry; 914 + } 915 + entry->d_inode->i_flags |= S_DEAD; 916 + } 917 + dont_mount(entry); 918 + clear_nlink(entry->d_inode); 919 + err = 0; 920 + badentry: 921 + mutex_unlock(&entry->d_inode->i_mutex); 922 + if (!err) 923 + d_delete(entry); 924 + } else { 925 + err = 0; 926 + } 898 927 dput(entry); 899 - err = 0; 900 928 901 929 unlock: 902 930 mutex_unlock(&parent->i_mutex); ··· 1208 1180 int datasync) 1209 1181 { 1210 1182 return fuse_fsync_common(file, start, end, datasync, 1); 1183 + } 1184 + 1185 + static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1186 + unsigned long arg) 1187 + { 1188 + struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1189 + 1190 + /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1191 + if (fc->minor < 18) 1192 + return -ENOTTY; 1193 + 1194 + return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1195 + } 1196 + 1197 + static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1198 + unsigned long arg) 1199 + { 1200 + struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1201 + 1202 + if (fc->minor < 18) 1203 + return -ENOTTY; 1204 + 1205 + return fuse_ioctl_common(file, cmd, arg, 1206 + FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1211 1207 } 1212 1208 1213 1209 static bool update_mtime(unsigned ivalid) ··· 1648 1596 .open = fuse_dir_open, 1649 1597 .release = fuse_dir_release, 1650 1598 .fsync = fuse_dir_fsync, 1599 + .unlocked_ioctl = fuse_dir_ioctl, 1600 + .compat_ioctl = fuse_dir_compat_ioctl, 1651 1601 }; 1652 1602 1653 1603 static const struct inode_operations fuse_common_inode_operations = {
+13 -45
fs/fuse/file.c
··· 1555 1555 loff_t retval; 1556 1556 struct inode *inode = file->f_path.dentry->d_inode; 1557 1557 1558 - mutex_lock(&inode->i_mutex); 1559 - if (origin != SEEK_CUR && origin != SEEK_SET) { 1560 - retval = fuse_update_attributes(inode, NULL, file, NULL); 1561 - if (retval) 1562 - goto exit; 1563 - } 1558 + /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */ 1559 + if (origin == SEEK_CUR || origin == SEEK_SET) 1560 + return generic_file_llseek(file, offset, origin); 1564 1561 1565 - switch (origin) { 1566 - case SEEK_END: 1567 - offset += i_size_read(inode); 1568 - break; 1569 - case SEEK_CUR: 1570 - if (offset == 0) { 1571 - retval = file->f_pos; 1572 - goto exit; 1573 - } 1574 - offset += file->f_pos; 1575 - break; 1576 - case SEEK_DATA: 1577 - if (offset >= i_size_read(inode)) { 1578 - retval = -ENXIO; 1579 - goto exit; 1580 - } 1581 - break; 1582 - case SEEK_HOLE: 1583 - if (offset >= i_size_read(inode)) { 1584 - retval = -ENXIO; 1585 - goto exit; 1586 - } 1587 - offset = i_size_read(inode); 1588 - break; 1589 - } 1590 - retval = -EINVAL; 1591 - if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { 1592 - if (offset != file->f_pos) { 1593 - file->f_pos = offset; 1594 - file->f_version = 0; 1595 - } 1596 - retval = offset; 1597 - } 1598 - exit: 1562 + mutex_lock(&inode->i_mutex); 1563 + retval = fuse_update_attributes(inode, NULL, file, NULL); 1564 + if (!retval) 1565 + retval = generic_file_llseek(file, offset, origin); 1599 1566 mutex_unlock(&inode->i_mutex); 1567 + 1600 1568 return retval; 1601 1569 } 1602 1570 ··· 1776 1808 BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); 1777 1809 1778 1810 err = -ENOMEM; 1779 - pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); 1811 + pages = kcalloc(FUSE_MAX_PAGES_PER_REQ, sizeof(pages[0]), GFP_KERNEL); 1780 1812 iov_page = (struct iovec *) __get_free_page(GFP_KERNEL); 1781 1813 if (!pages || !iov_page) 1782 1814 goto out; ··· 1926 1958 } 1927 1959 EXPORT_SYMBOL_GPL(fuse_do_ioctl); 1928 1960 1929 - static long fuse_file_ioctl_common(struct file *file, unsigned int cmd, 1930 - unsigned long arg, unsigned int flags) 1961 + long fuse_ioctl_common(struct file *file, unsigned int cmd, 1962 + unsigned long arg, unsigned int flags) 1931 1963 { 1932 1964 struct inode *inode = file->f_dentry->d_inode; 1933 1965 struct fuse_conn *fc = get_fuse_conn(inode); ··· 1944 1976 static long fuse_file_ioctl(struct file *file, unsigned int cmd, 1945 1977 unsigned long arg) 1946 1978 { 1947 - return fuse_file_ioctl_common(file, cmd, arg, 0); 1979 + return fuse_ioctl_common(file, cmd, arg, 0); 1948 1980 } 1949 1981 1950 1982 static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, 1951 1983 unsigned long arg) 1952 1984 { 1953 - return fuse_file_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT); 1985 + return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT); 1954 1986 } 1955 1987 1956 1988 /*
+9 -1
fs/fuse/fuse_i.h
··· 755 755 /** 756 756 * File-system tells the kernel to invalidate parent attributes and 757 757 * the dentry matching parent/name. 758 + * 759 + * If the child_nodeid is non-zero and: 760 + * - matches the inode number for the dentry matching parent/name, 761 + * - is not a mount point 762 + * - is a file or oan empty directory 763 + * then the dentry is unhashed (d_delete()). 758 764 */ 759 765 int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 760 - struct qstr *name); 766 + u64 child_nodeid, struct qstr *name); 761 767 762 768 int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, 763 769 bool isdir); ··· 771 765 size_t count, loff_t *ppos, int write); 772 766 long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, 773 767 unsigned int flags); 768 + long fuse_ioctl_common(struct file *file, unsigned int cmd, 769 + unsigned long arg, unsigned int flags); 774 770 unsigned fuse_file_poll(struct file *file, poll_table *wait); 775 771 int fuse_dev_release(struct inode *inode, struct file *file); 776 772
+15 -1
include/linux/fuse.h
··· 50 50 * 51 51 * 7.17 52 52 * - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK 53 + * 54 + * 7.18 55 + * - add FUSE_IOCTL_DIR flag 56 + * - add FUSE_NOTIFY_DELETE 53 57 */ 54 58 55 59 #ifndef _LINUX_FUSE_H ··· 85 81 #define FUSE_KERNEL_VERSION 7 86 82 87 83 /** Minor version number of this interface */ 88 - #define FUSE_KERNEL_MINOR_VERSION 17 84 + #define FUSE_KERNEL_MINOR_VERSION 18 89 85 90 86 /** The node ID of the root inode */ 91 87 #define FUSE_ROOT_ID 1 ··· 218 214 * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed 219 215 * FUSE_IOCTL_RETRY: retry with new iovecs 220 216 * FUSE_IOCTL_32BIT: 32bit ioctl 217 + * FUSE_IOCTL_DIR: is a directory 221 218 * 222 219 * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs 223 220 */ ··· 226 221 #define FUSE_IOCTL_UNRESTRICTED (1 << 1) 227 222 #define FUSE_IOCTL_RETRY (1 << 2) 228 223 #define FUSE_IOCTL_32BIT (1 << 3) 224 + #define FUSE_IOCTL_DIR (1 << 4) 229 225 230 226 #define FUSE_IOCTL_MAX_IOV 256 231 227 ··· 289 283 FUSE_NOTIFY_INVAL_ENTRY = 3, 290 284 FUSE_NOTIFY_STORE = 4, 291 285 FUSE_NOTIFY_RETRIEVE = 5, 286 + FUSE_NOTIFY_DELETE = 6, 292 287 FUSE_NOTIFY_CODE_MAX, 293 288 }; 294 289 ··· 609 602 610 603 struct fuse_notify_inval_entry_out { 611 604 __u64 parent; 605 + __u32 namelen; 606 + __u32 padding; 607 + }; 608 + 609 + struct fuse_notify_delete_out { 610 + __u64 parent; 611 + __u64 child; 612 612 __u32 namelen; 613 613 __u32 padding; 614 614 };