Commit 3ef3aca5 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 7c05bbf9 f55b6cfb
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <asm/mpspec.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -130,7 +130,6 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) ...@@ -130,7 +130,6 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
return 0; return 0;
error: error:
SetPageError(page); SetPageError(page);
kunmap(page);
unlock_page(page); unlock_page(page);
invalidate_inode_pages(inode->i_mapping); invalidate_inode_pages(inode->i_mapping);
desc->error = error; desc->error = error;
......
...@@ -54,6 +54,17 @@ nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, i ...@@ -54,6 +54,17 @@ nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, i
#define rpc_call_sync(clnt, msg, flags) \ #define rpc_call_sync(clnt, msg, flags) \
nfs3_rpc_wrapper(clnt, msg, flags) nfs3_rpc_wrapper(clnt, msg, flags)
static int
nfs3_async_handle_jukebox(struct rpc_task *task)
{
if (task->tk_status != -EJUKEBOX)
return 0;
task->tk_status = 0;
rpc_restart_call(task);
rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
return 1;
}
/* /*
* Bare-bones access to getattr: this is for nfs_read_super. * Bare-bones access to getattr: this is for nfs_read_super.
*/ */
...@@ -392,16 +403,20 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr ...@@ -392,16 +403,20 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr
return 0; return 0;
} }
static void static int
nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg) nfs3_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
{ {
struct rpc_message *msg = &task->tk_msg;
struct nfs_fattr *dir_attr; struct nfs_fattr *dir_attr;
if (nfs3_async_handle_jukebox(task))
return 1;
if (msg->rpc_argp) { if (msg->rpc_argp) {
dir_attr = (struct nfs_fattr*)msg->rpc_resp; dir_attr = (struct nfs_fattr*)msg->rpc_resp;
nfs_refresh_inode(dir->d_inode, dir_attr); nfs_refresh_inode(dir->d_inode, dir_attr);
kfree(msg->rpc_argp); kfree(msg->rpc_argp);
} }
return 0;
} }
static int static int
...@@ -652,7 +667,7 @@ nfs3_read_done(struct rpc_task *task) ...@@ -652,7 +667,7 @@ nfs3_read_done(struct rpc_task *task)
{ {
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
if (nfs_async_handle_jukebox(task)) if (nfs3_async_handle_jukebox(task))
return; return;
nfs_readpage_result(task, data->u.v3.res.count, data->u.v3.res.eof); nfs_readpage_result(task, data->u.v3.res.count, data->u.v3.res.eof);
} }
...@@ -692,6 +707,101 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -692,6 +707,101 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count)
rpc_call_setup(&data->task, &msg, 0); rpc_call_setup(&data->task, &msg, 0);
} }
static void
nfs3_write_done(struct rpc_task *task)
{
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
if (nfs3_async_handle_jukebox(task))
return;
nfs_writeback_done(task, data->u.v3.args.stable,
data->u.v3.args.count, data->u.v3.res.count);
}
static void
nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
struct nfs_page *req;
int stable;
int flags;
struct rpc_message msg;
if (how & FLUSH_STABLE) {
if (!NFS_I(inode)->ncommit)
stable = NFS_FILE_SYNC;
else
stable = NFS_DATA_SYNC;
} else
stable = NFS_UNSTABLE;
req = nfs_list_entry(data->pages.next);
data->u.v3.args.fh = NFS_FH(inode);
data->u.v3.args.offset = req_offset(req) + req->wb_offset;
data->u.v3.args.pgbase = req->wb_offset;
data->u.v3.args.count = count;
data->u.v3.args.stable = stable;
data->u.v3.args.pages = data->pagevec;
data->u.v3.res.fattr = &data->fattr;
data->u.v3.res.count = count;
data->u.v3.res.verf = &data->verf;
/* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs3_write_done, flags);
task->tk_calldata = data;
/* Release requests */
task->tk_release = nfs_writedata_release;
msg.rpc_proc = NFS3PROC_WRITE;
msg.rpc_argp = &data->u.v3.args;
msg.rpc_resp = &data->u.v3.res;
msg.rpc_cred = data->cred;
rpc_call_setup(&data->task, &msg, 0);
}
static void
nfs3_commit_done(struct rpc_task *task)
{
if (nfs3_async_handle_jukebox(task))
return;
nfs_commit_done(task);
}
static void
nfs3_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how)
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
int flags;
struct rpc_message msg;
data->u.v3.args.fh = NFS_FH(data->inode);
data->u.v3.args.offset = start;
data->u.v3.args.count = len;
data->u.v3.res.count = len;
data->u.v3.res.fattr = &data->fattr;
data->u.v3.res.verf = &data->verf;
/* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs3_commit_done, flags);
task->tk_calldata = data;
/* Release requests */
task->tk_release = nfs_writedata_release;
msg.rpc_proc = NFS3PROC_COMMIT;
msg.rpc_argp = &data->u.v3.args;
msg.rpc_resp = &data->u.v3.res;
msg.rpc_cred = data->cred;
rpc_call_setup(&data->task, &msg, 0);
}
struct nfs_rpc_ops nfs_v3_clientops = { struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */ .version = 3, /* protocol version */
.getroot = nfs3_proc_get_root, .getroot = nfs3_proc_get_root,
...@@ -716,4 +826,6 @@ struct nfs_rpc_ops nfs_v3_clientops = { ...@@ -716,4 +826,6 @@ struct nfs_rpc_ops nfs_v3_clientops = {
.statfs = nfs3_proc_statfs, .statfs = nfs3_proc_statfs,
.decode_dirent = nfs3_decode_dirent, .decode_dirent = nfs3_decode_dirent,
.read_setup = nfs3_proc_read_setup, .read_setup = nfs3_proc_read_setup,
.write_setup = nfs3_proc_write_setup,
.commit_setup = nfs3_proc_commit_setup,
}; };
...@@ -312,13 +312,16 @@ nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr * ...@@ -312,13 +312,16 @@ nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *
return 0; return 0;
} }
static void static int
nfs_proc_unlink_done(struct dentry *dir, struct rpc_message *msg) nfs_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
{ {
struct rpc_message *msg = &task->tk_msg;
if (msg->rpc_argp) { if (msg->rpc_argp) {
NFS_CACHEINV(dir->d_inode); NFS_CACHEINV(dir->d_inode);
kfree(msg->rpc_argp); kfree(msg->rpc_argp);
} }
return 0;
} }
static int static int
...@@ -512,6 +515,58 @@ nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -512,6 +515,58 @@ nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count)
rpc_call_setup(&data->task, &msg, 0); rpc_call_setup(&data->task, &msg, 0);
} }
static void
nfs_write_done(struct rpc_task *task)
{
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
nfs_writeback_done(task, data->u.v3.args.stable,
data->u.v3.args.count, data->u.v3.res.count);
}
static void
nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
struct nfs_page *req;
int flags;
struct rpc_message msg;
/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
req = nfs_list_entry(data->pages.next);
data->u.v3.args.fh = NFS_FH(inode);
data->u.v3.args.offset = req_offset(req) + req->wb_offset;
data->u.v3.args.pgbase = req->wb_offset;
data->u.v3.args.count = count;
data->u.v3.args.stable = NFS_FILE_SYNC;
data->u.v3.args.pages = data->pagevec;
data->u.v3.res.fattr = &data->fattr;
data->u.v3.res.count = count;
data->u.v3.res.verf = &data->verf;
/* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs_write_done, flags);
task->tk_calldata = data;
/* Release requests */
task->tk_release = nfs_writedata_release;
msg.rpc_proc = NFSPROC_WRITE;
msg.rpc_argp = &data->u.v3.args;
msg.rpc_resp = &data->u.v3.res;
msg.rpc_cred = data->cred;
rpc_call_setup(&data->task, &msg, 0);
}
static void
nfs_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how)
{
BUG();
}
struct nfs_rpc_ops nfs_v2_clientops = { struct nfs_rpc_ops nfs_v2_clientops = {
.version = 2, /* protocol version */ .version = 2, /* protocol version */
.getroot = nfs_proc_get_root, .getroot = nfs_proc_get_root,
...@@ -537,4 +592,6 @@ struct nfs_rpc_ops nfs_v2_clientops = { ...@@ -537,4 +592,6 @@ struct nfs_rpc_ops nfs_v2_clientops = {
.statfs = nfs_proc_statfs, .statfs = nfs_proc_statfs,
.decode_dirent = nfs_decode_dirent, .decode_dirent = nfs_decode_dirent,
.read_setup = nfs_proc_read_setup, .read_setup = nfs_proc_read_setup,
.write_setup = nfs_proc_write_setup,
.commit_setup = nfs_proc_commit_setup,
}; };
...@@ -123,13 +123,12 @@ nfs_async_unlink_done(struct rpc_task *task) ...@@ -123,13 +123,12 @@ nfs_async_unlink_done(struct rpc_task *task)
struct dentry *dir = data->dir; struct dentry *dir = data->dir;
struct inode *dir_i; struct inode *dir_i;
if (nfs_async_handle_jukebox(task))
return;
if (!dir) if (!dir)
return; return;
dir_i = dir->d_inode; dir_i = dir->d_inode;
nfs_zap_caches(dir_i); nfs_zap_caches(dir_i);
NFS_PROTO(dir_i)->unlink_done(dir, &task->tk_msg); if (NFS_PROTO(dir_i)->unlink_done(dir, task))
return;
put_rpccred(data->cred); put_rpccred(data->cred);
data->cred = NULL; data->cred = NULL;
dput(dir); dput(dir);
......
This diff is collapsed.
...@@ -323,6 +323,14 @@ extern void nfs_complete_unlink(struct dentry *); ...@@ -323,6 +323,14 @@ extern void nfs_complete_unlink(struct dentry *);
extern int nfs_writepage(struct page *); extern int nfs_writepage(struct page *);
extern int nfs_flush_incompatible(struct file *file, struct page *page); extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
extern void nfs_writeback_done(struct rpc_task *task, int stable,
unsigned int arg_count, unsigned int res_count);
extern void nfs_writedata_release(struct rpc_task *task);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern void nfs_commit_done(struct rpc_task *);
#endif
/* /*
* Try to write back everything synchronously (but check the * Try to write back everything synchronously (but check the
* return value!) * return value!)
...@@ -462,28 +470,7 @@ extern void * nfs_root_data(void); ...@@ -462,28 +470,7 @@ extern void * nfs_root_data(void);
__retval; \ __retval; \
}) })
#ifdef CONFIG_NFS_V3
#define NFS_JUKEBOX_RETRY_TIME (5 * HZ) #define NFS_JUKEBOX_RETRY_TIME (5 * HZ)
static inline int
nfs_async_handle_jukebox(struct rpc_task *task)
{
if (task->tk_status != -EJUKEBOX)
return 0;
task->tk_status = 0;
rpc_restart_call(task);
rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
return 1;
}
#else
static inline int
nfs_async_handle_jukebox(struct rpc_task *task)
{
return 0;
}
#endif /* CONFIG_NFS_V3 */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -67,6 +67,7 @@ struct nfs_fsinfo { ...@@ -67,6 +67,7 @@ struct nfs_fsinfo {
__u64 afiles; /* # of files available to user */ __u64 afiles; /* # of files available to user */
__u32 linkmax;/* max # of hard links */ __u32 linkmax;/* max # of hard links */
__u32 namelen;/* max name length */ __u32 namelen;/* max name length */
__u32 lease_time; /* in seconds */
}; };
/* /*
...@@ -326,6 +327,25 @@ struct nfs_read_data { ...@@ -326,6 +327,25 @@ struct nfs_read_data {
} u; } u;
}; };
struct nfs_write_data {
struct rpc_task task;
struct inode *inode;
struct rpc_cred *cred;
struct nfs_fattr fattr;
struct nfs_writeverf verf;
struct list_head pages; /* Coalesced requests we wish to flush */
struct page *pagevec[NFS_WRITE_MAXIOV];
union {
struct {
struct nfs_writeargs args;
struct nfs_writeres res;
} v3;
#ifdef CONFIG_NFS_V4
/* NFSv4 data to come here... */
#endif
} u;
};
/* /*
* RPC procedure vector for NFSv2/NFSv3 demuxing * RPC procedure vector for NFSv2/NFSv3 demuxing
*/ */
...@@ -356,7 +376,7 @@ struct nfs_rpc_ops { ...@@ -356,7 +376,7 @@ struct nfs_rpc_ops {
int (*remove) (struct inode *, struct qstr *); int (*remove) (struct inode *, struct qstr *);
int (*unlink_setup) (struct rpc_message *, int (*unlink_setup) (struct rpc_message *,
struct dentry *, struct qstr *); struct dentry *, struct qstr *);
void (*unlink_done) (struct dentry *, struct rpc_message *); int (*unlink_done) (struct dentry *, struct rpc_task *);
int (*rename) (struct inode *, struct qstr *, int (*rename) (struct inode *, struct qstr *,
struct inode *, struct qstr *); struct inode *, struct qstr *);
int (*link) (struct inode *, struct inode *, struct qstr *); int (*link) (struct inode *, struct inode *, struct qstr *);
...@@ -374,6 +394,8 @@ struct nfs_rpc_ops { ...@@ -374,6 +394,8 @@ struct nfs_rpc_ops {
struct nfs_fsinfo *); struct nfs_fsinfo *);
u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus);
void (*read_setup) (struct nfs_read_data *, unsigned int count); void (*read_setup) (struct nfs_read_data *, unsigned int count);
void (*write_setup) (struct nfs_write_data *, unsigned int count, int how);
void (*commit_setup) (struct nfs_write_data *, u64 start, u32 len, int how);
}; };
/* /*
......
...@@ -1446,6 +1446,8 @@ xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock) ...@@ -1446,6 +1446,8 @@ xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
sk->no_check = UDP_CSUM_NORCV; sk->no_check = UDP_CSUM_NORCV;
xprt_set_connected(xprt); xprt_set_connected(xprt);
} else { } else {
struct tcp_opt *tp = tcp_sk(sk);
tp->nonagle = 1; /* disable Nagle's algorithm */
sk->data_ready = tcp_data_ready; sk->data_ready = tcp_data_ready;
sk->state_change = tcp_state_change; sk->state_change = tcp_state_change;
xprt_clear_connected(xprt); xprt_clear_connected(xprt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment