aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/fcall.c21
-rw-r--r--fs/9p/mux.c222
-rw-r--r--fs/9p/mux.h4
-rw-r--r--fs/9p/vfs_file.c13
-rw-r--r--fs/9p/vfs_inode.c19
-rw-r--r--fs/Makefile2
-rw-r--r--fs/autofs4/autofs_i.h5
-rw-r--r--fs/autofs4/root.c10
-rw-r--r--fs/autofs4/waitq.c77
-rw-r--r--fs/binfmt_flat.c30
-rw-r--r--fs/bio.c3
-rw-r--r--fs/compat.c177
-rw-r--r--fs/configfs/dir.c137
-rw-r--r--fs/exportfs/expfs.c2
-rw-r--r--fs/inotify.c9
-rw-r--r--fs/jffs2/nodelist.c6
-rw-r--r--fs/jfs/jfs_metapage.c20
-rw-r--r--fs/namespace.c7
-rw-r--r--fs/nfsd/export.c4
-rw-r--r--fs/nfsd/vfs.c7
-rw-r--r--fs/ocfs2/aops.c46
-rw-r--r--fs/ocfs2/aops.h4
-rw-r--r--fs/ocfs2/extent_map.c6
-rw-r--r--fs/ocfs2/file.c86
-rw-r--r--fs/ocfs2/journal.c8
-rw-r--r--fs/ocfs2/uptodate.c4
-rw-r--r--fs/ocfs2/vote.c6
-rw-r--r--fs/open.c1
-rw-r--r--fs/partitions/check.c3
-rw-r--r--fs/smbfs/dir.c5
-rw-r--r--fs/smbfs/request.c4
31 files changed, 576 insertions, 372 deletions
diff --git a/fs/9p/fcall.c b/fs/9p/fcall.c
index 71742ba150c..6f2617820a4 100644
--- a/fs/9p/fcall.c
+++ b/fs/9p/fcall.c
@@ -98,23 +98,20 @@ v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
struct v9fs_fcall *rc, int err)
{
- int fid;
+ int fid, id;
struct v9fs_session_info *v9ses;
- if (err)
- return;
-
+ id = 0;
fid = tc->params.tclunk.fid;
- kfree(tc);
-
- if (!rc)
- return;
-
- v9ses = a;
- if (rc->id == RCLUNK)
- v9fs_put_idpool(fid, &v9ses->fidpool);
+ if (rc)
+ id = rc->id;
+ kfree(tc);
kfree(rc);
+ if (id == RCLUNK) {
+ v9ses = a;
+ v9fs_put_idpool(fid, &v9ses->fidpool);
+ }
}
/**
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 3e5b124a721..f4407eb276c 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -50,15 +50,23 @@ enum {
Wpending = 8, /* can write */
};
+enum {
+ None,
+ Flushing,
+ Flushed,
+};
+
struct v9fs_mux_poll_task;
struct v9fs_req {
+ spinlock_t lock;
int tag;
struct v9fs_fcall *tcall;
struct v9fs_fcall *rcall;
int err;
v9fs_mux_req_callback cb;
void *cba;
+ int flush;
struct list_head req_list;
};
@@ -96,8 +104,8 @@ struct v9fs_mux_poll_task {
struct v9fs_mux_rpc {
struct v9fs_mux_data *m;
- struct v9fs_req *req;
int err;
+ struct v9fs_fcall *tcall;
struct v9fs_fcall *rcall;
wait_queue_head_t wqueue;
};
@@ -524,10 +532,9 @@ again:
static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
{
- int ecode, tag;
+ int ecode;
struct v9fs_str *ename;
- tag = req->tag;
if (!req->err && req->rcall->id == RERROR) {
ecode = req->rcall->params.rerror.errno;
ename = &req->rcall->params.rerror.error;
@@ -553,23 +560,6 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
if (!req->err)
req->err = -EIO;
}
-
- if (req->err == ERREQFLUSH)
- return;
-
- if (req->cb) {
- dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n",
- req->tcall, req->rcall);
-
- (*req->cb) (req->cba, req->tcall, req->rcall, req->err);
- req->cb = NULL;
- } else
- kfree(req->rcall);
-
- v9fs_mux_put_tag(m, tag);
-
- wake_up(&m->equeue);
- kfree(req);
}
/**
@@ -669,17 +659,26 @@ static void v9fs_read_work(void *a)
list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
if (rreq->tag == rcall->tag) {
req = rreq;
- req->rcall = rcall;
- list_del(&req->req_list);
- spin_unlock(&m->lock);
- process_request(m, req);
+ if (req->flush != Flushing)
+ list_del(&req->req_list);
break;
}
-
}
+ spin_unlock(&m->lock);
- if (!req) {
- spin_unlock(&m->lock);
+ if (req) {
+ req->rcall = rcall;
+ process_request(m, req);
+
+ if (req->flush != Flushing) {
+ if (req->cb)
+ (*req->cb) (req, req->cba);
+ else
+ kfree(req->rcall);
+
+ wake_up(&m->equeue);
+ }
+ } else {
if (err >= 0 && rcall->id != RFLUSH)
dprintk(DEBUG_ERROR,
"unexpected response mux %p id %d tag %d\n",
@@ -746,7 +745,6 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
return ERR_PTR(-ENOMEM);
v9fs_set_tag(tc, n);
-
if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
char buf[150];
@@ -754,12 +752,14 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
printk(KERN_NOTICE "<<< %p %s\n", m, buf);
}
+ spin_lock_init(&req->lock);
req->tag = n;
req->tcall = tc;
req->rcall = NULL;
req->err = 0;
req->cb = cb;
req->cba = cba;
+ req->flush = None;
spin_lock(&m->lock);
list_add_tail(&req->req_list, &m->unsent_req_list);
@@ -776,72 +776,108 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
return req;
}
-static void v9fs_mux_flush_cb(void *a, struct v9fs_fcall *tc,
- struct v9fs_fcall *rc, int err)
+static void v9fs_mux_free_request(struct v9fs_mux_data *m, struct v9fs_req *req)
+{
+ v9fs_mux_put_tag(m, req->tag);
+ kfree(req);
+}
+
+static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a)
{
v9fs_mux_req_callback cb;
int tag;
struct v9fs_mux_data *m;
- struct v9fs_req *req, *rptr;
+ struct v9fs_req *req, *rreq, *rptr;
m = a;
- dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, tc,
- rc, err, tc->params.tflush.oldtag);
+ dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
+ freq->tcall, freq->rcall, freq->err,
+ freq->tcall->params.tflush.oldtag);
spin_lock(&m->lock);
cb = NULL;
- tag = tc->params.tflush.oldtag;
- list_for_each_entry_safe(req, rptr, &m->req_list, req_list) {
- if (req->tag == tag) {
+ tag = freq->tcall->params.tflush.oldtag;
+ req = NULL;
+ list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
+ if (rreq->tag == tag) {
+ req = rreq;
list_del(&req->req_list);
- if (req->cb) {
- cb = req->cb;
- req->cb = NULL;
- spin_unlock(&m->lock);
- (*cb) (req->cba, req->tcall, req->rcall,
- req->err);
- }
- kfree(req);
- wake_up(&m->equeue);
break;
}
}
+ spin_unlock(&m->lock);
- if (!cb)
- spin_unlock(&m->lock);
+ if (req) {
+ spin_lock(&req->lock);
+ req->flush = Flushed;
+ spin_unlock(&req->lock);
+
+ if (req->cb)
+ (*req->cb) (req, req->cba);
+ else
+ kfree(req->rcall);
+
+ wake_up(&m->equeue);
+ }
- v9fs_mux_put_tag(m, tag);
- kfree(tc);
- kfree(rc);
+ kfree(freq->tcall);
+ kfree(freq->rcall);
+ v9fs_mux_free_request(m, freq);
}
-static void
+static int
v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
{
struct v9fs_fcall *fc;
+ struct v9fs_req *rreq, *rptr;
dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
+ /* if a response was received for a request, do nothing */
+ spin_lock(&req->lock);
+ if (req->rcall || req->err) {
+ spin_unlock(&req->lock);
+ dprintk(DEBUG_MUX, "mux %p req %p response already received\n", m, req);
+ return 0;
+ }
+
+ req->flush = Flushing;
+ spin_unlock(&req->lock);
+
+ spin_lock(&m->lock);
+ /* if the request is not sent yet, just remove it from the list */
+ list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
+ if (rreq->tag == req->tag) {
+ dprintk(DEBUG_MUX, "mux %p req %p request is not sent yet\n", m, req);
+ list_del(&rreq->req_list);
+ req->flush = Flushed;
+ spin_unlock(&m->lock);
+ if (req->cb)
+ (*req->cb) (req, req->cba);
+ return 0;
+ }
+ }
+ spin_unlock(&m->lock);
+
+ clear_thread_flag(TIF_SIGPENDING);
fc = v9fs_create_tflush(req->tag);
v9fs_send_request(m, fc, v9fs_mux_flush_cb, m);
+ return 1;
}
static void
-v9fs_mux_rpc_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, int err)
+v9fs_mux_rpc_cb(struct v9fs_req *req, void *a)
{
struct v9fs_mux_rpc *r;
- if (err == ERREQFLUSH) {
- kfree(rc);
- dprintk(DEBUG_MUX, "err req flush\n");
- return;
- }
-
+ dprintk(DEBUG_MUX, "req %p r %p\n", req, a);
r = a;
- dprintk(DEBUG_MUX, "mux %p req %p tc %p rc %p err %d\n", r->m, r->req,
- tc, rc, err);
- r->rcall = rc;
- r->err = err;
+ r->rcall = req->rcall;
+ r->err = req->err;
+
+ if (req->flush!=None && !req->err)
+ r->err = -ERESTARTSYS;
+
wake_up(&r->wqueue);
}
@@ -856,12 +892,13 @@ int
v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
struct v9fs_fcall **rc)
{
- int err;
+ int err, sigpending;
unsigned long flags;
struct v9fs_req *req;
struct v9fs_mux_rpc r;
r.err = 0;
+ r.tcall = tc;
r.rcall = NULL;
r.m = m;
init_waitqueue_head(&r.wqueue);
@@ -869,48 +906,50 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
if (rc)
*rc = NULL;
+ sigpending = 0;
+ if (signal_pending(current)) {
+ sigpending = 1;
+ clear_thread_flag(TIF_SIGPENDING);
+ }
+
req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r);
if (IS_ERR(req)) {
err = PTR_ERR(req);
dprintk(DEBUG_MUX, "error %d\n", err);
- return PTR_ERR(req);
+ return err;
}
- r.req = req;
- dprintk(DEBUG_MUX, "mux %p tc %p tag %d rpc %p req %p\n", m, tc,
- req->tag, &r, req);
err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0);
if (r.err < 0)
err = r.err;
if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) {
- spin_lock(&m->lock);
- req->tcall = NULL;
- req->err = ERREQFLUSH;
- spin_unlock(&m->lock);
+ if (v9fs_mux_flush_request(m, req)) {
+ /* wait until we get response of the flush message */
+ do {
+ clear_thread_flag(TIF_SIGPENDING);
+ err = wait_event_interruptible(r.wqueue,
+ r.rcall || r.err);
+ } while (!r.rcall && !r.err && err==-ERESTARTSYS &&
+ m->trans->status==Connected && !m->err);
+ }
+ sigpending = 1;
+ }
- clear_thread_flag(TIF_SIGPENDING);
- v9fs_mux_flush_request(m, req);
+ if (sigpending) {
spin_lock_irqsave(&current->sighand->siglock, flags);
recalc_sigpending();
spin_unlock_irqrestore(&current->sighand->siglock, flags);
}
- if (!err) {
- if (r.rcall)
- dprintk(DEBUG_MUX, "got response id %d tag %d\n",
- r.rcall->id, r.rcall->tag);
-
- if (rc)
- *rc = r.rcall;
- else
- kfree(r.rcall);
- } else {
+ if (rc)
+ *rc = r.rcall;
+ else
kfree(r.rcall);
- dprintk(DEBUG_MUX, "got error %d\n", err);
- if (err > 0)
- err = -EIO;
- }
+
+ v9fs_mux_free_request(m, req);
+ if (err > 0)
+ err = -EIO;
return err;
}
@@ -951,12 +990,15 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
struct v9fs_req *req, *rtmp;
LIST_HEAD(cancel_list);
- dprintk(DEBUG_MUX, "mux %p err %d\n", m, err);
+ dprintk(DEBUG_ERROR, "mux %p err %d\n", m, err);
m->err = err;
spin_lock(&m->lock);
list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
list_move(&req->req_list, &cancel_list);
}
+ list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
+ list_move(&req->req_list, &cancel_list);
+ }
spin_unlock(&m->lock);
list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
@@ -965,11 +1007,9 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
req->err = err;
if (req->cb)
- (*req->cb) (req->cba, req->tcall, req->rcall, req->err);
+ (*req->cb) (req, req->cba);
else
kfree(req->rcall);
-
- kfree(req);
}
wake_up(&m->equeue);
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
index e90bfd32ea4..fb10c50186a 100644
--- a/fs/9p/mux.h
+++ b/fs/9p/mux.h
@@ -24,6 +24,7 @@
*/
struct v9fs_mux_data;
+struct v9fs_req;
/**
* v9fs_mux_req_callback - callback function that is called when the
@@ -36,8 +37,7 @@ struct v9fs_mux_data;
* @rc - response call
* @err - error code (non-zero if error occured)
*/
-typedef void (*v9fs_mux_req_callback)(void *a, struct v9fs_fcall *tc,
- struct v9fs_fcall *rc, int err);
+typedef void (*v9fs_mux_req_callback)(struct v9fs_req *req, void *a);
int v9fs_mux_global_init(void);
void v9fs_mux_global_exit(void);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 083dcfcd158..1a8e46084f0 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -72,11 +72,17 @@ int v9fs_file_open(struct inode *inode, struct file *file)
return -ENOSPC;
}
- err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL);
+ err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, &fcall);
if (err < 0) {
dprintk(DEBUG_ERROR, "rewalk didn't work\n");
- goto put_fid;
+ if (fcall && fcall->id == RWALK)
+ goto clunk_fid;
+ else {
+ v9fs_put_idpool(fid, &v9ses->fidpool);
+ goto free_fcall;
+ }
}
+ kfree(fcall);
/* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
/* translate open mode appropriately */
@@ -109,8 +115,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
clunk_fid:
v9fs_t_clunk(v9ses, fid);
-put_fid:
- v9fs_put_idpool(fid, &v9ses->fidpool);
+free_fcall:
kfree(fcall);
return err;
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 133db366d30..2cb87ba4b1c 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -270,7 +270,10 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("clone error", fcall);
- goto put_fid;
+ if (fcall && fcall->id == RWALK)
+ goto clunk_fid;
+ else
+ goto put_fid;
}
kfree(fcall);
@@ -322,6 +325,9 @@ v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
&fcall);
if (err < 0) {
+ if (fcall && fcall->id == RWALK)
+ goto clunk_fid;
+
PRINT_FCALL_ERROR("walk error", fcall);
v9fs_put_idpool(nfid, &v9ses->fidpool);
goto error;
@@ -640,19 +646,26 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
}
result = v9fs_t_walk(v9ses, dirfidnum, newfid,
- (char *)dentry->d_name.name, NULL);
+ (char *)dentry->d_name.name, &fcall);
+
if (result < 0) {
- v9fs_put_idpool(newfid, &v9ses->fidpool);
+ if (fcall && fcall->id == RWALK)
+ v9fs_t_clunk(v9ses, newfid);
+ else
+ v9fs_put_idpool(newfid, &v9ses->fidpool);
+
if (result == -ENOENT) {
d_add(dentry, NULL);
dprintk(DEBUG_VFS,
"Return negative dentry %p count %d\n",
dentry, atomic_read(&dentry->d_count));
+ kfree(fcall);
return NULL;
}
dprintk(DEBUG_ERROR, "walk error:%d\n", result);
goto FreeFcall;
}
+ kfree(fcall);
result = v9fs_t_stat(v9ses, newfid, &fcall);
if (result < 0) {
diff --git a/fs/Makefile b/fs/Makefile
index 2c22e282c77..c731d2c0f40 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_DNOTIFY) += dnotify.o
obj-$(CONFIG_PROC_FS) += proc/
obj-y += partitions/
obj-$(CONFIG_SYSFS) += sysfs/
+obj-$(CONFIG_CONFIGFS_FS) += configfs/
obj-y += devpts/
obj-$(CONFIG_PROFILING) += dcookies.o
@@ -101,6 +102,5 @@ obj-$(CONFIG_BEFS_FS) += befs/
obj-$(CONFIG_HOSTFS) += hostfs/
obj-$(CONFIG_HPPFS) += hppfs/
obj-$(CONFIG_DEBUG_FS) += debugfs/
-obj-$(CONFIG_CONFIGFS_FS) += configfs/
obj-$(CONFIG_OCFS2_FS) += ocfs2/
obj-$(CONFIG_GFS2_FS) += gfs2/
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 57c4903614e..d6603d02304 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -74,8 +74,8 @@ struct autofs_wait_queue {
struct autofs_wait_queue *next;
autofs_wqt_t wait_queue_token;
/* We use the following to see what we are waiting for */
- int hash;
- int len;
+ unsigned int hash;
+ unsigned int len;
char *name;
u32 dev;
u64 ino;
@@ -85,7 +85,6 @@ struct autofs_wait_queue {
pid_t tgid;
/* This is for status reporting upon return */
int status;
- atomic_t notify;
atomic_t wait_ctr;
};
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 84e030c8ddd..5100f984783 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -327,6 +327,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct autofs_info *ino = autofs4_dentry_ino(dentry);
int oz_mode = autofs4_oz_mode(sbi);
unsigned int lookup_type;
int status;
@@ -340,13 +341,8 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
if (oz_mode || !lookup_type)
goto done;
- /*
- * If a request is pending wait for it.
- * If it's a mount then it won't be expired till at least
- * a liitle later and if it's an expire then we might need
- * to mount it again.
- */
- if (autofs4_ispending(dentry)) {
+ /* If an expire request is pending wait for it. */
+ if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
DPRINTK("waiting for active request %p name=%.*s",
dentry, dentry->d_name.len, dentry->d_name.name);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 142ab6aa2aa..ce103e7b0bc 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -189,14 +189,30 @@ static int autofs4_getpath(struct autofs_sb_info *sbi,
return len;
}
+static struct autofs_wait_queue *
+autofs4_find_wait(struct autofs_sb_info *sbi,
+ char *name, unsigned int hash, unsigned int len)
+{
+ struct autofs_wait_queue *wq;
+
+ for (wq = sbi->queues; wq; wq = wq->next) {
+ if (wq->hash == hash &&
+ wq->len == len &&
+ wq->name && !memcmp(wq->name, name, len))
+ break;
+ }
+ return wq;
+}
+
int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
enum autofs_notify notify)
{
+ struct autofs_info *ino;
struct autofs_wait_queue *wq;
char *name;
unsigned int len = 0;
unsigned int hash = 0;
- int status;
+ int status, type;
/* In catatonic mode, we don't wait for nobody */
if (sbi->catatonic)
@@ -223,21 +239,41 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
return -EINTR;
}
- for (wq = sbi->queues ; wq ; wq = wq->next) {
- if (wq->hash == dentry->d_name.hash &&
- wq->len == len &&
- wq->name && !memcmp(wq->name, name, len))
- break;
- }
+ wq = autofs4_find_wait(sbi, name, hash, len);
+ ino = autofs4_dentry_ino(dentry);
+ if (!wq && ino && notify == NFY_NONE) {
+ /*
+ * Either we've betean the pending expire to post it's
+ * wait or it finished while we waited on the mutex.
+ * So we need to wait till either, the wait appears
+ * or the expire finishes.
+ */
+
+ while (ino->flags & AUTOFS_INF_EXPIRING) {
+ mutex_unlock(&sbi->wq_mutex);
+ schedule_timeout_interruptible(HZ/10);
+ if (mutex_lock_interruptible(&sbi->wq_mutex)) {
+ kfree(name);
+ return -EINTR;
+ }
+ wq = autofs4_find_wait(sbi, name, hash, len);
+ if (wq)
+ break;
+ }
- if (!wq) {
- /* Can't wait for an expire if there's no mount */
- if (notify == NFY_NONE && !d_mountpoint(dentry)) {
+ /*
+ * Not ideal but the status has already gone. Of the two
+ * cases where we wait on NFY_NONE neither depend on the
+ * return status of the wait.
+ */
+ if (!wq) {
kfree(name);
mutex_unlock(&sbi->wq_mutex);
- return -ENOENT;
+ return 0;
}
+ }
+ if (!wq) {
/* Create a new wait queue */
wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
if (!wq) {
@@ -263,20 +299,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
wq->tgid = current->tgid;
wq->status = -EINTR; /* Status return if interrupted */
atomic_set(&wq->wait_ctr, 2);
- atomic_set(&wq->notify, 1);
- mutex_unlock(&sbi->wq_mutex);
- } else {
- atomic_inc(&wq->wait_ctr);
mutex_unlock(&sbi->wq_mutex);
- kfree(name);
- DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
- (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
- }
-
- if (notify != NFY_NONE && atomic_read(&wq->notify)) {
- int type;
-
- atomic_dec(&wq->notify);
if (sbi->version < 5) {
if (notify == NFY_MOUNT)
@@ -299,6 +322,12 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
/* autofs4_notify_daemon() may block */
autofs4_notify_daemon(sbi, wq, type);
+ } else {
+ atomic_inc(&wq->wait_ctr);
+ mutex_unlock(&sbi->wq_mutex);
+ kfree(name);
+ DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
+ (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
}
/* wq->name is NULL if and only if the lock is already released */
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 69f44dcdb0b..b1c902e319c 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -428,7 +428,6 @@ static int load_flat_file(struct linux_binprm * bprm,
loff_t fpos;
unsigned long start_code, end_code;
int ret;
- int exec_fileno;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
inode = bprm->file->f_dentry->d_inode;
@@ -502,21 +501,12 @@ static int load_flat_file(struct linux_binprm * bprm,
goto err;
}
- /* check file descriptor */
- exec_fileno = get_unused_fd();
- if (exec_fileno < 0) {
- ret = -EMFILE;
- goto err;
- }
- get_file(bprm->file);
- fd_install(exec_fileno, bprm->file);
-
/* Flush all traces of the currently running executable */
if (id == 0) {
result = flush_old_exec(bprm);
if (result) {
ret = result;
- goto err_close;
+ goto err;
}
/* OK, This is the point of no return */
@@ -548,7 +538,7 @@ static int load_flat_file(struct linux_binprm * bprm,
textpos = (unsigned long) -ENOMEM;
printk("Unable to mmap process text, errno %d\n", (int)-textpos);
ret = textpos;
- goto err_close;
+ goto err;
}
down_write(&current->mm->mmap_sem);
@@ -564,7 +554,7 @@ static int load_flat_file(struct linux_binprm * bprm,
(int)-datapos);
do_munmap(current->mm, textpos, text_len);
ret = realdatastart;
- goto err_close;
+ goto err;
}
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
@@ -587,7 +577,7 @@ static int load_flat_file(struct linux_binprm * bprm,
do_munmap(current->mm, textpos, text_len);
do_munmap(current->mm, realdatastart, data_len + extra);
ret = result;
- goto err_close;
+ goto err;
}
reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
@@ -606,7 +596,7 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("Unable to allocate RAM for process text/data, errno %d\n",
(int)-textpos);
ret = textpos;
- goto err_close;
+ goto err;
}
realdatastart = textpos + ntohl(hdr->data_start);
@@ -652,7 +642,7 @@ static int load_flat_file(struct linux_binprm * bprm,
do_munmap(current->mm, textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long));
ret = result;
- goto err_close;
+ goto err;
}
}
@@ -717,7 +707,7 @@ static int load_flat_file(struct linux_binprm * bprm,
addr = calc_reloc(*rp, libinfo, id, 0);
if (addr == RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
*rp = addr;
}
@@ -747,7 +737,7 @@ static int load_flat_file(struct linux_binprm * bprm,
rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
if (rp == (unsigned long *)RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
/* Get the pointer's value. */
@@ -762,7 +752,7 @@ static int load_flat_file(struct linux_binprm * bprm,
addr = calc_reloc(addr, libinfo, id, 0);
if (addr == RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
/* Write back the relocated pointer. */
@@ -783,8 +773,6 @@ static int load_flat_file(struct linux_binprm * bprm,
stack_len);
return 0;
-err_close:
- sys_close(exec_fileno);
err:
return ret;
}
diff --git a/fs/bio.c b/fs/bio.c
index eb8fbc53f2c..098c12b2d60 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1116,6 +1116,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
bp->bio1.bi_io_vec = &bp->bv1;
bp->bio2.bi_io_vec = &bp->bv2;
+ bp->bio1.bi_max_vecs = 1;
+ bp->bio2.bi_max_vecs = 1;
+
bp->bio1.bi_end_io = bio_pair_end_1;
bp->bio2.bi_end_io = bio_pair_end_2;
diff --git a/fs/compat.c b/fs/compat.c
index 970888aad84..b1f64786a61 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1913,7 +1913,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
}
if (sigmask) {
- if (sigsetsize |= sizeof(compat_sigset_t))
+ if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL;
if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
return -EFAULT;
@@ -2030,109 +2030,115 @@ union compat_nfsctl_res {
struct knfsd_fh cr32_getfs;
};
-static int compat_nfs_svc_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
+static int compat_nfs_svc_trans(struct nfsctl_arg *karg,
+ struct compat_nfsctl_arg __user *arg)
{
- int err;
-
- err = access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc));
- err |= get_user(karg->ca_version, &arg->ca32_version);
- err |= __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port);
- err |= __get_user(karg->ca_svc.svc_nthreads, &arg->ca32_svc.svc32_nthreads);
- return (err) ? -EFAULT : 0;
+ if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) ||
+ get_user(karg->ca_version, &arg->ca32_version) ||
+ __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) ||
+ __get_user(karg->ca_svc.svc_nthreads,
+ &arg->ca32_svc.svc32_nthreads))
+ return -EFAULT;
+ return 0;
}
-static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
-{
- int err;
-
- err = access_ok(VERIFY_READ, &arg->ca32_client, sizeof(arg->ca32_client));
- err |= get_user(karg->ca_version, &arg->ca32_version);
- err |= __copy_from_user(&karg->ca_client.cl_ident[0],
- &arg->ca32_client.cl32_ident[0],
- NFSCLNT_IDMAX);
- err |= __get_user(karg->ca_client.cl_naddr, &arg->ca32_client.cl32_naddr);
- err |= __copy_from_user(&karg->ca_client.cl_addrlist[0],
- &arg->ca32_client.cl32_addrlist[0],
- (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
- err |= __get_user(karg->ca_client.cl_fhkeytype,
- &arg->ca32_client.cl32_fhkeytype);
- err |= __get_user(karg->ca_client.cl_fhkeylen,
- &arg->ca32_client.cl32_fhkeylen);
- err |= __copy_from_user(&karg->ca_client.cl_fhkey[0],
- &arg->ca32_client.cl32_fhkey[0],
- NFSCLNT_KEYMAX);
+static int compat_nfs_clnt_trans(struct nfsctl_arg *karg,
+ struct compat_nfsctl_arg __user *arg)
+{
+ if (!access_ok(VERIFY_READ, &arg->ca32_clien