|
@@ -206,7 +206,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
|
|
|
BUG();
|
|
|
}
|
|
|
|
|
|
-static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
|
|
|
+int fuse_inode_eq(struct inode *inode, void *_nodeidp)
|
|
|
{
|
|
|
u64 nodeid = *(u64 *) _nodeidp;
|
|
|
if (get_node_id(inode) == nodeid)
|
|
@@ -257,6 +257,31 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
|
|
|
return inode;
|
|
|
}
|
|
|
|
|
|
+int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
|
|
|
+ loff_t offset, loff_t len)
|
|
|
+{
|
|
|
+ struct inode *inode;
|
|
|
+ pgoff_t pg_start;
|
|
|
+ pgoff_t pg_end;
|
|
|
+
|
|
|
+ inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid);
|
|
|
+ if (!inode)
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ fuse_invalidate_attr(inode);
|
|
|
+ if (offset >= 0) {
|
|
|
+ pg_start = offset >> PAGE_CACHE_SHIFT;
|
|
|
+ if (len <= 0)
|
|
|
+ pg_end = -1;
|
|
|
+ else
|
|
|
+ pg_end = (offset + len - 1) >> PAGE_CACHE_SHIFT;
|
|
|
+ invalidate_inode_pages2_range(inode->i_mapping,
|
|
|
+ pg_start, pg_end);
|
|
|
+ }
|
|
|
+ iput(inode);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void fuse_umount_begin(struct super_block *sb)
|
|
|
{
|
|
|
fuse_abort_conn(get_fuse_conn_super(sb));
|
|
@@ -480,6 +505,7 @@ void fuse_conn_init(struct fuse_conn *fc)
|
|
|
memset(fc, 0, sizeof(*fc));
|
|
|
spin_lock_init(&fc->lock);
|
|
|
mutex_init(&fc->inst_mutex);
|
|
|
+ init_rwsem(&fc->killsb);
|
|
|
atomic_set(&fc->count, 1);
|
|
|
init_waitqueue_head(&fc->waitq);
|
|
|
init_waitqueue_head(&fc->blocked_waitq);
|
|
@@ -725,6 +751,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
|
|
|
}
|
|
|
if (arg->flags & FUSE_BIG_WRITES)
|
|
|
fc->big_writes = 1;
|
|
|
+ if (arg->flags & FUSE_DONT_MASK)
|
|
|
+ fc->dont_mask = 1;
|
|
|
} else {
|
|
|
ra_pages = fc->max_read / PAGE_CACHE_SIZE;
|
|
|
fc->no_lock = 1;
|
|
@@ -748,7 +776,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
|
|
|
arg->minor = FUSE_KERNEL_MINOR_VERSION;
|
|
|
arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
|
|
|
arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
|
|
|
- FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES;
|
|
|
+ FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK;
|
|
|
req->in.h.opcode = FUSE_INIT;
|
|
|
req->in.numargs = 1;
|
|
|
req->in.args[0].size = sizeof(*arg);
|
|
@@ -860,10 +888,16 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
fuse_conn_init(fc);
|
|
|
|
|
|
fc->dev = sb->s_dev;
|
|
|
+ fc->sb = sb;
|
|
|
err = fuse_bdi_init(fc, sb);
|
|
|
if (err)
|
|
|
goto err_put_conn;
|
|
|
|
|
|
+ /* Handle umasking inside the fuse code */
|
|
|
+ if (sb->s_flags & MS_POSIXACL)
|
|
|
+ fc->dont_mask = 1;
|
|
|
+ sb->s_flags |= MS_POSIXACL;
|
|
|
+
|
|
|
fc->release = fuse_free_conn;
|
|
|
fc->flags = d.flags;
|
|
|
fc->user_id = d.user_id;
|
|
@@ -941,12 +975,25 @@ static int fuse_get_sb(struct file_system_type *fs_type,
|
|
|
return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt);
|
|
|
}
|
|
|
|
|
|
+static void fuse_kill_sb_anon(struct super_block *sb)
|
|
|
+{
|
|
|
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
|
|
|
+
|
|
|
+ if (fc) {
|
|
|
+ down_write(&fc->killsb);
|
|
|
+ fc->sb = NULL;
|
|
|
+ up_write(&fc->killsb);
|
|
|
+ }
|
|
|
+
|
|
|
+ kill_anon_super(sb);
|
|
|
+}
|
|
|
+
|
|
|
static struct file_system_type fuse_fs_type = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.name = "fuse",
|
|
|
.fs_flags = FS_HAS_SUBTYPE,
|
|
|
.get_sb = fuse_get_sb,
|
|
|
- .kill_sb = kill_anon_super,
|
|
|
+ .kill_sb = fuse_kill_sb_anon,
|
|
|
};
|
|
|
|
|
|
#ifdef CONFIG_BLOCK
|
|
@@ -958,11 +1005,24 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type,
|
|
|
mnt);
|
|
|
}
|
|
|
|
|
|
+static void fuse_kill_sb_blk(struct super_block *sb)
|
|
|
+{
|
|
|
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
|
|
|
+
|
|
|
+ if (fc) {
|
|
|
+ down_write(&fc->killsb);
|
|
|
+ fc->sb = NULL;
|
|
|
+ up_write(&fc->killsb);
|
|
|
+ }
|
|
|
+
|
|
|
+ kill_block_super(sb);
|
|
|
+}
|
|
|
+
|
|
|
static struct file_system_type fuseblk_fs_type = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.name = "fuseblk",
|
|
|
.get_sb = fuse_get_sb_blk,
|
|
|
- .kill_sb = kill_block_super,
|
|
|
+ .kill_sb = fuse_kill_sb_blk,
|
|
|
.fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE,
|
|
|
};
|
|
|
|