aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-09-09 16:10:31 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 17:03:45 -0400
commit1e9a4ed9396e9c31139721b639550ffb1df17065 (patch)
tree213566cf1294f5dd8f6ff62ceb3557b5f5b6c59c /fs/fuse/inode.c
parentb6aeadeda22a9aa322fdfcd3f4c69ccf0da5cbdd (diff)
[PATCH] FUSE - mount options
This patch adds miscellaneous mount options to the FUSE filesystem. The following mount options are added: o default_permissions: check permissions with generic_permission() o allow_other: allow other users to access files o allow_root: allow root to access files o kernel_cache: don't invalidate page cache on open Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c77
1 files changed, 38 insertions, 39 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index f229d6962643..458c62ca0fec 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -15,7 +15,6 @@
15#include <linux/seq_file.h> 15#include <linux/seq_file.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/parser.h> 18#include <linux/parser.h>
20#include <linux/statfs.h> 19#include <linux/statfs.h>
21 20
@@ -25,11 +24,6 @@ MODULE_LICENSE("GPL");
25 24
26spinlock_t fuse_lock; 25spinlock_t fuse_lock;
27static kmem_cache_t *fuse_inode_cachep; 26static kmem_cache_t *fuse_inode_cachep;
28static int mount_count;
29
30static int mount_max = 1000;
31module_param(mount_max, int, 0644);
32MODULE_PARM_DESC(mount_max, "Maximum number of FUSE mounts allowed, if -1 then unlimited (default: 1000)");
33 27
34#define FUSE_SUPER_MAGIC 0x65735546 28#define FUSE_SUPER_MAGIC 0x65735546
35 29
@@ -37,6 +31,7 @@ struct fuse_mount_data {
37 int fd; 31 int fd;
38 unsigned rootmode; 32 unsigned rootmode;
39 unsigned user_id; 33 unsigned user_id;
34 unsigned flags;
40}; 35};
41 36
42static struct inode *fuse_alloc_inode(struct super_block *sb) 37static struct inode *fuse_alloc_inode(struct super_block *sb)
@@ -89,8 +84,8 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
89 84
90static void fuse_clear_inode(struct inode *inode) 85static void fuse_clear_inode(struct inode *inode)
91{ 86{
92 struct fuse_conn *fc = get_fuse_conn(inode); 87 if (inode->i_sb->s_flags & MS_ACTIVE) {
93 if (fc) { 88 struct fuse_conn *fc = get_fuse_conn(inode);
94 struct fuse_inode *fi = get_fuse_inode(inode); 89 struct fuse_inode *fi = get_fuse_inode(inode);
95 fuse_send_forget(fc, fi->forget_req, fi->nodeid, fi->nlookup); 90 fuse_send_forget(fc, fi->forget_req, fi->nodeid, fi->nlookup);
96 fi->forget_req = NULL; 91 fi->forget_req = NULL;
@@ -195,14 +190,19 @@ static void fuse_put_super(struct super_block *sb)
195{ 190{
196 struct fuse_conn *fc = get_fuse_conn_super(sb); 191 struct fuse_conn *fc = get_fuse_conn_super(sb);
197 192
193 down_write(&fc->sbput_sem);
194 while (!list_empty(&fc->background))
195 fuse_release_background(list_entry(fc->background.next,
196 struct fuse_req, bg_entry));
197
198 spin_lock(&fuse_lock); 198 spin_lock(&fuse_lock);
199 mount_count --; 199 fc->mounted = 0;
200 fc->sb = NULL;
201 fc->user_id = 0; 200 fc->user_id = 0;
201 fc->flags = 0;
202 /* Flush all readers on this fs */ 202 /* Flush all readers on this fs */
203 wake_up_all(&fc->waitq); 203 wake_up_all(&fc->waitq);
204 up_write(&fc->sbput_sem);
204 fuse_release_conn(fc); 205 fuse_release_conn(fc);
205 *get_fuse_conn_super_p(sb) = NULL;
206 spin_unlock(&fuse_lock); 206 spin_unlock(&fuse_lock);
207} 207}
208 208
@@ -249,7 +249,6 @@ enum {
249 OPT_USER_ID, 249 OPT_USER_ID,
250 OPT_DEFAULT_PERMISSIONS, 250 OPT_DEFAULT_PERMISSIONS,
251 OPT_ALLOW_OTHER, 251 OPT_ALLOW_OTHER,
252 OPT_ALLOW_ROOT,
253 OPT_KERNEL_CACHE, 252 OPT_KERNEL_CACHE,
254 OPT_ERR 253 OPT_ERR
255}; 254};
@@ -260,7 +259,6 @@ static match_table_t tokens = {
260 {OPT_USER_ID, "user_id=%u"}, 259 {OPT_USER_ID, "user_id=%u"},
261 {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, 260 {OPT_DEFAULT_PERMISSIONS, "default_permissions"},
262 {OPT_ALLOW_OTHER, "allow_other"}, 261 {OPT_ALLOW_OTHER, "allow_other"},
263 {OPT_ALLOW_ROOT, "allow_root"},
264 {OPT_KERNEL_CACHE, "kernel_cache"}, 262 {OPT_KERNEL_CACHE, "kernel_cache"},
265 {OPT_ERR, NULL} 263 {OPT_ERR, NULL}
266}; 264};
@@ -298,6 +296,18 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
298 d->user_id = value; 296 d->user_id = value;
299 break; 297 break;
300 298
299 case OPT_DEFAULT_PERMISSIONS:
300 d->flags |= FUSE_DEFAULT_PERMISSIONS;
301 break;
302
303 case OPT_ALLOW_OTHER:
304 d->flags |= FUSE_ALLOW_OTHER;
305 break;
306
307 case OPT_KERNEL_CACHE:
308 d->flags |= FUSE_KERNEL_CACHE;
309 break;
310
301 default: 311 default:
302 return 0; 312 return 0;
303 } 313 }
@@ -313,6 +323,12 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
313 struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb); 323 struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb);
314 324
315 seq_printf(m, ",user_id=%u", fc->user_id); 325 seq_printf(m, ",user_id=%u", fc->user_id);
326 if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
327 seq_puts(m, ",default_permissions");
328 if (fc->flags & FUSE_ALLOW_OTHER)
329 seq_puts(m, ",allow_other");
330 if (fc->flags & FUSE_KERNEL_CACHE)
331 seq_puts(m, ",kernel_cache");
316 return 0; 332 return 0;
317} 333}
318 334
@@ -330,7 +346,8 @@ static void free_conn(struct fuse_conn *fc)
330/* Must be called with the fuse lock held */ 346/* Must be called with the fuse lock held */
331void fuse_release_conn(struct fuse_conn *fc) 347void fuse_release_conn(struct fuse_conn *fc)
332{ 348{
333 if (!fc->sb && !fc->file) 349 fc->count--;
350 if (!fc->count)
334 free_conn(fc); 351 free_conn(fc);
335} 352}
336 353
@@ -342,14 +359,13 @@ static struct fuse_conn *new_conn(void)
342 if (fc != NULL) { 359 if (fc != NULL) {
343 int i; 360 int i;
344 memset(fc, 0, sizeof(*fc)); 361 memset(fc, 0, sizeof(*fc));
345 fc->sb = NULL;
346 fc->file = NULL;
347 fc->user_id = 0;
348 init_waitqueue_head(&fc->waitq); 362 init_waitqueue_head(&fc->waitq);
349 INIT_LIST_HEAD(&fc->pending); 363 INIT_LIST_HEAD(&fc->pending);
350 INIT_LIST_HEAD(&fc->processing); 364 INIT_LIST_HEAD(&fc->processing);
351 INIT_LIST_HEAD(&fc->unused_list); 365 INIT_LIST_HEAD(&fc->unused_list);
366 INIT_LIST_HEAD(&fc->background);
352 sema_init(&fc->outstanding_sem, 0); 367 sema_init(&fc->outstanding_sem, 0);
368 init_rwsem(&fc->sbput_sem);
353 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { 369 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
354 struct fuse_req *req = fuse_request_alloc(); 370 struct fuse_req *req = fuse_request_alloc();
355 if (!req) { 371 if (!req) {
@@ -380,8 +396,10 @@ static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
380 fc = ERR_PTR(-EINVAL); 396 fc = ERR_PTR(-EINVAL);
381 } else { 397 } else {
382 file->private_data = fc; 398 file->private_data = fc;
383 fc->sb = sb; 399 *get_fuse_conn_super_p(sb) = fc;
384 fc->file = file; 400 fc->mounted = 1;
401 fc->connected = 1;
402 fc->count = 2;
385 } 403 }
386 spin_unlock(&fuse_lock); 404 spin_unlock(&fuse_lock);
387 return fc; 405 return fc;
@@ -407,17 +425,6 @@ static struct super_operations fuse_super_operations = {
407 .show_options = fuse_show_options, 425 .show_options = fuse_show_options,
408}; 426};
409 427
410static int inc_mount_count(void)
411{
412 int success = 0;
413 spin_lock(&fuse_lock);
414 mount_count ++;
415 if (mount_max == -1 || mount_count <= mount_max)
416 success = 1;
417 spin_unlock(&fuse_lock);
418 return success;
419}
420
421static int fuse_fill_super(struct super_block *sb, void *data, int silent) 428static int fuse_fill_super(struct super_block *sb, void *data, int silent)
422{ 429{
423 struct fuse_conn *fc; 430 struct fuse_conn *fc;
@@ -444,14 +451,9 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
444 if (IS_ERR(fc)) 451 if (IS_ERR(fc))
445 return PTR_ERR(fc); 452 return PTR_ERR(fc);
446 453
454 fc->flags = d.flags;
447 fc->user_id = d.user_id; 455 fc->user_id = d.user_id;
448 456
449 *get_fuse_conn_super_p(sb) = fc;
450
451 err = -ENFILE;
452 if (!inc_mount_count() && current->uid != 0)
453 goto err;
454
455 err = -ENOMEM; 457 err = -ENOMEM;
456 root = get_root_inode(sb, d.rootmode); 458 root = get_root_inode(sb, d.rootmode);
457 if (root == NULL) 459 if (root == NULL)
@@ -467,11 +469,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
467 469
468 err: 470 err:
469 spin_lock(&fuse_lock); 471 spin_lock(&fuse_lock);
470 mount_count --;
471 fc->sb = NULL;
472 fuse_release_conn(fc); 472 fuse_release_conn(fc);
473 spin_unlock(&fuse_lock); 473 spin_unlock(&fuse_lock);
474 *get_fuse_conn_super_p(sb) = NULL;
475 return err; 474 return err;
476} 475}
477 476