Commit aeb08fc0 authored by Trond Myklebust's avatar Trond Myklebust

Merge http://nfsclient.bkbits.net/linux-2.5

into fys.uio.no:/home/linux/bitkeeper/nfsclient-2.5
parents fa9fcf5f b67cfdb8
......@@ -1305,15 +1305,18 @@ config NFS_V3
Say Y here if you want your NFS client to be able to speak the newer
version 3 of the NFS protocol.
If unsure, say N.
If unsure, say Y.
config NFS_V4
bool "Provide NFSv4 client support (EXPERIMENTAL)"
depends on NFS_FS && EXPERIMENTAL
select RPCSEC_GSS_KRB5
help
Say Y here if you want your NFS client to be able to speak the newer
version 4 of the NFS protocol. This feature is experimental, and
should only be used if you are interested in helping to test NFSv4.
version 4 of the NFS protocol.
Note: Requires auxiliary userspace daemons which may be found on
http://www.citi.umich.edu/projects/nfsv4/
If unsure, say N.
......@@ -1422,28 +1425,24 @@ config SUNRPC
tristate
config SUNRPC_GSS
tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)"
tristate
config RPCSEC_GSS_KRB5
tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
depends on SUNRPC && EXPERIMENTAL
default SUNRPC if NFS_V4=y
select SUNRPC_GSS
select CRYPTO
select CRYPTO_MD5
select CRYPTO_DES
help
Provides cryptographic authentication for NFS rpc requests. To
make this useful, you must also select at least one rpcsec_gss
mechanism.
Note: You should always select this option if you wish to use
Provides for secure RPC calls by means of a gss-api
mechanism based on Kerberos V5. This is required for
NFSv4.
config RPCSEC_GSS_KRB5
tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)"
depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5
default SUNRPC_GSS if NFS_V4=y
help
Provides a gss-api mechanism based on Kerberos V5 (this is
mandatory for RFC3010-compliant NFSv4 implementations).
Requires a userspace daemon;
see http://www.citi.umich.edu/projects/nfsv4/.
Note: Requires an auxiliary userspace daemon which may be found on
http://www.citi.umich.edu/projects/nfsv4/
Note: If you select this option, please ensure that you also
enable the MD5 and DES crypto ciphers.
If unsure, say N.
config SMB_FS
tristate "SMB file system support (to mount Windows shares etc.)"
......
......@@ -1178,6 +1178,8 @@ void inode_update_time(struct inode *inode, int ctime_too)
struct timespec now;
int sync_it = 0;
if (IS_NOCMTIME(inode))
return;
if (IS_RDONLY(inode))
return;
......
......@@ -443,7 +443,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
}
if (status < 0)
return status;
} while (resp->status == NLM_LCK_BLOCKED);
} while (resp->status == NLM_LCK_BLOCKED && req->a_args.block);
if (resp->status == NLM_LCK_GRANTED) {
fl->fl_u.nfs_fl.state = host->h_state;
......
......@@ -188,14 +188,14 @@ nlm_bind_host(struct nlm_host *host)
}
} else {
xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL);
if (xprt == NULL)
if (IS_ERR(xprt))
goto forgetit;
xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
host->h_version, host->h_authflavor);
if (clnt == NULL) {
if (IS_ERR(clnt)) {
xprt_destroy(xprt);
goto forgetit;
}
......
......@@ -36,10 +36,11 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
int status;
struct nsm_args args;
status = -EACCES;
clnt = nsm_create();
if (!clnt)
if (IS_ERR(clnt)) {
status = PTR_ERR(clnt);
goto out;
}
args.addr = host->h_addr.sin_addr.s_addr;
args.proto= (host->h_proto<<1) | host->h_server;
......@@ -104,7 +105,7 @@ static struct rpc_clnt *
nsm_create(void)
{
struct rpc_xprt *xprt;
struct rpc_clnt *clnt = NULL;
struct rpc_clnt *clnt;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
......@@ -112,24 +113,23 @@ nsm_create(void)
sin.sin_port = 0;
xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL);
if (!xprt)
goto out;
if (IS_ERR(xprt))
return (struct rpc_clnt *)xprt;
clnt = rpc_create_client(xprt, "localhost",
&nsm_program, SM_VERSION,
RPC_AUTH_NULL);
if (!clnt)
if (IS_ERR(clnt))
goto out_destroy;
clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
clnt->cl_oneshot = 1;
xprt->resvport = 1; /* NSM requires a reserved port */
out:
return clnt;
out_destroy:
xprt_destroy(xprt);
goto out;
return clnt;
}
/*
......
......@@ -452,6 +452,24 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
return rpc_success;
}
/*
* client sent a GRANTED_RES, let's remove the associated block
*/
static int
nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
void *resp)
{
if (!nlmsvc_ops)
return rpc_success;
dprintk("lockd: GRANTED_RES called\n");
nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status);
return rpc_success;
}
/*
* This is the generic lockd callback for async RPC calls
*/
......@@ -515,7 +533,6 @@ nlm4svc_callback_exit(struct rpc_task *task)
#define nlm4svc_proc_lock_res nlm4svc_proc_null
#define nlm4svc_proc_cancel_res nlm4svc_proc_null
#define nlm4svc_proc_unlock_res nlm4svc_proc_null
#define nlm4svc_proc_granted_res nlm4svc_proc_null
struct nlm_void { int dummy; };
......@@ -548,7 +565,7 @@ struct svc_procedure nlmsvc_procedures4[] = {
PROC(lock_res, lockres, norep, res, void, 1),
PROC(cancel_res, cancelres, norep, res, void, 1),
PROC(unlock_res, unlockres, norep, res, void, 1),
PROC(granted_res, grantedres, norep, res, void, 1),
PROC(granted_res, res, norep, res, void, 1),
/* statd callback */
PROC(sm_notify, reboot, void, reboot, void, 1),
PROC(none, void, void, void, void, 0),
......
......@@ -64,7 +64,7 @@ nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
if (when != NLM_NEVER) {
if ((when += jiffies) == NLM_NEVER)
when ++;
while ((b = *bp) && time_before_eq(b->b_when,when))
while ((b = *bp) && time_before_eq(b->b_when,when) && b->b_when != NLM_NEVER)
bp = &b->b_next;
} else
while ((b = *bp))
......@@ -143,14 +143,15 @@ static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
* Find a block with a given NLM cookie.
*/
static inline struct nlm_block *
nlmsvc_find_block(struct nlm_cookie *cookie)
nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin)
{
struct nlm_block *block;
for (block = nlm_blocked; block; block = block->b_next) {
dprintk("cookie: head of blocked queue %p, block %p\n",
nlm_blocked, block);
if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie))
if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie)
&& nlm_cmp_addr(sin, &block->b_host->h_addr))
break;
}
......@@ -566,12 +567,16 @@ nlmsvc_grant_callback(struct rpc_task *task)
struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata;
struct nlm_block *block;
unsigned long timeout;
struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client);
dprintk("lockd: GRANT_MSG RPC callback\n");
dprintk("callback: looking for cookie %x \n",
*(unsigned int *)(call->a_args.cookie.data));
if (!(block = nlmsvc_find_block(&call->a_args.cookie))) {
dprintk("lockd: no block for cookie %x\n", *(u32 *)(call->a_args.cookie.data));
dprintk("callback: looking for cookie %x, host (%08x)\n",
*(unsigned int *)(call->a_args.cookie.data),
ntohl(peer_addr->sin_addr.s_addr));
if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) {
dprintk("lockd: no block for cookie %x, host (%08x)\n",
*(u32 *)(call->a_args.cookie.data),
ntohl(peer_addr->sin_addr.s_addr));
return;
}
......@@ -600,18 +605,21 @@ nlmsvc_grant_callback(struct rpc_task *task)
* block.
*/
void
nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status)
{
struct nlm_block *block;
struct nlm_file *file;
if (!(block = nlmsvc_find_block(cookie)))
dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n",
*(unsigned int *)(cookie->data),
ntohl(rqstp->rq_addr.sin_addr.s_addr), status);
if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr)))
return;
file = block->b_file;
file->f_count++;
down(&file->f_sema);
if ((block = nlmsvc_find_block(cookie)) != NULL) {
if ((block = nlmsvc_find_block(cookie,&rqstp->rq_addr)) != NULL) {
if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
/* Try again in a couple of seconds */
nlmsvc_insert_block(block, 10 * HZ);
......
......@@ -478,6 +478,22 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
return rpc_success;
}
/*
* client sent a GRANTED_RES, let's remove the associated block
*/
static int
nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
void *resp)
{
if (!nlmsvc_ops)
return rpc_success;
dprintk("lockd: GRANTED_RES called\n");
nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status);
return rpc_success;
}
/*
* This is the generic lockd callback for async RPC calls
*/
......@@ -541,7 +557,6 @@ nlmsvc_callback_exit(struct rpc_task *task)
#define nlmsvc_proc_lock_res nlmsvc_proc_null
#define nlmsvc_proc_cancel_res nlmsvc_proc_null
#define nlmsvc_proc_unlock_res nlmsvc_proc_null
#define nlmsvc_proc_granted_res nlmsvc_proc_null
struct nlm_void { int dummy; };
......@@ -576,7 +591,7 @@ struct svc_procedure nlmsvc_procedures[] = {
PROC(lock_res, lockres, norep, res, void, 1),
PROC(cancel_res, cancelres, norep, res, void, 1),
PROC(unlock_res, unlockres, norep, res, void, 1),
PROC(granted_res, grantedres, norep, res, void, 1),
PROC(granted_res, res, norep, res, void, 1),
/* statd callback */
PROC(sm_notify, reboot, void, reboot, void, 1),
PROC(none, void, void, void, void, 1),
......
This diff is collapsed.
......@@ -269,6 +269,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
if (IS_SYNC(inode) || NFS_PROTO(inode)->version == 2 || count <= wsize)
wdata.args.stable = NFS_FILE_SYNC;
nfs_begin_data_update(inode);
retry:
need_commit = 0;
tot_bytes = 0;
......@@ -334,6 +335,8 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
VERF_SIZE) != 0)
goto sync_retry;
}
nfs_end_data_update(inode);
NFS_FLAGS(inode) |= NFS_INO_INVALID_DATA;
return tot_bytes;
......
......@@ -104,11 +104,16 @@ nfs_file_flush(struct file *file)
dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
if ((file->f_mode & FMODE_WRITE) == 0)
return 0;
lock_kernel();
status = nfs_wb_file(inode, file);
/* Ensure that data+attribute caches are up to date after close() */
status = nfs_wb_all(inode);
if (!status) {
status = file->f_error;
file->f_error = 0;
if (!status)
__nfs_revalidate_inode(NFS_SERVER(inode), inode);
}
unlock_kernel();
return status;
......@@ -179,7 +184,7 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
lock_kernel();
status = nfs_wb_file(inode, file);
status = nfs_wb_all(inode);
if (!status) {
status = file->f_error;
file->f_error = 0;
......
This diff is collapsed.
......@@ -57,8 +57,9 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
(unsigned)ntohl(addr->sin_addr.s_addr), path);
sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr));
if (!(mnt_clnt = mnt_create(hostname, addr, version, protocol)))
return -EACCES;
mnt_clnt = mnt_create(hostname, addr, version, protocol);
if (IS_ERR(mnt_clnt))
return PTR_ERR(mnt_clnt);
call = (version == NFS_MNT3_VERSION) ? MOUNTPROC3_MNT : MNTPROC_MNT;
status = rpc_call(mnt_clnt, call, path, &result, 0);
......@@ -72,13 +73,14 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
struct rpc_xprt *xprt;
struct rpc_clnt *clnt;
if (!(xprt = xprt_create_proto(protocol, srvaddr, NULL)))
return NULL;
xprt = xprt_create_proto(protocol, srvaddr, NULL);
if (IS_ERR(xprt))
return (struct rpc_clnt *)xprt;
clnt = rpc_create_client(xprt, hostname,
&mnt_program, version,
RPC_AUTH_NULL);
if (!clnt) {
RPC_AUTH_UNIX);
if (IS_ERR(clnt)) {
xprt_destroy(xprt);
} else {
clnt->cl_softrtry = 1;
......
......@@ -36,33 +36,33 @@ extern int nfs_stat_to_errno(int stat);
* Declare the space requirements for NFS arguments and replies as
* number of 32bit-words
*/
#define NFS_fhandle_sz 8
#define NFS_sattr_sz 8
#define NFS_filename_sz 1+(NFS2_MAXNAMLEN>>2)
#define NFS_path_sz 1+(NFS2_MAXPATHLEN>>2)
#define NFS_fattr_sz 17
#define NFS_info_sz 5
#define NFS_entry_sz NFS_filename_sz+3
#define NFS_diropargs_sz NFS_fhandle_sz+NFS_filename_sz
#define NFS_sattrargs_sz NFS_fhandle_sz+NFS_sattr_sz
#define NFS_readlinkargs_sz NFS_fhandle_sz
#define NFS_readargs_sz NFS_fhandle_sz+3
#define NFS_writeargs_sz NFS_fhandle_sz+4
#define NFS_createargs_sz NFS_diropargs_sz+NFS_sattr_sz
#define NFS_renameargs_sz NFS_diropargs_sz+NFS_diropargs_sz
#define NFS_linkargs_sz NFS_fhandle_sz+NFS_diropargs_sz
#define NFS_symlinkargs_sz NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz
#define NFS_readdirargs_sz NFS_fhandle_sz+2
#define NFS_attrstat_sz 1+NFS_fattr_sz
#define NFS_diropres_sz 1+NFS_fhandle_sz+NFS_fattr_sz
#define NFS_readlinkres_sz 1
#define NFS_readres_sz 1+NFS_fattr_sz+1
#define NFS_writeres_sz NFS_attrstat_sz
#define NFS_stat_sz 1
#define NFS_readdirres_sz 1
#define NFS_statfsres_sz 1+NFS_info_sz
#define NFS_fhandle_sz (8)
#define NFS_sattr_sz (8)
#define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2))
#define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2))
#define NFS_fattr_sz (17)
#define NFS_info_sz (5)
#define NFS_entry_sz (NFS_filename_sz+3)
#define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
#define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz)
#define NFS_readlinkargs_sz (NFS_fhandle_sz)
#define NFS_readargs_sz (NFS_fhandle_sz+3)
#define NFS_writeargs_sz (NFS_fhandle_sz+4)
#define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz)
#define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz)
#define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz)
#define NFS_symlinkargs_sz (NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz)
#define NFS_readdirargs_sz (NFS_fhandle_sz+2)
#define NFS_attrstat_sz (1+NFS_fattr_sz)
#define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz)
#define NFS_readlinkres_sz (1)
#define NFS_readres_sz (1+NFS_fattr_sz+1)
#define NFS_writeres_sz (NFS_attrstat_sz)
#define NFS_stat_sz (1)
#define NFS_readdirres_sz (1)
#define NFS_statfsres_sz (1+NFS_info_sz)
/*
* Common NFS XDR functions as inlines
......
......@@ -68,20 +68,6 @@ nfs3_async_handle_jukebox(struct rpc_task *task)
return 1;
}
static void
nfs3_write_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
{
if (fattr->valid & NFS_ATTR_FATTR) {
if (!(fattr->valid & NFS_ATTR_WCC)) {
fattr->pre_size = NFS_CACHE_ISIZE(inode);
fattr->pre_mtime = NFS_CACHE_MTIME(inode);
fattr->pre_ctime = NFS_CACHE_CTIME(inode);
fattr->valid |= NFS_ATTR_WCC;
}
nfs_refresh_inode(inode, fattr);
}
}
static struct rpc_cred *
nfs_cred(struct inode *inode, struct file *filp)
{
......@@ -99,14 +85,18 @@ nfs_cred(struct inode *inode, struct file *filp)
*/
static int
nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
struct nfs_fsinfo *info)
{
int status;
dprintk("NFS call getroot\n");
fattr->valid = 0;
status = rpc_call(server->client, NFS3PROC_GETATTR, fhandle, fattr, 0);
dprintk("NFS reply getroot\n");
dprintk("%s: call fsinfo\n", __FUNCTION__);
info->fattr->valid = 0;
status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
dprintk("%s: reply fsinfo %d\n", __FUNCTION__, status);
if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
status = rpc_call(server->client_sys, NFS3PROC_GETATTR, fhandle, info->fattr, 0);
dprintk("%s: reply getattr %d\n", __FUNCTION__, status);
}
return status;
}
......@@ -280,7 +270,7 @@ nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
if (status >= 0)
nfs3_write_refresh_inode(inode, fattr);
nfs_refresh_inode(inode, fattr);
dprintk("NFS reply write: %d\n", status);
return status < 0? status : wdata->res.count;
}
......@@ -303,7 +293,7 @@ nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
if (status >= 0)
nfs3_write_refresh_inode(inode, fattr);
nfs_refresh_inode(inode, fattr);
dprintk("NFS reply commit: %d\n", status);
return status;
}
......@@ -777,12 +767,13 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count)
static void
nfs3_write_done(struct rpc_task *task)
{
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
struct nfs_write_data *data;
if (nfs3_async_handle_jukebox(task))
return;
data = (struct nfs_write_data *)task->tk_calldata;
if (task->tk_status >= 0)
nfs3_write_refresh_inode(data->inode, data->res.fattr);
nfs_refresh_inode(data->inode, data->res.fattr);
nfs_writeback_done(task);
}
......@@ -835,12 +826,13 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
static void
nfs3_commit_done(struct rpc_task *task)
{
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
struct nfs_write_data *data;
if (nfs3_async_handle_jukebox(task))
return;
data = (struct nfs_write_data *)task->tk_calldata;
if (task->tk_status >= 0)
nfs3_write_refresh_inode(data->inode, data->res.fattr);
nfs_refresh_inode(data->inode, data->res.fattr);
nfs_commit_done(task);
}
......
......@@ -33,51 +33,51 @@ extern int nfs_stat_to_errno(int);
* Declare the space requirements for NFS arguments and replies as
* number of 32bit-words
*/
#define NFS3_fhandle_sz 1+16
#define NFS3_fh_sz NFS3_fhandle_sz /* shorthand */
#define NFS3_sattr_sz 15
#define NFS3_filename_sz 1+(NFS3_MAXNAMLEN>>2)
#define NFS3_path_sz 1+(NFS3_MAXPATHLEN>>2)
#define NFS3_fattr_sz 21
#define NFS3_wcc_attr_sz 6
#define NFS3_pre_op_attr_sz 1+NFS3_wcc_attr_sz
#define NFS3_post_op_attr_sz 1+NFS3_fattr_sz
#define NFS3_wcc_data_sz NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz
#define NFS3_fhandle_sz (1+16)
#define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
#define NFS3_sattr_sz (15)
#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
#define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
#define NFS3_fattr_sz (21)
#define NFS3_wcc_attr_sz (6)
#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
#define NFS3_fsstat_sz
#define NFS3_fsinfo_sz
#define NFS3_pathconf_sz
#define NFS3_entry_sz NFS3_filename_sz+3
#define NFS3_sattrargs_sz NFS3_fh_sz+NFS3_sattr_sz+3
#define NFS3_diropargs_sz NFS3_fh_sz+NFS3_filename_sz
#define NFS3_accessargs_sz NFS3_fh_sz+1
#define NFS3_readlinkargs_sz NFS3_fh_sz
#define NFS3_readargs_sz NFS3_fh_sz+3
#define NFS3_writeargs_sz NFS3_fh_sz+5
#define NFS3_createargs_sz NFS3_diropargs_sz+NFS3_sattr_sz
#define NFS3_mkdirargs_sz NFS3_diropargs_sz+NFS3_sattr_sz
#define NFS3_symlinkargs_sz NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz
#define NFS3_mknodargs_sz NFS3_diropargs_sz+2+NFS3_sattr_sz
#define NFS3_renameargs_sz NFS3_diropargs_sz+NFS3_diropargs_sz
#define NFS3_linkargs_sz NFS3_fh_sz+NFS3_diropargs_sz
#define NFS3_readdirargs_sz NFS3_fh_sz+2
#define NFS3_commitargs_sz NFS3_fh_sz+3
#define NFS3_attrstat_sz 1+NFS3_fattr_sz
#define NFS3_wccstat_sz 1+NFS3_wcc_data_sz
#define NFS3_lookupres_sz 1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)
#define NFS3_accessres_sz 1+NFS3_post_op_attr_sz+1
#define NFS3_readlinkres_sz 1+NFS3_post_op_attr_sz
#define NFS3_readres_sz 1+NFS3_post_op_attr_sz+3
#define NFS3_writeres_sz 1+NFS3_wcc_data_sz+4
#define NFS3_createres_sz 1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz
#define NFS3_renameres_sz 1+(2 * NFS3_wcc_data_sz)
#define NFS3_linkres_sz 1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz
#define NFS3_readdirres_sz 1+NFS3_post_op_attr_sz+2
#define NFS3_fsstatres_sz 1+NFS3_post_op_attr_sz+13
#define NFS3_fsinfores_sz 1+NFS3_post_op_attr_sz+12
#define NFS3_pathconfres_sz 1+NFS3_post_op_attr_sz+6
#define NFS3_commitres_sz 1+NFS3_wcc_data_sz+2
#define NFS3_entry_sz (NFS3_filename_sz+3)
#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
#define NFS3_accessargs_sz (NFS3_fh_sz+1)
#define NFS3_readlinkargs_sz (NFS3_fh_sz)
#define NFS3_readargs_sz (NFS3_fh_sz+3)
#define NFS3_writeargs_sz (NFS3_fh_sz+5)
#define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz)
#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
#define NFS3_readdirargs_sz (NFS3_fh_sz+2)
#define NFS3_commitargs_sz (NFS3_fh_sz+3)
#define NFS3_attrstat_sz (1+NFS3_fattr_sz)
#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz)
#define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
#define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
#define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
#define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
#define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
#define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
#define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
#define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
/*
* Map file type to S_IFMT bits
......@@ -103,9 +103,7 @@ static struct {
static inline u32 *
xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
{
*p++ = htonl(fh->size);
memcpy(p, fh->data, fh->size);
return p + XDR_QUADLEN(fh->size);
return xdr_encode_array(p, fh->data, fh->size);
}
static inline u32 *
......
This diff is collapsed.
......@@ -411,18 +411,20 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
return state;
}
void
nfs4_put_open_state(struct nfs4_state *state)
static void
__nfs4_put_open_state(struct nfs4_state *state)
{
struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner;
int status = 0;
if (!atomic_dec_and_lock(&state->count, &inode->i_lock))
if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) {
up(&owner->so_sema);
return;
}
if (!list_empty(&state->inode_states))
list_del(&state->inode_states);
spin_unlock(&inode->i_lock);
down(&owner->so_sema);
list_del(&state->open_states);
if (state->state != 0) {
do {
......@@ -439,6 +441,13 @@ nfs4_put_open_state(struct nfs4_state *state)
nfs4_put_state_owner(owner);
}
void
nfs4_put_open_state(struct nfs4_state *state)
{
down(&state->owner->so_sema);
__nfs4_put_open_state(state);
}
void
nfs4_close_state(struct nfs4_state *state, mode_t mode)
{
......@@ -479,8 +488,7 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
status = nfs4_handle_error(NFS_SERVER(inode), status);
down(&owner->so_sema);
} while (!status);
up(&owner->so_sema);
nfs4_put_open_state(state);
__nfs4_put_open_state(state);
}
/*
......@@ -790,7 +798,7 @@ reclaimer(void *ptr)
restart_loop:
spin_lock(&clp->cl_lock);
list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
if (sp->so_generation - generation <= 0)
if (sp->so_generation - generation >= 0)
continue;
atomic_inc(&sp->so_count);
spin_unlock(&clp->cl_lock);
......
This diff is collapsed.
......@@ -165,37 +165,6 @@ static struct nfs_bool_opts {
};
/*
* Extract IP address from the parameter string if needed. Note that we
* need to have root_server_addr set _before_ IPConfig gets called as it
* can override it.
*/
static void __init root_nfs_parse_addr(char *name)
{
int octets = 0;
char *cp, *cq;
cp = cq = name;
while (octets < 4) {
while (*cp >= '0' && *cp <= '9')
cp++;
if (cp == cq || cp - cq > 3)
break;
if (*cp == '.' || octets == 3)
octets++;
if (octets < 4)
cp++;
cq = cp;
}
if (octets == 4 && (*cp == ':' || *cp == '\0')) {
if (*cp == ':')
*cp++ = '\0';
root_server_addr = in_aton(name);
strcpy(name, cp);
}
}
/*
* Parse option string.
*/
......@@ -345,7 +314,7 @@ int __init nfs_root_setup(char *line)
line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
sprintf(nfs_root_name, NFS_ROOT, line);
}
root_nfs_parse_addr(nfs_root_name);
root_server_addr = root_nfs_parse_addr(nfs_root_name);
return 1;
}
......
......@@ -246,7 +246,6 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
* nfs_scan_list - Scan a list for matching requests
* @head: One of the NFS inode request lists
* @dst: Destination list
* @file: if set, ensure we match requests from this file
* @idx_start: lower bound of page->index to scan
* @npages: idx_start + npages sets the upper bound to scan.
*
......@@ -258,7 +257,6 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
*/
int
nfs_scan_list(struct list_head *head, struct list_head *dst,
struct file *file,
unsigned long idx_start, unsigned int npages)
{
struct list_head *pos, *tmp;
......@@ -276,9 +274,6 @@ nfs_scan_list(struct list_head *head, struct list_head *dst,
req = nfs_list_entry(pos);
if (file && req->wb_file != file)
continue;
if (req->wb_index < idx_start)
continue;
if (req->wb_index > idx_end)
......
......@@ -49,18 +49,6 @@
extern struct rpc_procinfo nfs_procedures[];
static void
nfs_write_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
{
if (!(fattr->valid & NFS_ATTR_WCC)) {
fattr->pre_size = NFS_CACHE_ISIZE(inode);
fattr->pre_mtime = NFS_CACHE_MTIME(inode);
fattr->pre_ctime = NFS_CACHE_CTIME(inode);
fattr->valid |= NFS_ATTR_WCC;
}
nfs_refresh_inode(inode, fattr);
}
static struct rpc_cred *
nfs_cred(struct inode *inode, struct file *filp)
{
......@@ -78,15 +66,33 @@ nfs_cred(struct inode *inode, struct file *filp)
*/
static int
nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
struct nfs_fsinfo *info)
{
struct nfs_fattr *fattr = info->fattr;
struct nfs2_fsstat fsinfo;
int status;
dprintk("NFS call getroot\n");
dprintk("%s: call getattr\n", __FUNCTION__);
fattr->valid = 0;
status = rpc_call(server->client, NFSPROC_GETATTR, fhandle, fattr, 0);
dprintk("NFS reply getroot\n");
status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0);
dprintk("%s: reply getattr %d\n", __FUNCTION__, status);
if (status)
return status;
dprintk("%s: call statfs\n", __FUNCTION__);
status = rpc_call(server->client_sys, NFSPROC_STATFS, fhandle, &fsinfo, 0);
dprintk("%s: reply statfs %d\n", __FUNCTION__, status);
if (status)
return status;
info->rtmax = NFS_MAXDATA;
info->rtpref = fsinfo.tsize;
info->rtmult = fsinfo.bsize;
info->wtmax = NFS_MAXDATA;
info->wtpref = fsinfo.tsize;
info->wtmult = fsinfo.bsize;
info->dtpref = fsinfo.tsize;
info->maxfilesize = 0x7FFFFFFF;
info->lease_time = 0;
return 0;
}
/*
......@@ -180,8 +186,14 @@ nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
if (status >= 0)
if (status >= 0) {
nfs_refresh_inode(inode, fattr);
/* Emulate the eof flag, which isn't normally needed in NFSv2
* as it is guaranteed to always return the file attributes
*/
if (rdata->args.offset + rdata->args.count >= fattr->size)
rdata->res.eof = 1;
}
dprintk("NFS reply read: %d\n", status);
return status;
}
......@@ -205,7 +217,7 @@ nfs_proc_write(struct nfs_write_data *wdata, struct file *filp)
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
if (status >= 0) {
nfs_write_refresh_inode(inode, fattr);
nfs_refresh_inode(inode, fattr);
wdata->res.count = wdata->args.count;
wdata->verf.committed = NFS_FILE_SYNC;
}
......@@ -331,10 +343,8 @@ nfs_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
{
struct rpc_message *msg = &task->tk_msg;
if (msg->rpc_argp) {
NFS_CACHEINV(dir->d_inode);
if (msg->rpc_argp)
kfree(msg->rpc_argp);
}
return 0;
}
......@@ -537,8 +547,14 @@ nfs_read_done(struct rpc_task *task)
{
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
if (task->tk_status >= 0)
if (task->tk_status >= 0) {
nfs_refresh_inode(data->inode, data->res.fattr);
/* Emulate the eof flag, which isn't normally needed in NFSv2
* as it is guaranteed to always return the file attributes
*/
if (data->args.offset + data->args.count >= data->res.fattr->size)
data->res.eof = 1;
}
nfs_readpage_result(task);
}
......@@ -584,7 +600,7 @@ nfs_write_done(struct rpc_task *task)
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
if (task->tk_status >= 0)
nfs_write_refresh_inode(data->inode, data->res.fattr);
nfs_refresh_inode(data->inode, data->res.fattr);
nfs_writeback_done(task);
}
......
......@@ -121,9 +121,13 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
}
count -= result;
rdata.args.pgbase += result;
if (result < rdata.args.count) /* NFSv2ism */
/* Note: result == 0 should only happen if we're caching
* a write that extends the file and punches a hole.
*/
if (rdata.res.eof != 0 || result == 0)
break;
} while (count);
NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
if (count)
memclear_highpage_flush(page, rdata.args.pgbase, count);
......@@ -266,6 +270,7 @@ nfs_readpage_result(struct rpc_task *task)
dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
task->tk_pid, task->tk_status);
NFS_FLAGS(data->inode) |= NFS_INO_INVALID_ATIME;
while (!list_empty(&data->pages)) {
struct nfs_page *req = nfs_list_entry(data->pages.next);
struct page *page = req->wb_page;
......
......@@ -104,6 +104,7 @@ nfs_async_unlink_init(struct rpc_task *task)
status = NFS_PROTO(dir->d_inode)->unlink_setup(&msg, dir, &data->name);
if (status < 0)
goto out_err;
nfs_begin_data_update(dir->d_inode);
rpc_call_setup(task, &msg, 0);
return;
out_err:
......@@ -126,7 +127,7 @@ nfs_async_unlink_done(struct rpc_task *task)
if (!dir)
return;
dir_i = dir->d_inode;
nfs_zap_caches(dir_i);
nfs_end_data_update(dir_i);
if (NFS_PROTO(dir_i)->unlink_done(dir, task))
return;
put_rpccred(data->cred);
......
This diff is collapsed.
......@@ -138,6 +138,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
#define S_DEAD 32 /* removed, but still open directory */
#define S_NOQUOTA 64 /* Inode is not counted to quota */
#define S_DIRSYNC 128 /* Directory modifications are synchronous */
#define S_NOCMTIME 256 /* Do not update file c/mtime */
/*
* Note that nosuid etc flags are inode-specific: setting some file-system
......@@ -171,6 +172,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
#define IS_ONE_SECOND(inode) __IS_FLG(inode, MS_ONE_SECOND)
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
/* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */
......
......@@ -23,7 +23,7 @@
#undef ifdebug
#if defined(RPC_DEBUG) && defined(LOCKD_DEBUG)
# define ifdebug(flag) if (nlm_debug & NLMDBG_##flag)
# define ifdebug(flag) if (unlikely(nlm_debug & NLMDBG_##flag))
#else
# define ifdebug(flag) if (0)
#endif
......
......@@ -165,6 +165,7 @@ u32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
unsigned long nlmsvc_retry_blocked(void);
int nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
int action);
void nlmsvc_grant_reply(struct svc_rqst *, struct nlm_cookie *, u32);
/*
* File handling for the server personality
......
......@@ -99,7 +99,7 @@ struct nfs_inode {
/*
* Various flags
*/
unsigned short flags;
unsigned int flags;
/*
* read_cache_jiffies is when we started read-caching this inode,
......@@ -118,19 +118,22 @@ struct nfs_inode {
*
* mtime != read_cache_mtime
*/
unsigned long readdir_timestamp;
unsigned long read_cache_jiffies;
struct timespec read_cache_ctime;
struct timespec read_cache_mtime;
__u64 read_cache_isize;
unsigned long attrtimeo;
unsigned long attrtimeo_timestamp;
__u64 change_attr; /* v4 only */
/* "Generation counter" for the attribute cache. This is
* bumped whenever we update the metadata on the
* server.
*/
unsigned long cache_change_attribute;
/*
* Timestamp that dates the change made to read_cache_mtime.
* This is of use for dentry revalidation
* Counter indicating the number of outstanding requests that
* will cause a file data update.
*/
unsigned long cache_mtime_jiffies;
atomic_t data_updates;
struct nfs_access_cache cache_access;
......@@ -170,8 +173,9 @@ struct nfs_inode {
#define NFS_INO_STALE 0x0001 /* possible stale inode */
#define NFS_INO_ADVISE_RDPLUS 0x0002 /* advise readdirplus */
#define NFS_INO_REVALIDATING 0x0004 /* revalidating attrs */
#define NFS_INO_FLUSH 0x0008 /* inode is due for flushing */
#define NFS_INO_FAKE_ROOT 0x0080 /* root inode placeholder */
#define NFS_INO_INVALID_ATTR 0x0008 /* cached attrs are invalid */
#define NFS_INO_INVALID_DATA 0x0010 /* cached data is invalid */
#define NFS_INO_INVALID_ATIME 0x0020 /* cached atime is invalid */
static inline struct nfs_inode *NFS_I(struct inode *inode)
{
......@@ -186,15 +190,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode)
#define NFS_ADDR(inode) (RPC_PEERADDR(NFS_CLIENT(inode)))
#define NFS_COOKIEVERF(inode) (NFS_I(inode)->cookieverf)
#define NFS_READTIME(inode) (NFS_I(inode)->read_cache_jiffies)
#define NFS_MTIME_UPDATE(inode) (NFS_I(inode)->cache_mtime_jiffies)
#define NFS_CACHE_CTIME(inode) (NFS_I(inode)->read_cache_ctime)
#define NFS_CACHE_MTIME(inode) (NFS_I(inode)->read_cache_mtime)
#define NFS_CACHE_ISIZE(inode) (NFS_I(inode)->read_cache_isize)
#define NFS_CHANGE_ATTR(inode) (NFS_I(inode)->change_attr)
#define NFS_CACHEINV(inode) \
do { \
NFS_READTIME(inode) = jiffies - NFS_MAXATTRTIMEO(inode) - 1; \
} while (0)
#define NFS_ATTRTIMEO(inode) (NFS_I(inode)->attrtimeo)
#define NFS_MINATTRTIMEO(inode) \
(S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmin \
......@@ -207,10 +203,20 @@ do { \
#define NFS_FLAGS(inode) (NFS_I(inode)->flags)
#define NFS_REVALIDATING(inode) (NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
#define NFS_STALE(inode) (NFS_FLAGS(inode) & NFS_INO_STALE)
#define NFS_FAKE_ROOT(inode) (NFS_FLAGS(inode) & NFS_INO_FAKE_ROOT)
#define NFS_FILEID(inode) (NFS_I(inode)->fileid)
static inline int nfs_caches_unstable(struct inode *inode)
{
return atomic_read(&NFS_I(inode)->data_updates) != 0;
}
static inline void NFS_CACHEINV(struct inode *inode)
{
if (!nfs_caches_unstable(inode))
NFS_FLAGS(inode) |= NFS_INO_INVALID_ATTR;
}
static inline int nfs_server_capable(struct inode *inode, int cap)
{
return NFS_SERVER(inode)->caps & cap;
......@@ -227,13 +233,37 @@ loff_t page_offset(struct page *page)
return ((loff_t)page->index) << PAGE_CACHE_SHIFT;
}
/**
* nfs_save_change_attribute - Returns the inode attribute change cookie
* @inode - pointer to inode
* The "change attribute" is updated every time we finish an operation
* that will result in a metadata change on the server.
*/
static inline long nfs_save_change_attribute(struct inode *inode)
{
return NFS_I(inode)->cache_change_attribute;
}
/**
* nfs_verify_change_attribute - Detects NFS inode cache updates
* @inode - pointer to inode
* @chattr - previously saved change attribute
* Return "false" if metadata has been updated (or is in the process of
* being updated) since the change attribute was saved.
*/
static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long chattr)
{
return !nfs_caches_unstable(inode)
&& chattr == NFS_I(inode)->cache_change_attribute;
}
/*
* linux/fs/nfs/inode.c
*/
extern void nfs_zap_caches(struct inode *);
extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
struct nfs_fattr *);
extern int __nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int nfs_permission(struct inode *, int, struct nameidata *);
extern void nfs_set_mmcred(struct inode *, struct rpc_cred *);
......@@ -241,6 +271,13 @@ extern int nfs_open(struct inode *, struct file *);
extern int nfs_release(struct inode *, struct file *);
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
extern int nfs_setattr(struct dentry *, struct iattr *);
extern void nfs_begin_attr_update(struct inode *);
extern void nfs_end_attr_update(struct inode *);
extern void nfs_begin_data_update(struct inode *);
extern void nfs_end_data_update(struct inode *);
/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
extern u32 root_nfs_parse_addr(char *name); /*__init*/
/*
* linux/fs/nfs/file.c
......@@ -309,16 +346,15 @@ extern void nfs_commit_done(struct rpc_task *);
* Try to write back everything synchronously (but check the
* return value!)
*/
extern int nfs_sync_file(struct inode *, struct file *, unsigned long, unsigned int, int);
extern int nfs_flush_file(struct inode *, struct file *, unsigned long, unsigned int, int);
extern int nfs_sync_inode(struct inode *, unsigned long, unsigned int, int);
extern int nfs_flush_inode(struct inode *, unsigned long, unsigned int, int);
extern int nfs_flush_list(struct list_head *, int, int);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern int nfs_commit_file(struct inode *, struct file *, unsigned long, unsigned int, int);
extern int nfs_commit_inode(struct inode *, unsigned long, unsigned int, int);
extern int nfs_commit_list(struct list_head *, int);
#else
static inline int
nfs_commit_file(struct inode *inode, struct file *file, unsigned long offset,
unsigned int len, int flags)
nfs_commit_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how)
{
return 0;
}
......@@ -333,7 +369,7 @@ nfs_have_writebacks(struct inode *inode)
static inline int
nfs_wb_all(struct inode *inode)
{
int error = nfs_sync_file(inode, 0, 0, 0, FLUSH_WAIT);
int error = nfs_sync_inode(inode, 0, 0, FLUSH_WAIT);
return (error < 0) ? error : 0;
}
......@@ -343,21 +379,11 @@ nfs_wb_all(struct inode *inode)
static inline int
nfs_wb_page(struct inode *inode, struct page* page)
{
int error = nfs_sync_file(inode, 0, page->index, 1,
int error = nfs_sync_inode(inode, page->index, 1,
FLUSH_WAIT | FLUSH_STABLE);
return (error < 0) ? error : 0;
}
/*
* Write back all pending writes for one user..
*/
static inline int
nfs_wb_file(struct inode *inode, struct file *file)
{
int error = nfs_sync_file(inode, file, 0, 0, FLUSH_WAIT);
return (error < 0) ? error : 0;
}
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
......@@ -383,20 +409,27 @@ extern int nfsroot_mount(struct sockaddr_in *, char *, struct nfs_fh *,
/*
* inline functions
*/
static inline int
nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
static inline int nfs_attribute_timeout(struct inode *inode)
{
if (time_before(jiffies, NFS_READTIME(inode)+NFS_ATTRTIMEO(inode)))
return NFS_STALE(inode) ? -ESTALE : 0;
return __nfs_revalidate_inode(server, inode);
struct nfs_inode *nfsi = NFS_I(inode);
return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
}
static inline int
nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
/**
* nfs_revalidate_inode - Revalidate the inode attributes
* @server - pointer to nfs_server struct
* @inode - pointer to inode struct
*
* Updates inode attribute information by retrieving the data from the server.
*/
static inline int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
{
if ((fattr->valid & NFS_ATTR_FATTR) == 0)
return 0;
return __nfs_refresh_inode(inode,fattr);
if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
&& !nfs_attribute_timeout(inode))
return NFS_STALE(inode) ? -ESTALE : 0;
return __nfs_revalidate_inode(server, inode);
}
static inline loff_t
......@@ -661,7 +694,7 @@ struct nfs4_mount_data;
#ifdef __KERNEL__
# undef ifdebug
# ifdef NFS_DEBUG
# define ifdebug(fac) if (nfs_debug & NFSDBG_##fac)
# define ifdebug(fac) if (unlikely(nfs_debug & NFSDBG_##fac))
# else
# define ifdebug(fac) if (0)
# endif
......
......@@ -53,7 +53,7 @@ extern void nfs_release_request(struct nfs_page *req);
extern void nfs_list_add_request(struct nfs_page *, struct list_head *);
extern int nfs_scan_list(struct list_head *, struct list_head *,
struct file *, unsigned long, unsigned int);
unsigned long, unsigned int);
extern int nfs_coalesce_requests(struct list_head *, struct list_head *,
unsigned int);
extern int nfs_wait_on_request(struct nfs_page *);
......
......@@ -700,7 +700,7 @@ struct nfs_rpc_ops {
struct inode_operations *dir_inode_ops;
int (*getroot) (struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *);
struct nfs_fsinfo *);
int (*getattr) (struct inode *, struct nfs_fattr *);
int (*setattr) (struct dentry *, struct nfs_fattr *,
struct iattr *);
......
......@@ -54,7 +54,7 @@ extern unsigned int nlm_debug;
#undef ifdebug
#ifdef RPC_DEBUG
# define ifdebug(fac) if (rpc_debug & RPCDBG_##fac)
# define ifdebug(fac) if (unlikely(rpc_debug & RPCDBG_##fac))
# define dfprintk(fac, args...) do { ifdebug(fac) printk(args); } while(0)
# define RPC_IFDEBUG(x) x
#else
......@@ -92,6 +92,8 @@ enum {
CTL_NFSDEBUG,
CTL_NFSDDEBUG,
CTL_NLMDEBUG,
CTL_SLOTTABLE_UDP,
CTL_SLOTTABLE_TCP,
};
#endif /* _LINUX_SUNRPC_DEBUG_H_ */
......@@ -25,9 +25,18 @@ extern unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned timer);
static inline void rpc_set_timeo(struct rpc_rtt *rt, int timer, int ntimeo)
{
int *t;
if (!timer)
return;
rt->ntimeouts[timer-1] = ntimeo;
t = &rt->ntimeouts[timer-1];
if (ntimeo < *t) {
if (*t > 0)
(*t)--;
} else {
if (ntimeo > 8)
ntimeo = 8;
*t = ntimeo;
}
}
static inline int rpc_ntimeo(struct rpc_rtt *rt, int timer)
......
......@@ -87,7 +87,7 @@ struct xdr_buf {
/*
* Miscellaneous XDR helper functions
*/
u32 * xdr_encode_array(u32 *p, const char *s, unsigned int len);
u32 * xdr_encode_array(u32 *p, const void *s, unsigned int len);
u32 * xdr_encode_string(u32 *p, const char *s);
u32 * xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen);
u32 * xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen);
......
......@@ -28,16 +28,18 @@
*
* Upper procedures may check whether a request would block waiting for
* a free RPC slot by using the RPC_CONGESTED() macro.
*
* Note: on machines with low memory we should probably use a smaller
* MAXREQS value: At 32 outstanding reqs with 8 megs of RAM, fragment
* reassembly will frequently run out of memory.
*/
#define RPC_MAXCONG (16)
#define RPC_MAXREQS RPC_MAXCONG
#define RPC_CWNDSCALE (256)
#define RPC_MAXCWND (RPC_MAXCONG * RPC_CWNDSCALE)
*/
extern unsigned int xprt_udp_slot_table_entries;
extern unsigned int xprt_tcp_slot_table_entries;
#define RPC_MIN_SLOT_TABLE (2U)
#define RPC_DEF_SLOT_TABLE (16U)
#define RPC_MAX_SLOT_TABLE (128U)
#define RPC_CWNDSHIFT (8U)
#define RPC_CWNDSCALE (1U << RPC_CWNDSHIFT)
#define RPC_INITCWND RPC_CWNDSCALE
#define RPC_MAXCWND(xprt) ((xprt)->max_reqs << RPC_CWNDSHIFT)
#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
/* Default timeout values */
......@@ -92,7 +94,6 @@ struct rpc_rqst {
*/
struct rpc_task * rq_task; /* RPC task data */
__u32 rq_xid; /* request XID */
struct rpc_rqst * rq_next; /* free list */
int rq_cong; /* has incremented xprt->cong */
int rq_received; /* receive completed */
u32 rq_seqno; /* gss seq no. used on req. */
......@@ -102,7 +103,6 @@ struct rpc_rqst {
struct xdr_buf rq_private_buf; /* The receive buffer
* used in the softirq.
*/
/*
* For authentication (e.g. auth_des)
*/
......@@ -146,14 +146,20 @@ struct rpc_xprt {
struct rpc_wait_queue resend; /* requests waiting to resend */
struct rpc_wait_queue pending; /* requests in flight */
struct rpc_wait_queue backlog; /* waiting for slot */
struct rpc_rqst * free; /* free slots */
struct rpc_rqst slot[RPC_MAXREQS];
struct list_head free; /* free slots */
struct rpc_rqst * slot; /* slot table storage */
unsigned int max_reqs; /* total slots */
unsigned long sockstate; /* Socket state */
unsigned char shutdown : 1, /* being shut down */
nocong : 1, /* no congestion control */
resvport : 1, /* use a reserved port */
stream : 1; /* TCP */
/*
* XID
*/
__u32 xid; /* Next XID value to use */
/*
* State of TCP reply receive stuff
*/
......@@ -163,6 +169,11 @@ struct rpc_xprt {
tcp_offset; /* fragment offset */
unsigned long tcp_copied, /* copied to request */
tcp_flags;
/*
* Connection of sockets
*/
struct work_struct sock_connect;
unsigned short port;
/*
* Disconnection of idle sockets
*/
......
......@@ -1188,6 +1188,40 @@ static struct file_operations pnp_seq_fops = {
};
#endif /* CONFIG_PROC_FS */
/*
* Extract IP address from the parameter string if needed. Note that we
* need to have root_server_addr set _before_ IPConfig gets called as it
* can override it.
*/
u32 __init root_nfs_parse_addr(char *name)
{
u32 addr;
int octets = 0;
char *cp, *cq;
cp = cq = name;
while (octets < 4) {
while (*cp >= '0' && *cp <= '9')
cp++;
if (cp == cq || cp - cq > 3)
break;
if (*cp == '.' || octets == 3)
octets++;
if (octets < 4)
cp++;
cq = cp;
}
if (octets == 4 && (*cp == ':' || *cp == '\0')) {
if (*cp == ':')
*cp++ = '\0';
addr = in_aton(name);
strcpy(name, cp);
} else
addr = INADDR_NONE;
return addr;
}
/*
* IP Autoconfig dispatcher.
*/
......@@ -1195,6 +1229,7 @@ static struct file_operations pnp_seq_fops = {
static int __init ip_auto_config(void)
{
unsigned long jiff;
u32 addr;
#ifdef CONFIG_PROC_FS
proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops);
......@@ -1283,6 +1318,10 @@ static int __init ip_auto_config(void)
ic_dev = ic_first_dev->dev;
}
addr = root_nfs_parse_addr(root_server_path);
if (root_server_addr == INADDR_NONE)
root_server_addr = addr;
/*
* Use defaults whereever applicable.
*/
......
......@@ -149,7 +149,7 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid)
struct rpc_clnt *clnt = task->tk_client;
struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
u32 *base, *hold;
int i, n;
int i;
*p++ = htonl(RPC_AUTH_UNIX);
base = p++;
......@@ -158,10 +158,7 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid)
/*
* Copy the UTS nodename captured when the client was created.
*/
n = clnt->cl_nodelen;
*p++ = htonl(n);
memcpy(p, clnt->cl_nodename, n);
p += (n + 3) >> 2;
p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
/* Note: we don't use real uid if it involves raising privilege */
if (ruid && cred->uc_puid != 0 && cred->uc_pgid != 0) {
......
......@@ -102,19 +102,22 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
{
struct rpc_version *version;
struct rpc_clnt *clnt = NULL;
int err;
int len;
dprintk("RPC: creating %s client for %s (xprt %p)\n",
program->name, servname, xprt);
err = -EINVAL;
if (!xprt)
goto out;
goto out_err;
if (vers >= program->nrvers || !(version = program->version[vers]))
goto out;
goto out_err;
err = -ENOMEM;
clnt = (struct rpc_clnt *) kmalloc(sizeof(*clnt), GFP_KERNEL);
if (!clnt)
goto out_no_clnt;
goto out_err;
memset(clnt, 0, sizeof(*clnt));
atomic_set(&clnt->cl_users, 0);
atomic_set(&clnt->cl_count, 1);
......@@ -149,9 +152,11 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
clnt->cl_rtt = &clnt->cl_rtt_default;
rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval);
if (rpc_setup_pipedir(clnt, program->pipe_dir_name) < 0)
err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
if (err < 0)
goto out_no_path;
err = -ENOMEM;
if (!rpcauth_create(flavor, clnt)) {
printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n",
flavor);
......@@ -163,20 +168,16 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
if (clnt->cl_nodelen > UNX_MAXNODENAME)
clnt->cl_nodelen = UNX_MAXNODENAME;
memcpy(clnt->cl_nodename, system_utsname.nodename, clnt->cl_nodelen);
out:
return clnt;
out_no_clnt:
printk(KERN_INFO "RPC: out of memory in rpc_create_client\n");
goto out;
out_no_auth:
rpc_rmdir(clnt->cl_pathname);
out_no_path:
if (clnt->cl_server != clnt->cl_inline_name)
kfree(clnt->cl_server);
kfree(clnt);
clnt = NULL;
goto out;
out_err:
return ERR_PTR(err);
}
/*
......@@ -198,11 +199,10 @@ rpc_clone_client(struct rpc_clnt *clnt)
atomic_inc(&new->cl_parent->cl_count);
if (new->cl_auth)
atomic_inc(&new->cl_auth->au_count);
out:
return new;
out_no_clnt:
printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
goto out;
return ERR_PTR(-ENOMEM);
}
/*
......@@ -611,9 +611,6 @@ call_encode(struct rpc_task *task)
rcvbuf->page_len = 0;
rcvbuf->len = bufsiz;
/* Zero buffer so we have automatic zero-padding of opaque & string */
memset(task->tk_buffer, 0, bufsiz);
/* Encode header and provided arguments */
encode = task->tk_msg.rpc_proc->p_encode;
if (!(p = call_header(task))) {
......
......@@ -65,9 +65,11 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
map->pm_binding = 1;
spin_unlock(&pmap_lock);
task->tk_status = -EACCES; /* why set this? returns -EIO below */
if (!(pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot)))
pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot);
if (IS_ERR(pmap_clnt)) {
task->tk_status = PTR_ERR(pmap_clnt);
goto bailout;
}
task->tk_status = 0;
/*
......@@ -110,8 +112,9 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
if (!(pmap_clnt = pmap_create(hostname, sin, prot)))
return -EACCES;
pmap_clnt = pmap_create(hostname, sin, prot);
if (IS_ERR(pmap_clnt))
return PTR_ERR(pmap_clnt);
/* Setup the call info struct */
status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0);
......@@ -161,16 +164,18 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
struct sockaddr_in sin;
struct rpc_portmap map;
struct rpc_clnt *pmap_clnt;
unsigned int error = 0;
int error = 0;
dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n",
prog, vers, prot, port);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (!(pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP))) {
dprintk("RPC: couldn't create pmap client\n");
return -EACCES;
pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP);
if (IS_ERR(pmap_clnt)) {
error = PTR_ERR(pmap_clnt);
dprintk("RPC: couldn't create pmap client. Error = %d\n", error);
return error;
}
map.pm_prog = prog;
......@@ -199,15 +204,16 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
struct rpc_clnt *clnt;
/* printk("pmap: create xprt\n"); */
if (!(xprt = xprt_create_proto(proto, srvaddr, NULL)))
return NULL;
xprt = xprt_create_proto(proto, srvaddr, NULL);
if (IS_ERR(xprt))
return (struct rpc_clnt *)xprt;
xprt->addr.sin_port = htons(RPC_PMAP_PORT);
/* printk("pmap: create clnt\n"); */
clnt = rpc_create_client(xprt, hostname,
&pmap_program, RPC_PMAP_VERSION,
RPC_AUTH_NULL);
if (!clnt) {
if (IS_ERR(clnt)) {
xprt_destroy(xprt);
} else {
clnt->cl_softrtry = 1;
......
......@@ -530,6 +530,9 @@ __rpc_execute(struct rpc_task *task)
if (!task->tk_action)
break;
task->tk_action(task);
/* micro-optimization to avoid spinlock */
if (RPC_IS_RUNNING(task))
continue;
}
/*
......@@ -545,29 +548,31 @@ __rpc_execute(struct rpc_task *task)
}
spin_unlock_bh(&rpc_queue_lock);
while (RPC_IS_SLEEPING(task)) {
if (!RPC_IS_SLEEPING(task))
continue;
/* sync task: sleep here */
dprintk("RPC: %4d sync task going to sleep\n",
task->tk_pid);
dprintk("RPC: %4d sync task going to sleep\n", task->tk_pid);
if (current->pid == rpciod_pid)
printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
if (!task->tk_client->cl_intr) {
__wait_event(task->tk_wait, !RPC_IS_SLEEPING(task));
dprintk("RPC: %4d sync task resuming\n", task->tk_pid);
} else {
__wait_event_interruptible(task->tk_wait, !RPC_IS_SLEEPING(task), status);
/*
* When a sync task receives a signal, it exits with
* -ERESTARTSYS. In order to catch any callbacks that
* clean up after sleeping on some queue, we don't
* break the loop here, but go around once more.
*/
if (task->tk_client->cl_intr && signalled()) {
if (status == -ERESTARTSYS) {
dprintk("RPC: %4d got signal\n", task->tk_pid);
task->tk_flags |= RPC_TASK_KILLED;
rpc_exit(task, -ERESTARTSYS);
rpc_wake_up_task(task);
}
}
dprintk("RPC: %4d sync task resuming\n", task->tk_pid);
}
if (task->tk_exit) {
......
......@@ -63,6 +63,8 @@ EXPORT_SYMBOL(rpc_mkpipe);
EXPORT_SYMBOL(xprt_create_proto);
EXPORT_SYMBOL(xprt_destroy);
EXPORT_SYMBOL(xprt_set_timeout);
EXPORT_SYMBOL(xprt_udp_slot_table_entries);
EXPORT_SYMBOL(xprt_tcp_slot_table_entries);
/* Client credential cache */
EXPORT_SYMBOL(rpcauth_register);
......
/*
* linux/net/sunrpc/sysctl.c
*
* Sysctl interface to sunrpc module. This is for debugging only now.
* Sysctl interface to sunrpc module.
*
* I would prefer to register the sunrpc table below sys/net, but that's
* impossible at the moment.
......@@ -19,6 +19,7 @@
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/xprt.h>
/*
* Declare the debug flags here
......@@ -117,6 +118,9 @@ proc_dodebug(ctl_table *table, int write, struct file *file,
return 0;
}
static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
static ctl_table debug_table[] = {
{
.ctl_name = CTL_RPCDEBUG,
......@@ -150,6 +154,28 @@ static ctl_table debug_table[] = {
.mode = 0644,
.proc_handler = &proc_dodebug
},
{
.ctl_name = CTL_SLOTTABLE_UDP,
.procname = "udp_slot_table_entries",
.data = &xprt_udp_slot_table_entries,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_slot_table_size,
.extra2 = &max_slot_table_size
},
{
.ctl_name = CTL_SLOTTABLE_TCP,
.procname = "tcp_slot_table_entries",
.data = &xprt_tcp_slot_table_entries,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_slot_table_size,
.extra2 = &max_slot_table_size
},
{ .ctl_name = 0 }
};
......
......@@ -54,7 +54,7 @@ xdr_decode_netobj(u32 *p, struct xdr_netobj *obj)
}
u32 *
xdr_encode_array(u32 *p, const char *array, unsigned int len)
xdr_encode_array(u32 *p, const void *array, unsigned int len)
{
int quadlen = XDR_QUADLEN(len);
......
This diff is collapsed.
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