diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2005-04-22 12:04:55 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2005-04-22 12:04:55 +0000 |
commit | 0111f9dbe43a8c4ae516d3eb470186770894c5bf (patch) | |
tree | 6112c59cbfcebc262d88ae10d1e06d92e0fcd142 /kernel | |
parent | d001bf9915e651dd301c29aafe0b7e777a1ae7cf (diff) | |
download | libfuse-0111f9dbe43a8c4ae516d3eb470186770894c5bf.tar.gz |
fix
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/dev.c | 14 | ||||
-rw-r--r-- | kernel/dir.c | 7 | ||||
-rw-r--r-- | kernel/fuse_i.h | 17 | ||||
-rw-r--r-- | kernel/inode.c | 32 |
4 files changed, 26 insertions, 44 deletions
diff --git a/kernel/dev.c b/kernel/dev.c index 29a9b63..d64423e 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -24,7 +24,7 @@ static inline struct fuse_conn *fuse_get_conn(struct file *file) struct fuse_conn *fc; spin_lock(&fuse_lock); fc = file->private_data; - if (fc && !fc->sb) + if (fc && !fc->mounted) fc = NULL; spin_unlock(&fuse_lock); return fc; @@ -214,7 +214,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) spin_unlock(&fuse_lock); if (req->background) { down_read(&fc->sbput_sem); - if (fc->sb) + if (fc->mounted) fuse_release_background(req); up_read(&fc->sbput_sem); } @@ -371,7 +371,7 @@ static void request_send_wait(struct fuse_conn *fc, struct fuse_req *req, { req->isreply = 1; spin_lock(&fuse_lock); - if (!fc->file) + if (!fc->connected) req->out.h.error = -ENOTCONN; else if (fc->conn_error) req->out.h.error = -ECONNREFUSED; @@ -404,7 +404,7 @@ void request_send_nonint(struct fuse_conn *fc, struct fuse_req *req) static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) { spin_lock(&fuse_lock); - if (fc->file) { + if (fc->connected) { queue_request(fc, req); spin_unlock(&fuse_lock); } else { @@ -659,7 +659,7 @@ static void request_wait(struct fuse_conn *fc) DECLARE_WAITQUEUE(wait, current); add_wait_queue_exclusive(&fc->waitq, &wait); - while (fc->sb && list_empty(&fc->pending)) { + while (fc->mounted && list_empty(&fc->pending)) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) break; @@ -709,7 +709,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, goto err_unlock; request_wait(fc); err = -ENODEV; - if (!fc->sb) + if (!fc->mounted) goto err_unlock; err = -ERESTARTSYS; if (list_empty(&fc->pending)) @@ -917,7 +917,7 @@ static int fuse_dev_release(struct inode *inode, struct file *file) spin_lock(&fuse_lock); fc = file->private_data; if (fc) { - fc->file = NULL; + fc->connected = 0; end_requests(fc, &fc->pending); end_requests(fc, &fc->processing); fuse_release_conn(fc); diff --git a/kernel/dir.c b/kernel/dir.c index 6ae498c..947d538 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -441,9 +441,7 @@ static int fuse_revalidate(struct dentry *entry) if (get_node_id(inode) == FUSE_ROOT_ID) { if (!(fc->flags & FUSE_ALLOW_OTHER) && - current->fsuid != fc->user_id && - (!(fc->flags & FUSE_ALLOW_ROOT) || - !capable(CAP_DAC_OVERRIDE))) + current->fsuid != fc->user_id) return -EACCES; } else if (time_before_eq(jiffies, fi->i_time)) return 0; @@ -455,8 +453,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) { struct fuse_conn *fc = get_fuse_conn(inode); - if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->user_id && - (!(fc->flags & FUSE_ALLOW_ROOT) || !capable(CAP_DAC_OVERRIDE))) + if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->user_id) return -EACCES; else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { #ifdef KERNEL_2_6_10_PLUS diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index 373f36d..164eaa7 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -101,10 +101,6 @@ static inline void set_page_dirty_lock(struct page *page) /** Bypass the page cache for read and write operations */ #define FUSE_DIRECT_IO (1 << 3) -/** Allow root and setuid-root programs to access fuse-mounted - filesystems */ -#define FUSE_ALLOW_ROOT (1 << 4) - /** FUSE inode */ struct fuse_inode { /** Inode data */ @@ -260,11 +256,8 @@ struct fuse_req { * unmounted. */ struct fuse_conn { - /** The superblock of the mounted filesystem */ - struct super_block *sb; - - /** The opened client device */ - struct file *file; + /** Reference count */ + int count; /** The user id for this mount */ uid_t user_id; @@ -307,6 +300,12 @@ struct fuse_conn { /** The next unique request id */ int reqctr; + /** Mount is active */ + unsigned mounted : 1; + + /** Connection established */ + unsigned connected : 1; + /** Connection failed (version mismatch) */ unsigned conn_error : 1; diff --git a/kernel/inode.c b/kernel/inode.c index 1feaba9..9b894f5 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -99,8 +99,8 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, static void fuse_clear_inode(struct inode *inode) { - struct fuse_conn *fc = get_fuse_conn(inode); - if (fc && (inode->i_sb->s_flags & MS_ACTIVE)) { + if (inode->i_sb->s_flags & MS_ACTIVE) { + struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_inode *fi = get_fuse_inode(inode); fuse_send_forget(fc, fi->forget_req, fi->nodeid, inode->i_version); fi->forget_req = NULL; @@ -260,14 +260,13 @@ static void fuse_put_super(struct super_block *sb) struct fuse_req, bg_entry)); spin_lock(&fuse_lock); - fc->sb = NULL; + fc->mounted = 0; fc->user_id = 0; fc->flags = 0; /* Flush all readers on this fs */ wake_up_all(&fc->waitq); up_write(&fc->sbput_sem); fuse_release_conn(fc); - *get_fuse_conn_super_p(sb) = NULL; spin_unlock(&fuse_lock); } @@ -314,7 +313,6 @@ enum { OPT_USER_ID, OPT_DEFAULT_PERMISSIONS, OPT_ALLOW_OTHER, - OPT_ALLOW_ROOT, OPT_KERNEL_CACHE, #ifndef KERNEL_2_6 OPT_LARGE_READ, @@ -330,7 +328,6 @@ static match_table_t tokens = { {OPT_USER_ID, "user_id=%u"}, {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, {OPT_ALLOW_OTHER, "allow_other"}, - {OPT_ALLOW_ROOT, "allow_root"}, {OPT_KERNEL_CACHE, "kernel_cache"}, #ifndef KERNEL_2_6 {OPT_LARGE_READ, "large_read"}, @@ -382,10 +379,6 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d) d->flags |= FUSE_ALLOW_OTHER; break; - case OPT_ALLOW_ROOT: - d->flags |= FUSE_ALLOW_ROOT; - break; - case OPT_KERNEL_CACHE: d->flags |= FUSE_KERNEL_CACHE; break; @@ -424,8 +417,6 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) seq_puts(m, ",default_permissions"); if (fc->flags & FUSE_ALLOW_OTHER) seq_puts(m, ",allow_other"); - if (fc->flags & FUSE_ALLOW_ROOT) - seq_puts(m, ",allow_root"); if (fc->flags & FUSE_KERNEL_CACHE) seq_puts(m, ",kernel_cache"); #ifndef KERNEL_2_6 @@ -453,7 +444,8 @@ static void free_conn(struct fuse_conn *fc) /* Must be called with the fuse lock held */ void fuse_release_conn(struct fuse_conn *fc) { - if (!fc->sb && !fc->file) + fc->count--; + if (!fc->count) free_conn(fc); } @@ -465,10 +457,6 @@ static struct fuse_conn *new_conn(void) if (fc != NULL) { int i; memset(fc, 0, sizeof(*fc)); - fc->sb = NULL; - fc->file = NULL; - fc->flags = 0; - fc->user_id = 0; init_waitqueue_head(&fc->waitq); INIT_LIST_HEAD(&fc->pending); INIT_LIST_HEAD(&fc->processing); @@ -508,8 +496,10 @@ static struct fuse_conn *get_conn(struct file *file, struct super_block *sb) fc = ERR_PTR(-EINVAL); } else { file->private_data = fc; - fc->sb = sb; - fc->file = file; + *get_fuse_conn_super_p(sb) = fc; + fc->mounted = 1; + fc->connected = 1; + fc->count = 2; } spin_unlock(&fuse_lock); return fc; @@ -636,8 +626,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) #endif fc->max_write = FUSE_MAX_IN / 2; - *get_fuse_conn_super_p(sb) = fc; - err = -ENOMEM; root = get_root_inode(sb, d.rootmode); if (root == NULL) @@ -653,10 +641,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) err: spin_lock(&fuse_lock); - fc->sb = NULL; fuse_release_conn(fc); spin_unlock(&fuse_lock); - *get_fuse_conn_super_p(sb) = NULL; return err; } |