aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dir.c
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 /fs/fuse/dir.c
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
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r--fs/fuse/dir.c58
1 files changed, 56 insertions, 2 deletions
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 = {