From 057a28c5cccb76854b65e6e5d3c652c6a9c9dea6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 26 Apr 2006 02:39:19 -0700 Subject: [PATCH] --- yaml --- r: 26181 b: refs/heads/master c: 85ca719e5756d79ea0f10c469e3762462ac45e22 h: refs/heads/master i: 26179: 24edb2ac48e6576cd91d2ef446983f0a0e75bef2 v: v3 --- [refs] | 2 +- trunk/Documentation/filesystems/sysfs.txt | 5 --- trunk/fs/fuse/dev.c | 35 +++++++++----------- trunk/fs/fuse/fuse_i.h | 12 ++----- trunk/fs/fuse/inode.c | 40 +++++++++++++---------- trunk/net/bridge/br_forward.c | 8 ++++- 6 files changed, 48 insertions(+), 54 deletions(-) diff --git a/[refs] b/[refs] index 1594fdfd6074..d7d359ccd169 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c86d90df2676d9d212c0ab1f3c64e0abdf5b4c09 +refs/heads/master: 85ca719e5756d79ea0f10c469e3762462ac45e22 diff --git a/trunk/Documentation/filesystems/sysfs.txt b/trunk/Documentation/filesystems/sysfs.txt index 89b1d196ca80..c8bce82ddcac 100644 --- a/trunk/Documentation/filesystems/sysfs.txt +++ b/trunk/Documentation/filesystems/sysfs.txt @@ -246,7 +246,6 @@ class/ devices/ firmware/ net/ -fs/ devices/ contains a filesystem representation of the device tree. It maps directly to the internal kernel device tree, which is a hierarchy of @@ -265,10 +264,6 @@ drivers/ contains a directory for each device driver that is loaded for devices on that particular bus (this assumes that drivers do not span multiple bus types). -fs/ contains a directory for some filesystems. Currently each -filesystem wanting to export attributes must create its own hierarchy -below fs/ (see ./fuse.txt for an example). - More information can driver-model specific features can be found in Documentation/driver-model/. diff --git a/trunk/fs/fuse/dev.c b/trunk/fs/fuse/dev.c index 104a62dadb94..cc750c68fe70 100644 --- a/trunk/fs/fuse/dev.c +++ b/trunk/fs/fuse/dev.c @@ -128,24 +128,14 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) } } -/* - * Called with sbput_sem held for read (request_end) or write - * (fuse_put_super). By the time fuse_put_super() is finished, all - * inodes belonging to background requests must be released, so the - * iputs have to be done within the locked region. - */ -void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req) +void fuse_remove_background(struct fuse_conn *fc, struct fuse_req *req) { - iput(req->inode); - iput(req->inode2); - spin_lock(&fc->lock); - list_del(&req->bg_entry); + list_del_init(&req->bg_entry); if (fc->num_background == FUSE_MAX_BACKGROUND) { fc->blocked = 0; wake_up_all(&fc->blocked_waitq); } fc->num_background--; - spin_unlock(&fc->lock); } /* @@ -175,22 +165,27 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) wake_up(&req->waitq); fuse_put_request(fc, req); } else { + struct inode *inode = req->inode; + struct inode *inode2 = req->inode2; + struct file *file = req->file; void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; req->end = NULL; + req->inode = NULL; + req->inode2 = NULL; + req->file = NULL; + if (!list_empty(&req->bg_entry)) + fuse_remove_background(fc, req); spin_unlock(&fc->lock); - down_read(&fc->sbput_sem); - if (fc->mounted) - fuse_release_background(fc, req); - up_read(&fc->sbput_sem); - - /* fput must go outside sbput_sem, otherwise it can deadlock */ - if (req->file) - fput(req->file); if (end) end(fc, req); else fuse_put_request(fc, req); + + if (file) + fput(file); + iput(inode); + iput(inode2); } } diff --git a/trunk/fs/fuse/fuse_i.h b/trunk/fs/fuse/fuse_i.h index 0474202cb5dc..59661c481d9d 100644 --- a/trunk/fs/fuse/fuse_i.h +++ b/trunk/fs/fuse/fuse_i.h @@ -258,15 +258,9 @@ struct fuse_conn { /** waitq for blocked connection */ wait_queue_head_t blocked_waitq; - /** RW semaphore for exclusion with fuse_put_super() */ - struct rw_semaphore sbput_sem; - /** The next unique request id */ u64 reqctr; - /** Mount is active */ - unsigned mounted; - /** Connection established, cleared on umount, connection abort and device release */ unsigned connected; @@ -477,11 +471,11 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req); void request_send_background(struct fuse_conn *fc, struct fuse_req *req); /** - * Release inodes and file associated with background request + * Remove request from the the background list */ -void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req); +void fuse_remove_background(struct fuse_conn *fc, struct fuse_req *req); -/* Abort all requests */ +/** Abort all requests */ void fuse_abort_conn(struct fuse_conn *fc); /** diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index 7627022446b2..43a6fc0db8a7 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/fs/fuse/inode.c @@ -204,17 +204,26 @@ static void fuse_put_super(struct super_block *sb) { struct fuse_conn *fc = get_fuse_conn_super(sb); - down_write(&fc->sbput_sem); - while (!list_empty(&fc->background)) - fuse_release_background(fc, - list_entry(fc->background.next, - struct fuse_req, bg_entry)); - spin_lock(&fc->lock); - fc->mounted = 0; fc->connected = 0; + while (!list_empty(&fc->background)) { + struct fuse_req *req = list_entry(fc->background.next, + struct fuse_req, bg_entry); + struct inode *inode = req->inode; + struct inode *inode2 = req->inode2; + + /* File would hold a reference to vfsmount */ + BUG_ON(req->file); + req->inode = NULL; + req->inode2 = NULL; + fuse_remove_background(fc, req); + + spin_unlock(&fc->lock); + iput(inode); + iput(inode2); + spin_lock(&fc->lock); + } spin_unlock(&fc->lock); - up_write(&fc->sbput_sem); /* Flush all readers on this fs */ kill_fasync(&fc->fasync, SIGIO, POLL_IN); wake_up_all(&fc->waitq); @@ -386,7 +395,6 @@ static struct fuse_conn *new_conn(void) INIT_LIST_HEAD(&fc->processing); INIT_LIST_HEAD(&fc->io); INIT_LIST_HEAD(&fc->background); - init_rwsem(&fc->sbput_sem); kobj_set_kset_s(fc, connections_subsys); kobject_init(&fc->kobj); atomic_set(&fc->num_waiting, 0); @@ -500,6 +508,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) if (file->f_op != &fuse_dev_operations) return -EINVAL; + /* Setting file->private_data can't race with other mount() + instances, since BKL is held for ->get_sb() */ + if (file->private_data) + return -EINVAL; + fc = new_conn(); if (!fc) return -ENOMEM; @@ -535,14 +548,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) if (err) goto err_free_req; - /* Setting file->private_data can't race with other mount() - instances, since BKL is held for ->get_sb() */ - err = -EINVAL; - if (file->private_data) - goto err_kobject_del; - sb->s_root = root_dentry; - fc->mounted = 1; fc->connected = 1; kobject_get(&fc->kobj); file->private_data = fc; @@ -557,8 +563,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) return 0; - err_kobject_del: - kobject_del(&fc->kobj); err_free_req: fuse_request_free(init_req); err_put_root: diff --git a/trunk/net/bridge/br_forward.c b/trunk/net/bridge/br_forward.c index 2d24fb400e0c..56f3aa47e758 100644 --- a/trunk/net/bridge/br_forward.c +++ b/trunk/net/bridge/br_forward.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "br_private.h" @@ -29,10 +30,15 @@ static inline int should_deliver(const struct net_bridge_port *p, return 1; } +static inline unsigned packet_length(const struct sk_buff *skb) +{ + return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); +} + int br_dev_queue_push_xmit(struct sk_buff *skb) { /* drop mtu oversized packets except tso */ - if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size) + if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size) kfree_skb(skb); else { #ifdef CONFIG_BRIDGE_NETFILTER