aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-12 15:39:21 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-12 15:39:21 -0500
commit6733e54b669c600eb8e451939ad55130db664fed (patch)
tree2a8c24c856fa3f5d7d58a3eb39da943ca1c57e65
parentbcf8a3dfcb274cf6654a19e12e244f3af8c0d355 (diff)
parent451d0f599934fd97faf54a5d7954b518e66192cb (diff)
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
-rw-r--r--fs/fuse/dev.c57
-rw-r--r--fs/fuse/dir.c58
-rw-r--r--fs/fuse/file.c58
-rw-r--r--fs/fuse/fuse_i.h10
-rw-r--r--include/linux/fuse.h16
5 files changed, 149 insertions, 50 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 2aaf3eaaf13d..5f3368ab0fa9 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1378,7 +1378,59 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
1378 down_read(&fc->killsb); 1378 down_read(&fc->killsb);
1379 err = -ENOENT; 1379 err = -ENOENT;
1380 if (fc->sb) 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
1386err:
1387 kfree(buf);
1388 fuse_copy_finish(cs);
1389 return err;
1390}
1391
1392static 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 up_read(&fc->killsb); 1434 up_read(&fc->killsb);
1383 kfree(buf); 1435 kfree(buf);
1384 return err; 1436 return err;
@@ -1597,6 +1649,9 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
1597 case FUSE_NOTIFY_RETRIEVE: 1649 case FUSE_NOTIFY_RETRIEVE:
1598 return fuse_notify_retrieve(fc, size, cs); 1650 return fuse_notify_retrieve(fc, size, cs);
1599 1651
1652 case FUSE_NOTIFY_DELETE:
1653 return fuse_notify_delete(fc, size, cs);
1654
1600 default: 1655 default:
1601 fuse_copy_finish(cs); 1656 fuse_copy_finish(cs);
1602 return -EINVAL; 1657 return -EINVAL;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 5ddd6ea8f839..206632887bb4 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -868,7 +868,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
868} 868}
869 869
870int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 870int 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 int err = -ENOTDIR; 873 int err = -ENOTDIR;
874 struct inode *parent; 874 struct inode *parent;
@@ -895,8 +895,36 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
895 895
896 fuse_invalidate_attr(parent); 896 fuse_invalidate_attr(parent);
897 fuse_invalidate_entry(entry); 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 dput(entry); 927 dput(entry);
899 err = 0;
900 928
901 unlock: 929 unlock:
902 mutex_unlock(&parent->i_mutex); 930 mutex_unlock(&parent->i_mutex);
@@ -1182,6 +1210,30 @@ static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1182 return fuse_fsync_common(file, start, end, datasync, 1); 1210 return fuse_fsync_common(file, start, end, datasync, 1);
1183} 1211}
1184 1212
1213static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1214 unsigned long arg)
1215{
1216 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1217
1218 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1219 if (fc->minor < 18)
1220 return -ENOTTY;
1221
1222 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1223}
1224
1225static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1226 unsigned long arg)
1227{
1228 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1229
1230 if (fc->minor < 18)
1231 return -ENOTTY;
1232
1233 return fuse_ioctl_common(file, cmd, arg,
1234 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1235}
1236
1185static bool update_mtime(unsigned ivalid) 1237static bool update_mtime(unsigned ivalid)
1186{ 1238{
1187 /* Always update if mtime is explicitly set */ 1239 /* Always update if mtime is explicitly set */
@@ -1596,6 +1648,8 @@ static const struct file_operations fuse_dir_operations = {
1596 .open = fuse_dir_open, 1648 .open = fuse_dir_open,
1597 .release = fuse_dir_release, 1649 .release = fuse_dir_release,
1598 .fsync = fuse_dir_fsync, 1650 .fsync = fuse_dir_fsync,
1651 .unlocked_ioctl = fuse_dir_ioctl,
1652 .compat_ioctl = fuse_dir_compat_ioctl,
1599}; 1653};
1600 1654
1601static const struct inode_operations fuse_common_inode_operations = { 1655static const struct inode_operations fuse_common_inode_operations = {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 0c84100acd44..4a199fd93fbd 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1555,48 +1555,16 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin)
1555 loff_t retval; 1555 loff_t retval;
1556 struct inode *inode = file->f_path.dentry->d_inode; 1556 struct inode *inode = file->f_path.dentry->d_inode;
1557 1557
1558 mutex_lock(&inode->i_mutex); 1558 /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
1559 if (origin != SEEK_CUR && origin != SEEK_SET) { 1559 if (origin == SEEK_CUR || origin == SEEK_SET)
1560 retval = fuse_update_attributes(inode, NULL, file, NULL); 1560 return generic_file_llseek(file, offset, origin);
1561 if (retval)
1562 goto exit;
1563 }
1564 1561
1565 switch (origin) { 1562 mutex_lock(&inode->i_mutex);
1566 case SEEK_END: 1563 retval = fuse_update_attributes(inode, NULL, file, NULL);
1567 offset += i_size_read(inode); 1564 if (!retval)
1568 break; 1565 retval = generic_file_llseek(file, offset, origin);
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 }
1598exit:
1599 mutex_unlock(&inode->i_mutex); 1566 mutex_unlock(&inode->i_mutex);
1567
1600 return retval; 1568 return retval;
1601} 1569}
1602 1570
@@ -1808,7 +1776,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1808 BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); 1776 BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);
1809 1777
1810 err = -ENOMEM; 1778 err = -ENOMEM;
1811 pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); 1779 pages = kcalloc(FUSE_MAX_PAGES_PER_REQ, sizeof(pages[0]), GFP_KERNEL);
1812 iov_page = (struct iovec *) __get_free_page(GFP_KERNEL); 1780 iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);
1813 if (!pages || !iov_page) 1781 if (!pages || !iov_page)
1814 goto out; 1782 goto out;
@@ -1958,8 +1926,8 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1958} 1926}
1959EXPORT_SYMBOL_GPL(fuse_do_ioctl); 1927EXPORT_SYMBOL_GPL(fuse_do_ioctl);
1960 1928
1961static long fuse_file_ioctl_common(struct file *file, unsigned int cmd, 1929long fuse_ioctl_common(struct file *file, unsigned int cmd,
1962 unsigned long arg, unsigned int flags) 1930 unsigned long arg, unsigned int flags)
1963{ 1931{
1964 struct inode *inode = file->f_dentry->d_inode; 1932 struct inode *inode = file->f_dentry->d_inode;
1965 struct fuse_conn *fc = get_fuse_conn(inode); 1933 struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1976,13 +1944,13 @@ static long fuse_file_ioctl_common(struct file *file, unsigned int cmd,
1976static long fuse_file_ioctl(struct file *file, unsigned int cmd, 1944static long fuse_file_ioctl(struct file *file, unsigned int cmd,
1977 unsigned long arg) 1945 unsigned long arg)
1978{ 1946{
1979 return fuse_file_ioctl_common(file, cmd, arg, 0); 1947 return fuse_ioctl_common(file, cmd, arg, 0);
1980} 1948}
1981 1949
1982static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, 1950static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
1983 unsigned long arg) 1951 unsigned long arg)
1984{ 1952{
1985 return fuse_file_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT); 1953 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);
1986} 1954}
1987 1955
1988/* 1956/*
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 1964da0257d9..572cefc78012 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -755,9 +755,15 @@ int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
755/** 755/**
756 * File-system tells the kernel to invalidate parent attributes and 756 * File-system tells the kernel to invalidate parent attributes and
757 * the dentry matching parent/name. 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 */
759int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 765int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
760 struct qstr *name); 766 u64 child_nodeid, struct qstr *name);
761 767
762int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, 768int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
763 bool isdir); 769 bool isdir);
@@ -765,6 +771,8 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf,
765 size_t count, loff_t *ppos, int write); 771 size_t count, loff_t *ppos, int write);
766long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, 772long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
767 unsigned int flags); 773 unsigned int flags);
774long fuse_ioctl_common(struct file *file, unsigned int cmd,
775 unsigned long arg, unsigned int flags);
768unsigned fuse_file_poll(struct file *file, poll_table *wait); 776unsigned fuse_file_poll(struct file *file, poll_table *wait);
769int fuse_dev_release(struct inode *inode, struct file *file); 777int fuse_dev_release(struct inode *inode, struct file *file);
770 778
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 464cff526860..8ba2c9460b28 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -50,6 +50,10 @@
50 * 50 *
51 * 7.17 51 * 7.17
52 * - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK 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#ifndef _LINUX_FUSE_H 59#ifndef _LINUX_FUSE_H
@@ -81,7 +85,7 @@
81#define FUSE_KERNEL_VERSION 7 85#define FUSE_KERNEL_VERSION 7
82 86
83/** Minor version number of this interface */ 87/** Minor version number of this interface */
84#define FUSE_KERNEL_MINOR_VERSION 17 88#define FUSE_KERNEL_MINOR_VERSION 18
85 89
86/** The node ID of the root inode */ 90/** The node ID of the root inode */
87#define FUSE_ROOT_ID 1 91#define FUSE_ROOT_ID 1
@@ -214,6 +218,7 @@ struct fuse_file_lock {
214 * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed 218 * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
215 * FUSE_IOCTL_RETRY: retry with new iovecs 219 * FUSE_IOCTL_RETRY: retry with new iovecs
216 * FUSE_IOCTL_32BIT: 32bit ioctl 220 * FUSE_IOCTL_32BIT: 32bit ioctl
221 * FUSE_IOCTL_DIR: is a directory
217 * 222 *
218 * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs 223 * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
219 */ 224 */
@@ -221,6 +226,7 @@ struct fuse_file_lock {
221#define FUSE_IOCTL_UNRESTRICTED (1 << 1) 226#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
222#define FUSE_IOCTL_RETRY (1 << 2) 227#define FUSE_IOCTL_RETRY (1 << 2)
223#define FUSE_IOCTL_32BIT (1 << 3) 228#define FUSE_IOCTL_32BIT (1 << 3)
229#define FUSE_IOCTL_DIR (1 << 4)
224 230
225#define FUSE_IOCTL_MAX_IOV 256 231#define FUSE_IOCTL_MAX_IOV 256
226 232
@@ -283,6 +289,7 @@ enum fuse_notify_code {
283 FUSE_NOTIFY_INVAL_ENTRY = 3, 289 FUSE_NOTIFY_INVAL_ENTRY = 3,
284 FUSE_NOTIFY_STORE = 4, 290 FUSE_NOTIFY_STORE = 4,
285 FUSE_NOTIFY_RETRIEVE = 5, 291 FUSE_NOTIFY_RETRIEVE = 5,
292 FUSE_NOTIFY_DELETE = 6,
286 FUSE_NOTIFY_CODE_MAX, 293 FUSE_NOTIFY_CODE_MAX,
287}; 294};
288 295
@@ -606,6 +613,13 @@ struct fuse_notify_inval_entry_out {
606 __u32 padding; 613 __u32 padding;
607}; 614};
608 615
616struct fuse_notify_delete_out {
617 __u64 parent;
618 __u64 child;
619 __u32 namelen;
620 __u32 padding;
621};
622
609struct fuse_notify_store_out { 623struct fuse_notify_store_out {
610 __u64 nodeid; 624 __u64 nodeid;
611 __u64 offset; 625 __u64 offset;