aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/fuse.txt30
-rw-r--r--fs/fuse/Makefile2
-rw-r--r--fs/fuse/control.c218
-rw-r--r--fs/fuse/dev.c2
-rw-r--r--fs/fuse/fuse_i.h53
-rw-r--r--fs/fuse/inode.c141
6 files changed, 331 insertions, 115 deletions
diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt
index e7747774ceb..324df27704c 100644
--- a/Documentation/filesystems/fuse.txt
+++ b/Documentation/filesystems/fuse.txt
@@ -18,6 +18,14 @@ Non-privileged mount (or user mount):
18 user. NOTE: this is not the same as mounts allowed with the "user" 18 user. NOTE: this is not the same as mounts allowed with the "user"
19 option in /etc/fstab, which is not discussed here. 19 option in /etc/fstab, which is not discussed here.
20 20
21Filesystem connection:
22
23 A connection between the filesystem daemon and the kernel. The
24 connection exists until either the daemon dies, or the filesystem is
25 umounted. Note that detaching (or lazy umounting) the filesystem
26 does _not_ break the connection, in this case it will exist until
27 the last reference to the filesystem is released.
28
21Mount owner: 29Mount owner:
22 30
23 The user who does the mounting. 31 The user who does the mounting.
@@ -86,16 +94,20 @@ Mount options
86 The default is infinite. Note that the size of read requests is 94 The default is infinite. Note that the size of read requests is
87 limited anyway to 32 pages (which is 128kbyte on i386). 95 limited anyway to 32 pages (which is 128kbyte on i386).
88 96
89Sysfs 97Control filesystem
90~~~~~ 98~~~~~~~~~~~~~~~~~~
99
100There's a control filesystem for FUSE, which can be mounted by:
91 101
92FUSE sets up the following hierarchy in sysfs: 102 mount -t fusectl none /sys/fs/fuse/connections
93 103
94 /sys/fs/fuse/connections/N/ 104Mounting it under the '/sys/fs/fuse/connections' directory makes it
105backwards compatible with earlier versions.
95 106
96where N is an increasing number allocated to each new connection. 107Under the fuse control filesystem each connection has a directory
108named by a unique number.
97 109
98For each connection the following attributes are defined: 110For each connection the following files exist within this directory:
99 111
100 'waiting' 112 'waiting'
101 113
@@ -110,7 +122,7 @@ For each connection the following attributes are defined:
110 connection. This means that all waiting requests will be aborted an 122 connection. This means that all waiting requests will be aborted an
111 error returned for all aborted and new requests. 123 error returned for all aborted and new requests.
112 124
113Only a privileged user may read or write these attributes. 125Only the owner of the mount may read or write these files.
114 126
115Aborting a filesystem connection 127Aborting a filesystem connection
116~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 128~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -139,8 +151,8 @@ the filesystem. There are several ways to do this:
139 - Use forced umount (umount -f). Works in all cases but only if 151 - Use forced umount (umount -f). Works in all cases but only if
140 filesystem is still attached (it hasn't been lazy unmounted) 152 filesystem is still attached (it hasn't been lazy unmounted)
141 153
142 - Abort filesystem through the sysfs interface. Most powerful 154 - Abort filesystem through the FUSE control filesystem. Most
143 method, always works. 155 powerful method, always works.
144 156
145How do non-privileged mounts work? 157How do non-privileged mounts work?
146~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 158~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
index c3e1f760cac..72437065f6a 100644
--- a/fs/fuse/Makefile
+++ b/fs/fuse/Makefile
@@ -4,4 +4,4 @@
4 4
5obj-$(CONFIG_FUSE_FS) += fuse.o 5obj-$(CONFIG_FUSE_FS) += fuse.o
6 6
7fuse-objs := dev.o dir.o file.o inode.o 7fuse-objs := dev.o dir.o file.o inode.o control.o
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
new file mode 100644
index 00000000000..a3bce3a7725
--- /dev/null
+++ b/fs/fuse/control.c
@@ -0,0 +1,218 @@
1/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
11#include <linux/init.h>
12#include <linux/module.h>
13
14#define FUSE_CTL_SUPER_MAGIC 0x65735543
15
16/*
17 * This is non-NULL when the single instance of the control filesystem
18 * exists. Protected by fuse_mutex
19 */
20static struct super_block *fuse_control_sb;
21
22static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
23{
24 struct fuse_conn *fc;
25 mutex_lock(&fuse_mutex);
26 fc = file->f_dentry->d_inode->u.generic_ip;
27 if (fc)
28 fc = fuse_conn_get(fc);
29 mutex_unlock(&fuse_mutex);
30 return fc;
31}
32
33static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
34 size_t count, loff_t *ppos)
35{
36 struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
37 if (fc) {
38 fuse_abort_conn(fc);
39 fuse_conn_put(fc);
40 }
41 return count;
42}
43
44static ssize_t fuse_conn_waiting_read(struct file *file, char __user *buf,
45 size_t len, loff_t *ppos)
46{
47 char tmp[32];
48 size_t size;
49
50 if (!*ppos) {
51 struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
52 if (!fc)
53 return 0;
54
55 file->private_data=(void *)(long)atomic_read(&fc->num_waiting);
56 fuse_conn_put(fc);
57 }
58 size = sprintf(tmp, "%ld\n", (long)file->private_data);
59 return simple_read_from_buffer(buf, len, ppos, tmp, size);
60}
61
62static const struct file_operations fuse_ctl_abort_ops = {
63 .open = nonseekable_open,
64 .write = fuse_conn_abort_write,
65};
66
67static const struct file_operations fuse_ctl_waiting_ops = {
68 .open = nonseekable_open,
69 .read = fuse_conn_waiting_read,
70};
71
72static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
73 struct fuse_conn *fc,
74 const char *name,
75 int mode, int nlink,
76 struct inode_operations *iop,
77 const struct file_operations *fop)
78{
79 struct dentry *dentry;
80 struct inode *inode;
81
82 BUG_ON(fc->ctl_ndents >= FUSE_CTL_NUM_DENTRIES);
83 dentry = d_alloc_name(parent, name);
84 if (!dentry)
85 return NULL;
86
87 fc->ctl_dentry[fc->ctl_ndents++] = dentry;
88 inode = new_inode(fuse_control_sb);
89 if (!inode)
90 return NULL;
91
92 inode->i_mode = mode;
93 inode->i_uid = fc->user_id;
94 inode->i_gid = fc->group_id;
95 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
96 /* setting ->i_op to NULL is not allowed */
97 if (iop)
98 inode->i_op = iop;
99 inode->i_fop = fop;
100 inode->i_nlink = nlink;
101 inode->u.generic_ip = fc;
102 d_add(dentry, inode);
103 return dentry;
104}
105
106/*
107 * Add a connection to the control filesystem (if it exists). Caller
108 * must host fuse_mutex
109 */
110int fuse_ctl_add_conn(struct fuse_conn *fc)
111{
112 struct dentry *parent;
113 char name[32];
114
115 if (!fuse_control_sb)
116 return 0;
117
118 parent = fuse_control_sb->s_root;
119 parent->d_inode->i_nlink++;
120 sprintf(name, "%llu", (unsigned long long) fc->id);
121 parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
122 &simple_dir_inode_operations,
123 &simple_dir_operations);
124 if (!parent)
125 goto err;
126
127 if (!fuse_ctl_add_dentry(parent, fc, "waiting", S_IFREG | 0400, 1,
128 NULL, &fuse_ctl_waiting_ops) ||
129 !fuse_ctl_add_dentry(parent, fc, "abort", S_IFREG | 0200, 1,
130 NULL, &fuse_ctl_abort_ops))
131 goto err;
132
133 return 0;
134
135 err:
136 fuse_ctl_remove_conn(fc);
137 return -ENOMEM;
138}
139
140/*
141 * Remove a connection from the control filesystem (if it exists).
142 * Caller must host fuse_mutex
143 */
144void fuse_ctl_remove_conn(struct fuse_conn *fc)
145{
146 int i;
147
148 if (!fuse_control_sb)
149 return;
150
151 for (i = fc->ctl_ndents - 1; i >= 0; i--) {
152 struct dentry *dentry = fc->ctl_dentry[i];
153 dentry->d_inode->u.generic_ip = NULL;
154 d_drop(dentry);
155 dput(dentry);
156 }
157 fuse_control_sb->s_root->d_inode->i_nlink--;
158}
159
160static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
161{
162 struct tree_descr empty_descr = {""};
163 struct fuse_conn *fc;
164 int err;
165
166 err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
167 if (err)
168 return err;
169
170 mutex_lock(&fuse_mutex);
171 BUG_ON(fuse_control_sb);
172 fuse_control_sb = sb;
173 list_for_each_entry(fc, &fuse_conn_list, entry) {
174 err = fuse_ctl_add_conn(fc);
175 if (err) {
176 fuse_control_sb = NULL;
177 mutex_unlock(&fuse_mutex);
178 return err;
179 }
180 }
181 mutex_unlock(&fuse_mutex);
182
183 return 0;
184}
185
186static int fuse_ctl_get_sb(struct file_system_type *fs_type, int flags,
187 const char *dev_name, void *raw_data,
188 struct vfsmount *mnt)
189{
190 return get_sb_single(fs_type, flags, raw_data,
191 fuse_ctl_fill_super, mnt);
192}
193
194static void fuse_ctl_kill_sb(struct super_block *sb)
195{
196 mutex_lock(&fuse_mutex);
197 fuse_control_sb = NULL;
198 mutex_unlock(&fuse_mutex);
199
200 kill_litter_super(sb);
201}
202
203static struct file_system_type fuse_ctl_fs_type = {
204 .owner = THIS_MODULE,
205 .name = "fusectl",
206 .get_sb = fuse_ctl_get_sb,
207 .kill_sb = fuse_ctl_kill_sb,
208};
209
210int __init fuse_ctl_init(void)
211{
212 return register_filesystem(&fuse_ctl_fs_type);
213}
214
215void fuse_ctl_cleanup(void)
216{
217 unregister_filesystem(&fuse_ctl_fs_type);
218}
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index fec4779e2b5..fe3adf58917 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -833,7 +833,7 @@ static int fuse_dev_release(struct inode *inode, struct file *file)
833 end_requests(fc, &fc->processing); 833 end_requests(fc, &fc->processing);
834 spin_unlock(&fc->lock); 834 spin_unlock(&fc->lock);
835 fasync_helper(-1, file, 0, &fc->fasync); 835 fasync_helper(-1, file, 0, &fc->fasync);
836 kobject_put(&fc->kobj); 836 fuse_conn_put(fc);
837 } 837 }
838 838
839 return 0; 839 return 0;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 25f8581a770..ac12b01f444 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -14,6 +14,7 @@
14#include <linux/spinlock.h> 14#include <linux/spinlock.h>
15#include <linux/mm.h> 15#include <linux/mm.h>
16#include <linux/backing-dev.h> 16#include <linux/backing-dev.h>
17#include <linux/mutex.h>
17 18
18/** Max number of pages that can be used in a single read request */ 19/** Max number of pages that can be used in a single read request */
19#define FUSE_MAX_PAGES_PER_REQ 32 20#define FUSE_MAX_PAGES_PER_REQ 32
@@ -24,6 +25,9 @@
24/** It could be as large as PATH_MAX, but would that have any uses? */ 25/** It could be as large as PATH_MAX, but would that have any uses? */
25#define FUSE_NAME_MAX 1024 26#define FUSE_NAME_MAX 1024
26 27
28/** Number of dentries for each connection in the control filesystem */
29#define FUSE_CTL_NUM_DENTRIES 3
30
27/** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem 31/** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem
28 module will check permissions based on the file mode. Otherwise no 32 module will check permissions based on the file mode. Otherwise no
29 permission checking is done in the kernel */ 33 permission checking is done in the kernel */
@@ -33,6 +37,11 @@
33 doing the mount will be allowed to access the filesystem */ 37 doing the mount will be allowed to access the filesystem */
34#define FUSE_ALLOW_OTHER (1 << 1) 38#define FUSE_ALLOW_OTHER (1 << 1)
35 39
40/** List of active connections */
41extern struct list_head fuse_conn_list;
42
43/** Global mutex protecting fuse_conn_list and the control filesystem */
44extern struct mutex fuse_mutex;
36 45
37/** FUSE inode */ 46/** FUSE inode */
38struct fuse_inode { 47struct fuse_inode {
@@ -216,6 +225,9 @@ struct fuse_conn {
216 /** Lock protecting accessess to members of this structure */ 225 /** Lock protecting accessess to members of this structure */
217 spinlock_t lock; 226 spinlock_t lock;
218 227
228 /** Refcount */
229 atomic_t count;
230
219 /** The user id for this mount */ 231 /** The user id for this mount */
220 uid_t user_id; 232 uid_t user_id;
221 233
@@ -310,8 +322,17 @@ struct fuse_conn {
310 /** Backing dev info */ 322 /** Backing dev info */
311 struct backing_dev_info bdi; 323 struct backing_dev_info bdi;
312 324
313 /** kobject */ 325 /** Entry on the fuse_conn_list */
314 struct kobject kobj; 326 struct list_head entry;
327
328 /** Unique ID */
329 u64 id;
330
331 /** Dentries in the control filesystem */
332 struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES];
333
334 /** number of dentries used in the above array */
335 int ctl_ndents;
315 336
316 /** O_ASYNC requests */ 337 /** O_ASYNC requests */
317 struct fasync_struct *fasync; 338 struct fasync_struct *fasync;
@@ -327,11 +348,6 @@ static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
327 return get_fuse_conn_super(inode->i_sb); 348 return get_fuse_conn_super(inode->i_sb);
328} 349}
329 350
330static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj)
331{
332 return container_of(obj, struct fuse_conn, kobj);
333}
334
335static inline struct fuse_inode *get_fuse_inode(struct inode *inode) 351static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
336{ 352{
337 return container_of(inode, struct fuse_inode, inode); 353 return container_of(inode, struct fuse_inode, inode);
@@ -422,6 +438,9 @@ int fuse_dev_init(void);
422 */ 438 */
423void fuse_dev_cleanup(void); 439void fuse_dev_cleanup(void);
424 440
441int fuse_ctl_init(void);
442void fuse_ctl_cleanup(void);
443
425/** 444/**
426 * Allocate a request 445 * Allocate a request
427 */ 446 */
@@ -470,3 +489,23 @@ int fuse_do_getattr(struct inode *inode);
470 * Invalidate inode attributes 489 * Invalidate inode attributes
471 */ 490 */
472void fuse_invalidate_attr(struct inode *inode); 491void fuse_invalidate_attr(struct inode *inode);
492
493/**
494 * Acquire reference to fuse_conn
495 */
496struct fuse_conn *fuse_conn_get(struct fuse_conn *fc);
497
498/**
499 * Release reference to fuse_conn
500 */
501void fuse_conn_put(struct fuse_conn *fc);
502
503/**
504 * Add connection to control filesystem
505 */
506int fuse_ctl_add_conn(struct fuse_conn *fc);
507
508/**
509 * Remove connection from control filesystem
510 */
511void fuse_ctl_remove_conn(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 0225729977c..13a7e8ab7a7 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -22,13 +22,8 @@ MODULE_DESCRIPTION("Filesystem in Userspace");
22MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
23 23
24static kmem_cache_t *fuse_inode_cachep; 24static kmem_cache_t *fuse_inode_cachep;
25static struct subsystem connections_subsys; 25struct list_head fuse_conn_list;
26 26DEFINE_MUTEX(fuse_mutex);
27struct fuse_conn_attr {
28 struct attribute attr;
29 ssize_t (*show)(struct fuse_conn *, char *);
30 ssize_t (*store)(struct fuse_conn *, const char *, size_t);
31};
32 27
33#define FUSE_SUPER_MAGIC 0x65735546 28#define FUSE_SUPER_MAGIC 0x65735546
34 29
@@ -211,8 +206,11 @@ static void fuse_put_super(struct super_block *sb)
211 kill_fasync(&fc->fasync, SIGIO, POLL_IN); 206 kill_fasync(&fc->fasync, SIGIO, POLL_IN);
212 wake_up_all(&fc->waitq); 207 wake_up_all(&fc->waitq);
213 wake_up_all(&fc->blocked_waitq); 208 wake_up_all(&fc->blocked_waitq);
214 kobject_del(&fc->kobj); 209 mutex_lock(&fuse_mutex);
215 kobject_put(&fc->kobj); 210 list_del(&fc->entry);
211 fuse_ctl_remove_conn(fc);
212 mutex_unlock(&fuse_mutex);
213 fuse_conn_put(fc);
216} 214}
217 215
218static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 216static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
@@ -362,11 +360,6 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
362 return 0; 360 return 0;
363} 361}
364 362
365static void fuse_conn_release(struct kobject *kobj)
366{
367 kfree(get_fuse_conn_kobj(kobj));
368}
369
370static struct fuse_conn *new_conn(void) 363static struct fuse_conn *new_conn(void)
371{ 364{
372 struct fuse_conn *fc; 365 struct fuse_conn *fc;
@@ -374,13 +367,12 @@ static struct fuse_conn *new_conn(void)
374 fc = kzalloc(sizeof(*fc), GFP_KERNEL); 367 fc = kzalloc(sizeof(*fc), GFP_KERNEL);
375 if (fc) { 368 if (fc) {
376 spin_lock_init(&fc->lock); 369 spin_lock_init(&fc->lock);
370 atomic_set(&fc->count, 1);
377 init_waitqueue_head(&fc->waitq); 371 init_waitqueue_head(&fc->waitq);
378 init_waitqueue_head(&fc->blocked_waitq); 372 init_waitqueue_head(&fc->blocked_waitq);
379 INIT_LIST_HEAD(&fc->pending); 373 INIT_LIST_HEAD(&fc->pending);
380 INIT_LIST_HEAD(&fc->processing); 374 INIT_LIST_HEAD(&fc->processing);
381 INIT_LIST_HEAD(&fc->io); 375 INIT_LIST_HEAD(&fc->io);
382 kobj_set_kset_s(fc, connections_subsys);
383 kobject_init(&fc->kobj);
384 atomic_set(&fc->num_waiting, 0); 376 atomic_set(&fc->num_waiting, 0);
385 fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; 377 fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
386 fc->bdi.unplug_io_fn = default_unplug_io_fn; 378 fc->bdi.unplug_io_fn = default_unplug_io_fn;
@@ -390,6 +382,18 @@ static struct fuse_conn *new_conn(void)
390 return fc; 382 return fc;
391} 383}
392 384
385void fuse_conn_put(struct fuse_conn *fc)
386{
387 if (atomic_dec_and_test(&fc->count))
388 kfree(fc);
389}
390
391struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)
392{
393 atomic_inc(&fc->count);
394 return fc;
395}
396
393static struct inode *get_root_inode(struct super_block *sb, unsigned mode) 397static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
394{ 398{
395 struct fuse_attr attr; 399 struct fuse_attr attr;
@@ -459,10 +463,9 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
459 request_send_background(fc, req); 463 request_send_background(fc, req);
460} 464}
461 465
462static unsigned long long conn_id(void) 466static u64 conn_id(void)
463{ 467{
464 /* BKL is held for ->get_sb() */ 468 static u64 ctr = 1;
465 static unsigned long long ctr = 1;
466 return ctr++; 469 return ctr++;
467} 470}
468 471
@@ -519,24 +522,21 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
519 if (!init_req) 522 if (!init_req)
520 goto err_put_root; 523 goto err_put_root;
521 524
522 err = kobject_set_name(&fc->kobj, "%llu", conn_id()); 525 mutex_lock(&fuse_mutex);
523 if (err)
524 goto err_free_req;
525
526 err = kobject_add(&fc->kobj);
527 if (err)
528 goto err_free_req;
529
530 /* Setting file->private_data can't race with other mount()
531 instances, since BKL is held for ->get_sb() */
532 err = -EINVAL; 526 err = -EINVAL;
533 if (file->private_data) 527 if (file->private_data)
534 goto err_kobject_del; 528 goto err_unlock;
535 529
530 fc->id = conn_id();
531 err = fuse_ctl_add_conn(fc);
532 if (err)
533 goto err_unlock;
534
535 list_add_tail(&fc->entry, &fuse_conn_list);
536 sb->s_root = root_dentry; 536 sb->s_root = root_dentry;
537 fc->connected = 1; 537 fc->connected = 1;
538 kobject_get(&fc->kobj); 538 file->private_data = fuse_conn_get(fc);
539 file->private_data = fc; 539 mutex_unlock(&fuse_mutex);
540 /* 540 /*
541 * atomic_dec_and_test() in fput() provides the necessary 541 * atomic_dec_and_test() in fput() provides the necessary
542 * memory barrier for file->private_data to be visible on all 542 * memory barrier for file->private_data to be visible on all
@@ -548,15 +548,14 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
548 548
549 return 0; 549 return 0;
550 550
551 err_kobject_del: 551 err_unlock:
552 kobject_del(&fc->kobj); 552 mutex_unlock(&fuse_mutex);
553 err_free_req:
554 fuse_request_free(init_req); 553 fuse_request_free(init_req);
555 err_put_root: 554 err_put_root:
556 dput(root_dentry); 555 dput(root_dentry);
557 err: 556 err:
558 fput(file); 557 fput(file);
559 kobject_put(&fc->kobj); 558 fuse_conn_put(fc);
560 return err; 559 return err;
561} 560}
562 561
@@ -574,68 +573,8 @@ static struct file_system_type fuse_fs_type = {
574 .kill_sb = kill_anon_super, 573 .kill_sb = kill_anon_super,
575}; 574};
576 575
577static ssize_t fuse_conn_waiting_show(struct fuse_conn *fc, char *page)
578{
579 return sprintf(page, "%i\n", atomic_read(&fc->num_waiting));
580}
581
582static ssize_t fuse_conn_abort_store(struct fuse_conn *fc, const char *page,
583 size_t count)
584{
585 fuse_abort_conn(fc);
586 return count;
587}
588
589static struct fuse_conn_attr fuse_conn_waiting =
590 __ATTR(waiting, 0400, fuse_conn_waiting_show, NULL);
591static struct fuse_conn_attr fuse_conn_abort =
592 __ATTR(abort, 0600, NULL, fuse_conn_abort_store);
593
594static struct attribute *fuse_conn_attrs[] = {
595 &fuse_conn_waiting.attr,
596 &fuse_conn_abort.attr,
597 NULL,
598};
599
600static ssize_t fuse_conn_attr_show(struct kobject *kobj,
601 struct attribute *attr,
602 char *page)
603{
604 struct fuse_conn_attr *fca =
605 container_of(attr, struct fuse_conn_attr, attr);
606
607 if (fca->show)
608 return fca->show(get_fuse_conn_kobj(kobj), page);
609 else
610 return -EACCES;
611}
612
613static ssize_t fuse_conn_attr_store(struct kobject *kobj,
614 struct attribute *attr,
615 const char *page, size_t count)
616{
617 struct fuse_conn_attr *fca =
618 container_of(attr, struct fuse_conn_attr, attr);
619
620 if (fca->store)
621 return fca->store(get_fuse_conn_kobj(kobj), page, count);
622 else
623 return -EACCES;
624}
625
626static struct sysfs_ops fuse_conn_sysfs_ops = {
627 .show = &fuse_conn_attr_show,
628 .store = &fuse_conn_attr_store,
629};
630
631static struct kobj_type ktype_fuse_conn = {
632 .release = fuse_conn_release,
633 .sysfs_ops = &fuse_conn_sysfs_ops,
634 .default_attrs = fuse_conn_attrs,
635};
636
637static decl_subsys(fuse, NULL, NULL); 576static decl_subsys(fuse, NULL, NULL);
638static decl_subsys(connections, &ktype_fuse_conn, NULL); 577static decl_subsys(connections, NULL, NULL);
639 578
640static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep, 579static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
641 unsigned long flags) 580 unsigned long flags)
@@ -709,6 +648,7 @@ static int __init fuse_init(void)
709 printk("fuse init (API version %i.%i)\n", 648 printk("fuse init (API version %i.%i)\n",
710 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 649 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
711 650
651 INIT_LIST_HEAD(&fuse_conn_list);
712 res = fuse_fs_init(); 652 res = fuse_fs_init();
713 if (res) 653 if (res)
714 goto err; 654 goto err;
@@ -721,8 +661,14 @@ static int __init fuse_init(void)
721 if (res) 661 if (res)
722 goto err_dev_cleanup; 662 goto err_dev_cleanup;
723 663
664 res = fuse_ctl_init();
665 if (res)
666 goto err_sysfs_cleanup;
667
724 return 0; 668 return 0;
725 669
670 err_sysfs_cleanup:
671 fuse_sysfs_cleanup();
726 err_dev_cleanup: 672 err_dev_cleanup:
727 fuse_dev_cleanup(); 673 fuse_dev_cleanup();
728 err_fs_cleanup: 674 err_fs_cleanup:
@@ -735,6 +681,7 @@ static void __exit fuse_exit(void)
735{ 681{
736 printk(KERN_DEBUG "fuse exit\n"); 682 printk(KERN_DEBUG "fuse exit\n");
737 683
684 fuse_ctl_cleanup();
738 fuse_sysfs_cleanup(); 685 fuse_sysfs_cleanup();
739 fuse_fs_cleanup(); 686 fuse_fs_cleanup();
740 fuse_dev_cleanup(); 687 fuse_dev_cleanup();