Commit 477d40b4 authored by Trond Myklebust's avatar Trond Myklebust

Merge fys.uio.no:/home/linux/bitkeeper/nfsclient-2.6

into fys.uio.no:/home/linux/bitkeeper/work/nfsclient-2.6
parents fec00732 60fa4cfb
......@@ -982,12 +982,18 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
/* We may have been initialized further down */
if (dentry->d_inode)
return 0;
if (fhandle->size == 0 || !(fattr->valid & NFS_ATTR_FATTR)) {
if (fhandle->size == 0) {
struct inode *dir = dentry->d_parent->d_inode;
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
if (error)
goto out_err;
}
if (!(fattr->valid & NFS_ATTR_FATTR)) {
struct nfs_server *server = NFS_SB(dentry->d_sb);
error = server->rpc_ops->getattr(server, fhandle, fattr);
if (error < 0)
goto out_err;
}
inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
if (inode) {
d_instantiate(dentry, inode);
......
......@@ -110,7 +110,7 @@ nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
* nfs_direct_read_seg - Read in one iov segment. Generate separate
* read RPCs for each "rsize" bytes.
* @inode: target inode
* @file: target file (may be NULL)
* @ctx: target file open context
* user_addr: starting address of this segment of user's buffer
* count: size of this segment
* file_offset: offset in file to begin the operation
......@@ -118,7 +118,7 @@ nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
* nr_pages: size of pages array
*/
static int
nfs_direct_read_seg(struct inode *inode, struct file *file,
nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx,
unsigned long user_addr, size_t count, loff_t file_offset,
struct page **pages, int nr_pages)
{
......@@ -127,9 +127,10 @@ nfs_direct_read_seg(struct inode *inode, struct file *file,
int curpage = 0;
struct nfs_read_data rdata = {
.inode = inode,
.cred = ctx->cred,
.args = {
.fh = NFS_FH(inode),
.lockowner = current->files,
.context = ctx,
},
.res = {
.fattr = &rdata.fattr,
......@@ -151,7 +152,7 @@ nfs_direct_read_seg(struct inode *inode, struct file *file,
user_addr + tot_bytes, rdata.args.pgbase, curpage);
lock_kernel();
result = NFS_PROTO(inode)->read(&rdata, file);
result = NFS_PROTO(inode)->read(&rdata);
unlock_kernel();
if (result <= 0) {
......@@ -183,7 +184,7 @@ nfs_direct_read_seg(struct inode *inode, struct file *file,
* nfs_direct_read - For each iov segment, map the user's buffer
* then generate read RPCs.
* @inode: target inode
* @file: target file (may be NULL)
* @ctx: target file open context
* @iov: array of vectors that define I/O buffer
* file_offset: offset in file to begin the operation
* nr_segs: size of iovec array
......@@ -193,7 +194,7 @@ nfs_direct_read_seg(struct inode *inode, struct file *file,
* server.
*/
static ssize_t
nfs_direct_read(struct inode *inode, struct file *file,
nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx,
const struct iovec *iov, loff_t file_offset,
unsigned long nr_segs)
{
......@@ -216,7 +217,7 @@ nfs_direct_read(struct inode *inode, struct file *file,
return page_count;
}
result = nfs_direct_read_seg(inode, file, user_addr, size,
result = nfs_direct_read_seg(inode, ctx, user_addr, size,
file_offset, pages, page_count);
nfs_free_user_pages(pages, page_count, 1);
......@@ -239,7 +240,7 @@ nfs_direct_read(struct inode *inode, struct file *file,
* nfs_direct_write_seg - Write out one iov segment. Generate separate
* write RPCs for each "wsize" bytes, then commit.
* @inode: target inode
* @file: target file (may be NULL)
* @ctx: target file open context
* user_addr: starting address of this segment of user's buffer
* count: size of this segment
* file_offset: offset in file to begin the operation
......@@ -247,7 +248,7 @@ nfs_direct_read(struct inode *inode, struct file *file,
* nr_pages: size of pages array
*/
static int
nfs_direct_write_seg(struct inode *inode, struct file *file,
nfs_direct_write_seg(struct inode *inode, struct nfs_open_context *ctx,
unsigned long user_addr, size_t count, loff_t file_offset,
struct page **pages, int nr_pages)
{
......@@ -257,9 +258,10 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
struct nfs_writeverf first_verf;
struct nfs_write_data wdata = {
.inode = inode,
.cred = ctx->cred,
.args = {
.fh = NFS_FH(inode),
.lockowner = current->files,
.context = ctx,
},
.res = {
.fattr = &wdata.fattr,
......@@ -290,7 +292,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
user_addr + tot_bytes, wdata.args.pgbase, curpage);
lock_kernel();
result = NFS_PROTO(inode)->write(&wdata, file);
result = NFS_PROTO(inode)->write(&wdata);
unlock_kernel();
if (result <= 0) {
......@@ -325,7 +327,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
wdata.args.offset = file_offset;
lock_kernel();
result = NFS_PROTO(inode)->commit(&wdata, file);
result = NFS_PROTO(inode)->commit(&wdata);
unlock_kernel();
if (result < 0 || memcmp(&first_verf.verifier,
......@@ -349,7 +351,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
* nfs_direct_write - For each iov segment, map the user's buffer
* then generate write and commit RPCs.
* @inode: target inode
* @file: target file (may be NULL)
* @ctx: target file open context
* @iov: array of vectors that define I/O buffer
* file_offset: offset in file to begin the operation
* nr_segs: size of iovec array
......@@ -358,8 +360,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
* that non-direct readers might access, so they will pick up these
* writes immediately.
*/
static ssize_t
nfs_direct_write(struct inode *inode, struct file *file,
static int nfs_direct_write(struct inode *inode, struct nfs_open_context *ctx,
const struct iovec *iov, loff_t file_offset,
unsigned long nr_segs)
{
......@@ -382,7 +383,7 @@ nfs_direct_write(struct inode *inode, struct file *file,
return page_count;
}
result = nfs_direct_write_seg(inode, file, user_addr, size,
result = nfs_direct_write_seg(inode, ctx, user_addr, size,
file_offset, pages, page_count);
nfs_free_user_pages(pages, page_count, 0);
......@@ -414,6 +415,7 @@ nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
{
ssize_t result = -EINVAL;
struct file *file = iocb->ki_filp;
struct nfs_open_context *ctx;
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
......@@ -423,19 +425,20 @@ nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
if (!is_sync_kiocb(iocb))
return result;
ctx = (struct nfs_open_context *)file->private_data;
switch (rw) {
case READ:
dprintk("NFS: direct_IO(read) (%s) off/no(%Lu/%lu)\n",
dentry->d_name.name, file_offset, nr_segs);
result = nfs_direct_read(inode, file, iov,
result = nfs_direct_read(inode, ctx, iov,
file_offset, nr_segs);
break;
case WRITE:
dprintk("NFS: direct_IO(write) (%s) off/no(%Lu/%lu)\n",
dentry->d_name.name, file_offset, nr_segs);
result = nfs_direct_write(inode, file, iov,
result = nfs_direct_write(inode, ctx, iov,
file_offset, nr_segs);
break;
default:
......@@ -471,6 +474,8 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
ssize_t retval = -EINVAL;
loff_t *ppos = &iocb->ki_pos;
struct file *file = iocb->ki_filp;
struct nfs_open_context *ctx =
(struct nfs_open_context *) file->private_data;
struct dentry *dentry = file->f_dentry;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
......@@ -502,7 +507,7 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
goto out;
}
retval = nfs_direct_read(inode, file, &iov, pos, 1);
retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
if (retval > 0)
*ppos = pos + retval;
......@@ -542,6 +547,8 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
loff_t *ppos = &iocb->ki_pos;
unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
struct file *file = iocb->ki_filp;
struct nfs_open_context *ctx =
(struct nfs_open_context *) file->private_data;
struct dentry *dentry = file->f_dentry;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
......@@ -589,7 +596,7 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
goto out;
}
retval = nfs_direct_write(inode, file, &iov, pos, 1);
retval = nfs_direct_write(inode, ctx, &iov, pos, 1);
if (mapping->nrpages)
invalidate_inode_pages2(mapping);
if (retval > 0)
......
......@@ -113,6 +113,7 @@ nfs_file_release(struct inode *inode, struct file *filp)
static int
nfs_file_flush(struct file *file)
{
struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
struct inode *inode = file->f_dentry->d_inode;
int status;
......@@ -124,8 +125,8 @@ nfs_file_flush(struct file *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;
status = ctx->error;
ctx->error = 0;
if (!status)
__nfs_revalidate_inode(NFS_SERVER(inode), inode);
}
......@@ -197,6 +198,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
static int
nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
struct inode *inode = dentry->d_inode;
int status;
......@@ -205,8 +207,8 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
lock_kernel();
status = nfs_wb_all(inode);
if (!status) {
status = file->f_error;
file->f_error = 0;
status = ctx->error;
ctx->error = 0;
}
unlock_kernel();
return status;
......
......@@ -121,8 +121,9 @@ nfs_delete_inode(struct inode * inode)
{
dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
nfs_wb_all(inode);
/*
* The following can never actually happen...
* The following should never happen...
*/
if (nfs_have_writebacks(inode)) {
printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino);
......@@ -139,10 +140,10 @@ static void
nfs_clear_inode(struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
struct rpc_cred *cred = nfsi->mm_cred;
struct rpc_cred *cred;
if (cred)
put_rpccred(cred);
nfs_wb_all(inode);
BUG_ON (!list_empty(&nfsi->open_files));
cred = nfsi->cache_access.cred;
if (cred)
put_rpccred(cred);
......@@ -812,53 +813,114 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
return err;
}
struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred)
{
struct nfs_open_context *ctx;
ctx = (struct nfs_open_context *)kmalloc(sizeof(*ctx), GFP_KERNEL);
if (ctx != NULL) {
atomic_set(&ctx->count, 1);
ctx->dentry = dget(dentry);
ctx->cred = get_rpccred(cred);
ctx->state = NULL;
ctx->lockowner = current->files;
ctx->error = 0;
init_waitqueue_head(&ctx->waitq);
}
return ctx;
}
struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
{
if (ctx != NULL)
atomic_inc(&ctx->count);
return ctx;
}
void put_nfs_open_context(struct nfs_open_context *ctx)
{
if (atomic_dec_and_test(&ctx->count)) {
if (ctx->state != NULL)
nfs4_close_state(ctx->state, ctx->mode);
if (ctx->cred != NULL)
put_rpccred(ctx->cred);
dput(ctx->dentry);
kfree(ctx);
}
}
/*
* Ensure that mmap has a recent RPC credential for use when writing out
* shared pages
*/
void
nfs_set_mmcred(struct inode *inode, struct rpc_cred *cred)
void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
{
struct rpc_cred **p = &NFS_I(inode)->mm_cred,
*oldcred = *p;
struct inode *inode = filp->f_dentry->d_inode;
struct nfs_inode *nfsi = NFS_I(inode);
*p = get_rpccred(cred);
if (oldcred)
put_rpccred(oldcred);
filp->private_data = get_nfs_open_context(ctx);
spin_lock(&inode->i_lock);
list_add(&ctx->list, &nfsi->open_files);
spin_unlock(&inode->i_lock);
}
struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode)
{
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_open_context *pos, *ctx = NULL;
spin_lock(&inode->i_lock);
list_for_each_entry(pos, &nfsi->open_files, list) {
if ((pos->mode & mode) == mode) {
ctx = get_nfs_open_context(pos);
break;
}
}
spin_unlock(&inode->i_lock);
return ctx;
}
void nfs_file_clear_open_context(struct file *filp)
{
struct inode *inode = filp->f_dentry->d_inode;
struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;
if (ctx) {
filp->private_data = NULL;
spin_lock(&inode->i_lock);
list_del(&ctx->list);
spin_unlock(&inode->i_lock);
put_nfs_open_context(ctx);
}
}
/*
* These are probably going to contain hooks for
* allocating and releasing RPC credentials for
* the file. I'll have to think about Tronds patch
* a bit more..
* These allocate and release file read/write context information.
*/
int nfs_open(struct inode *inode, struct file *filp)
{
struct rpc_auth *auth;
struct nfs_open_context *ctx;
struct rpc_cred *cred;
auth = NFS_CLIENT(inode)->cl_auth;
cred = rpcauth_lookupcred(auth, 0);
filp->private_data = cred;
if ((filp->f_mode & FMODE_WRITE) != 0) {
nfs_set_mmcred(inode, cred);
if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL)
return -ENOMEM;
ctx = alloc_nfs_open_context(filp->f_dentry, cred);
put_rpccred(cred);
if (ctx == NULL)
return -ENOMEM;
ctx->mode = filp->f_mode;
nfs_file_set_open_context(filp, ctx);
put_nfs_open_context(ctx);
if ((filp->f_mode & FMODE_WRITE) != 0)
nfs_begin_data_update(inode);
}
return 0;
}
int nfs_release(struct inode *inode, struct file *filp)
{
struct rpc_cred *cred;
lock_kernel();
if ((filp->f_mode & FMODE_WRITE) != 0)
nfs_end_data_update(inode);
cred = nfs_file_cred(filp);
if (cred)
put_rpccred(cred);
unlock_kernel();
nfs_file_clear_open_context(filp);
return 0;
}
......@@ -899,7 +961,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
/* Protect against RPC races by saving the change attribute */
verifier = nfs_save_change_attribute(inode);
status = NFS_PROTO(inode)->getattr(inode, &fattr);
status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
if (status) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
inode->i_sb->s_id,
......@@ -1397,6 +1459,9 @@ static void nfs4_clear_inode(struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
/* First call standard NFS clear_inode() code */
nfs_clear_inode(inode);
/* Now clear out any remaining state */
while (!list_empty(&nfsi->open_states)) {
struct nfs4_state *state;
......@@ -1411,8 +1476,6 @@ static void nfs4_clear_inode(struct inode *inode)
BUG_ON(atomic_read(&state->count) != 1);
nfs4_close_state(state, state->state);
}
/* Now call standard NFS clear_inode() code */
nfs_clear_inode(inode);
}
......@@ -1510,8 +1573,13 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
nfs_idmap_new(clp);
}
if (list_empty(&clp->cl_superblocks))
clear_bit(NFS4CLNT_OK, &clp->cl_state);
if (list_empty(&clp->cl_superblocks)) {
err = nfs4_init_client(clp);
if (err != 0) {
up_write(&clp->cl_sem);
goto out_fail;
}
}
list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
clnt = rpc_clone_client(clp->cl_rpcclient);
if (!IS_ERR(clnt))
......@@ -1712,7 +1780,6 @@ static struct inode *nfs_alloc_inode(struct super_block *sb)
if (!nfsi)
return NULL;
nfsi->flags = 0;
nfsi->mm_cred = NULL;
nfs4_zero_state(nfsi);
return &nfsi->vfs_inode;
}
......@@ -1732,6 +1799,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
spin_lock_init(&nfsi->req_lock);
INIT_LIST_HEAD(&nfsi->dirty);
INIT_LIST_HEAD(&nfsi->commit);
INIT_LIST_HEAD(&nfsi->open_files);
INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
atomic_set(&nfsi->data_updates, 0);
nfsi->ndirty = 0;
......
......@@ -68,18 +68,6 @@ nfs3_async_handle_jukebox(struct rpc_task *task)
return 1;
}
static struct rpc_cred *
nfs_cred(struct inode *inode, struct file *filp)
{
struct rpc_cred *cred = NULL;
if (filp)
cred = (struct rpc_cred *)filp->private_data;
if (!cred)
cred = NFS_I(inode)->mm_cred;
return cred;
}
/*
* Bare-bones access to getattr: this is for nfs_read_super.
*/
......@@ -104,14 +92,15 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* One function for each procedure in the NFS protocol.
*/
static int
nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
int status;
dprintk("NFS call getattr\n");
fattr->valid = 0;
status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
NFS_FH(inode), fattr, 0);
status = rpc_call(server->client, NFS3PROC_GETATTR,
fhandle, fattr, 0);
dprintk("NFS reply getattr\n");
return status;
}
......@@ -233,8 +222,7 @@ nfs3_proc_readlink(struct inode *inode, struct page *page)
return status;
}
static int
nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
static int nfs3_proc_read(struct nfs_read_data *rdata)
{
int flags = rdata->flags;
struct inode * inode = rdata->inode;
......@@ -243,13 +231,13 @@ nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
.rpc_proc = &nfs3_procedures[NFS3PROC_READ],
.rpc_argp = &rdata->args,
.rpc_resp = &rdata->res,
.rpc_cred = rdata->cred,
};
int status;
dprintk("NFS call read %d @ %Ld\n", rdata->args.count,
(long long) rdata->args.offset);
fattr->valid = 0;
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
if (status >= 0)
nfs_refresh_inode(inode, fattr);
......@@ -257,8 +245,7 @@ nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
return status;
}
static int
nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
static int nfs3_proc_write(struct nfs_write_data *wdata)
{
int rpcflags = wdata->flags;
struct inode * inode = wdata->inode;
......@@ -267,13 +254,13 @@ nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
.rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
.rpc_argp = &wdata->args,
.rpc_resp = &wdata->res,
.rpc_cred = wdata->cred,
};
int status;
dprintk("NFS call write %d @ %Ld\n", wdata->args.count,
(long long) wdata->args.offset);
fattr->valid = 0;
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
if (status >= 0)
nfs_refresh_inode(inode, fattr);
......@@ -281,8 +268,7 @@ nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
return status < 0? status : wdata->res.count;
}
static int
nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
static int nfs3_proc_commit(struct nfs_write_data *cdata)
{
struct inode * inode = cdata->inode;
struct nfs_fattr * fattr = cdata->res.fattr;
......@@ -290,13 +276,13 @@ nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
.rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT],
.rpc_argp = &cdata->args,
.rpc_resp = &cdata->res,
.rpc_cred = cdata->cred,
};
int status;
dprintk("NFS call commit %d @ %Ld\n", cdata->args.count,
(long long) cdata->args.offset);
fattr->valid = 0;
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
if (status >= 0)
nfs_refresh_inode(inode, fattr);
......@@ -840,27 +826,6 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
rpc_call_setup(task, &msg, 0);
}
/*
* Set up the nfspage struct with the right credentials
*/
void
nfs3_request_init(struct nfs_page *req, struct file *filp)
{
req->wb_cred = get_rpccred(nfs_cred(req->wb_inode, filp));
}
static int
nfs3_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
{
if (req->wb_file != filp)
return 0;
if (req->wb_page != page)
return 0;
if (req->wb_cred != nfs_file_cred(filp))
return 0;
return 1;
}
static int
nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
{
......@@ -900,7 +865,5 @@ struct nfs_rpc_ops nfs_v3_clientops = {
.commit_setup = nfs3_proc_commit_setup,
.file_open = nfs_open,
.file_release = nfs_release,
.request_init = nfs3_request_init,
.request_compatible = nfs3_request_compatible,
.lock = nfs3_proc_lock,
};
This diff is collapsed.
This diff is collapsed.
......@@ -404,6 +404,15 @@ struct compound_hdr {
BUG_ON(!p); \
} while (0)
static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
{
uint32_t *p;
p = xdr_reserve_space(xdr, 4 + len);
BUG_ON(p == NULL);
xdr_encode_opaque(p, str, len);
}
static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
{
uint32_t *p;
......@@ -903,15 +912,15 @@ static int encode_putrootfh(struct xdr_stream *xdr)
return 0;
}
static void encode_stateid(struct xdr_stream *xdr, struct nfs4_state *state, fl_owner_t lockowner)
static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
{
extern nfs4_stateid zero_stateid;
nfs4_stateid stateid;
uint32_t *p;
RESERVE_SPACE(16);
if (state != NULL) {
nfs4_copy_stateid(&stateid, state, lockowner);
if (ctx->state != NULL) {
nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner);
WRITEMEM(stateid.data, sizeof(stateid.data));
} else
WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
......@@ -924,7 +933,7 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
RESERVE_SPACE(4);
WRITE32(OP_READ);
encode_stateid(xdr, args->state, args->lockowner);
encode_stateid(xdr, args->context);
RESERVE_SPACE(12);
WRITE64(args->offset);
......@@ -1047,26 +1056,18 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *
static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid)
{
uint32_t total_len;
uint32_t len1, len2, len3;
uint32_t *p;
len1 = strlen(setclientid->sc_name);
len2 = strlen(setclientid->sc_netid);
len3 = strlen(setclientid->sc_uaddr);
total_len = XDR_QUADLEN(len1) + XDR_QUADLEN(len2) + XDR_QUADLEN(len3);
total_len = (total_len << 2) + 24 + sizeof(setclientid->sc_verifier.data);
RESERVE_SPACE(total_len);
RESERVE_SPACE(4 + sizeof(setclientid->sc_verifier->data));
WRITE32(OP_SETCLIENTID);
WRITEMEM(setclientid->sc_verifier.data, sizeof(setclientid->sc_verifier.data));
WRITE32(len1);
WRITEMEM(setclientid->sc_name, len1);
WRITEMEM(setclientid->sc_verifier->data, sizeof(setclientid->sc_verifier->data));
encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
RESERVE_SPACE(4);
WRITE32(setclientid->sc_prog);
WRITE32(len2);
WRITEMEM(setclientid->sc_netid, len2);
WRITE32(len3);
WRITEMEM(setclientid->sc_uaddr, len3);
encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
RESERVE_SPACE(4);
WRITE32(setclientid->sc_cb_ident);
return 0;
......@@ -1091,7 +1092,7 @@ static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args
RESERVE_SPACE(4);
WRITE32(OP_WRITE);
encode_stateid(xdr, args->state, args->lockowner);
encode_stateid(xdr, args->context);
RESERVE_SPACE(16);
WRITE64(args->offset);
......@@ -1252,9 +1253,9 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n
goto out;
if ((status = encode_create(&xdr, args)) != 0)
goto out;
if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
if ((status = encode_getfh(&xdr)) != 0)
goto out;
status = encode_getfh(&xdr);
status = encode_getfattr(&xdr, args->bitmask);
out:
return status;
}
......@@ -1325,10 +1326,10 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena
status = encode_open(&xdr, args);
if (status)
goto out;
status = encode_getfattr(&xdr, args->bitmask);
status = encode_getfh(&xdr);
if (status)
goto out;
status = encode_getfh(&xdr);
status = encode_getfattr(&xdr, args->bitmask);
out:
return status;
}
......@@ -3220,9 +3221,11 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
goto out;
if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
goto out;
if ((status = decode_getfattr(&xdr, res->fattr, res->server)) != 0)
if ((status = decode_getfh(&xdr, res->fh)) != 0)
goto out;
status = decode_getfh(&xdr, res->fh);
status = decode_getfattr(&xdr, res->fattr, res->server);
if (status == NFS4ERR_DELAY)
status = 0;
out:
return status;
}
......@@ -3296,12 +3299,14 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_ope
if (status)
goto out;
status = decode_open(&xdr, res);
if (status)
goto out;
status = decode_getfattr(&xdr, res->f_attr, res->server);
if (status)
goto out;
status = decode_getfh(&xdr, &res->fh);
if (status)
goto out;
status = decode_getfattr(&xdr, res->f_attr, res->server);
if (status == NFS4ERR_DELAY)
status = 0;
out:
return status;
}
......@@ -3347,6 +3352,8 @@ static int nfs4_xdr_dec_open_reclaim(struct rpc_rqst *rqstp, uint32_t *p, struct
if (status)
goto out;
status = decode_getfattr(&xdr, res->f_attr, res->server);
if (status == NFS4ERR_DELAY)
status = 0;
out:
return status;
}
......@@ -3371,6 +3378,8 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_
if (status)
goto out;
status = decode_getfattr(&xdr, res->fattr, res->server);
if (status == NFS4ERR_DELAY)
status = 0;
out:
return status;
}
......
......@@ -31,7 +31,6 @@ nfs_page_alloc(void)
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->wb_list);
init_waitqueue_head(&p->wb_wait);
}
return p;
}
......@@ -57,7 +56,7 @@ nfs_page_free(struct nfs_page *p)
* User should ensure it is safe to sleep in this function.
*/
struct nfs_page *
nfs_create_request(struct file *file, struct inode *inode,
nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
struct page *page,
unsigned int offset, unsigned int count)
{
......@@ -89,33 +88,38 @@ nfs_create_request(struct file *file, struct inode *inode,
req->wb_offset = offset;
req->wb_pgbase = offset;
req->wb_bytes = count;
req->wb_inode = inode;
atomic_set(&req->wb_count, 1);
server->rpc_ops->request_init(req, file);
req->wb_context = get_nfs_open_context(ctx);
return req;
}
/**
* nfs_unlock_request - Unlock request and wake up sleepers.
* @req:
*/
void nfs_unlock_request(struct nfs_page *req)
{
if (!NFS_WBACK_BUSY(req)) {
printk(KERN_ERR "NFS: Invalid unlock attempted\n");
BUG();
}
smp_mb__before_clear_bit();
clear_bit(PG_BUSY, &req->wb_flags);
smp_mb__after_clear_bit();
wake_up_all(&req->wb_context->waitq);
nfs_release_request(req);
}
/**
* nfs_clear_request - Free up all resources allocated to the request
* @req:
*
* Release all resources associated with a write request after it
* Release page resources associated with a write request after it
* has completed.
*/
void nfs_clear_request(struct nfs_page *req)
{
if (req->wb_state)
req->wb_state = NULL;
/* Release struct file or cached credential */
if (req->wb_file) {
fput(req->wb_file);
req->wb_file = NULL;
}
if (req->wb_cred) {
put_rpccred(req->wb_cred);
req->wb_cred = NULL;
}
if (req->wb_page) {
page_cache_release(req->wb_page);
req->wb_page = NULL;
......@@ -142,6 +146,7 @@ nfs_release_request(struct nfs_page *req)
/* Release struct file or cached credential */
nfs_clear_request(req);
put_nfs_open_context(req->wb_context);
nfs_page_free(req);
}
......@@ -185,12 +190,12 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
int
nfs_wait_on_request(struct nfs_page *req)
{
struct inode *inode = req->wb_inode;
struct inode *inode = req->wb_context->dentry->d_inode;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
if (!NFS_WBACK_BUSY(req))
return 0;
return nfs_wait_event(clnt, req->wb_wait, !NFS_WBACK_BUSY(req));
return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req));
}
/**
......@@ -215,7 +220,11 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
req = nfs_list_entry(head->next);
if (prev) {
if (req->wb_cred != prev->wb_cred)
if (req->wb_context->cred != prev->wb_context->cred)
break;
if (req->wb_context->lockowner != prev->wb_context->lockowner)
break;
if (req->wb_context->state != prev->wb_context->state)
break;
if (req->wb_index != (prev->wb_index + 1))
break;
......
......@@ -49,18 +49,6 @@
extern struct rpc_procinfo nfs_procedures[];
static struct rpc_cred *
nfs_cred(struct inode *inode, struct file *filp)
{
struct rpc_cred *cred = NULL;
if (filp)
cred = (struct rpc_cred *)filp->private_data;
if (!cred)
cred = NFS_I(inode)->mm_cred;
return cred;
}
/*
* Bare-bones access to getattr: this is for nfs_read_super.
*/
......@@ -99,14 +87,15 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* One function for each procedure in the NFS protocol.
*/
static int
nfs_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
int status;
dprintk("NFS call getattr\n");
fattr->valid = 0;
status = rpc_call(NFS_CLIENT(inode), NFSPROC_GETATTR,
NFS_FH(inode), fattr, 0);
status = rpc_call(server->client, NFSPROC_GETATTR,
fhandle, fattr, 0);
dprintk("NFS reply getattr\n");
return status;
}
......@@ -167,8 +156,7 @@ nfs_proc_readlink(struct inode *inode, struct page *page)
return status;
}
static int
nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
static int nfs_proc_read(struct nfs_read_data *rdata)
{
int flags = rdata->flags;
struct inode * inode = rdata->inode;
......@@ -177,15 +165,14 @@ nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
.rpc_proc = &nfs_procedures[NFSPROC_READ],
.rpc_argp = &rdata->args,
.rpc_resp = &rdata->res,
.rpc_cred = rdata->cred,
};
int status;
dprintk("NFS call read %d @ %Ld\n", rdata->args.count,
(long long) rdata->args.offset);
fattr->valid = 0;
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
if (status >= 0) {
nfs_refresh_inode(inode, fattr);
/* Emulate the eof flag, which isn't normally needed in NFSv2
......@@ -198,8 +185,7 @@ nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
return status;
}
static int
nfs_proc_write(struct nfs_write_data *wdata, struct file *filp)
static int nfs_proc_write(struct nfs_write_data *wdata)
{
int flags = wdata->flags;
struct inode * inode = wdata->inode;
......@@ -208,13 +194,13 @@ nfs_proc_write(struct nfs_write_data *wdata, struct file *filp)
.rpc_proc = &nfs_procedures[NFSPROC_WRITE],
.rpc_argp = &wdata->args,
.rpc_resp = &wdata->res,
.rpc_cred = wdata->cred,
};
int status;
dprintk("NFS call write %d @ %Ld\n", wdata->args.count,
(long long) wdata->args.offset);
fattr->valid = 0;
msg.rpc_cred = nfs_cred(inode, filp);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
if (status >= 0) {
nfs_refresh_inode(inode, fattr);
......@@ -621,27 +607,6 @@ nfs_proc_commit_setup(struct nfs_write_data *data, int how)
BUG();
}
/*
* Set up the nfspage struct with the right credentials
*/
static void
nfs_request_init(struct nfs_page *req, struct file *filp)
{
req->wb_cred = get_rpccred(nfs_cred(req->wb_inode, filp));
}
static int
nfs_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
{
if (req->wb_file != filp)
return 0;
if (req->wb_page != page)
return 0;
if (req->wb_cred != nfs_file_cred(filp))
return 0;
return 1;
}
static int
nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
{
......@@ -682,7 +647,5 @@ struct nfs_rpc_ops nfs_v2_clientops = {
.commit_setup = nfs_proc_commit_setup,
.file_open = nfs_open,
.file_release = nfs_release,
.request_init = nfs_request_init,
.request_compatible = nfs_request_compatible,
.lock = nfs_proc_lock,
};
......@@ -91,8 +91,8 @@ int nfs_return_empty_page(struct page *page)
/*
* Read a page synchronously.
*/
static int
nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
struct page *page)
{
unsigned int rsize = NFS_SERVER(inode)->rsize;
unsigned int count = PAGE_CACHE_SIZE;
......@@ -105,10 +105,11 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
memset(rdata, 0, sizeof(*rdata));
rdata->flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
rdata->cred = ctx->cred;
rdata->inode = inode;
INIT_LIST_HEAD(&rdata->pages);
rdata->args.fh = NFS_FH(inode);
rdata->args.lockowner = current->files;
rdata->args.context = ctx;
rdata->args.pages = &page;
rdata->args.pgbase = 0UL;
rdata->args.count = rsize;
......@@ -134,7 +135,7 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
rdata->args.count);
lock_kernel();
result = NFS_PROTO(inode)->read(rdata, file);
result = NFS_PROTO(inode)->read(rdata);
unlock_kernel();
/*
......@@ -169,8 +170,8 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
return result;
}
static int
nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
struct page *page)
{
LIST_HEAD(one_request);
struct nfs_page *new;
......@@ -179,7 +180,7 @@ nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
len = nfs_page_length(inode, page);
if (len == 0)
return nfs_return_empty_page(page);
new = nfs_create_request(file, inode, page, 0, len);
new = nfs_create_request(ctx, inode, page, 0, len);
if (IS_ERR(new)) {
unlock_page(page);
return PTR_ERR(new);
......@@ -202,8 +203,8 @@ static void nfs_readpage_release(struct nfs_page *req)
nfs_unlock_request(req);
dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
req->wb_inode->i_sb->s_id,
(long long)NFS_FILEID(req->wb_inode),
req->wb_context->dentry->d_inode->i_sb->s_id,
(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
req->wb_bytes,
(long long)req_offset(req));
}
......@@ -217,16 +218,15 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
struct inode *inode;
data->req = req;
data->inode = inode = req->wb_inode;
data->cred = req->wb_cred;
data->inode = inode = req->wb_context->dentry->d_inode;
data->cred = req->wb_context->cred;
data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req) + offset;
data->args.pgbase = req->wb_pgbase + offset;
data->args.pages = data->pagevec;
data->args.count = count;
data->args.lockowner = req->wb_lockowner;
data->args.state = req->wb_state;
data->args.context = req->wb_context;
data->res.fattr = &data->fattr;
data->res.count = count;
......@@ -396,7 +396,7 @@ nfs_pagein_list(struct list_head *head, int rpages)
while (!list_empty(head)) {
pages += nfs_coalesce_requests(head, &one_request, rpages);
req = nfs_list_entry(one_request.next);
error = nfs_pagein_one(&one_request, req->wb_inode);
error = nfs_pagein_one(&one_request, req->wb_context->dentry->d_inode);
if (error < 0)
break;
}
......@@ -500,9 +500,9 @@ void nfs_readpage_result(struct rpc_task *task)
* - The error flag is set for this page. This happens only when a
* previous async read operation failed.
*/
int
nfs_readpage(struct file *file, struct page *page)
int nfs_readpage(struct file *file, struct page *page)
{
struct nfs_open_context *ctx;
struct inode *inode = page->mapping->host;
int error;
......@@ -519,25 +519,33 @@ nfs_readpage(struct file *file, struct page *page)
if (error)
goto out_error;
if (file == NULL) {
ctx = nfs_find_open_context(inode, FMODE_READ);
if (ctx == NULL)
return -EBADF;
} else
ctx = get_nfs_open_context((struct nfs_open_context *)
file->private_data);
if (!IS_SYNC(inode)) {
error = nfs_readpage_async(file, inode, page);
error = nfs_readpage_async(ctx, inode, page);
goto out;
}
error = nfs_readpage_sync(file, inode, page);
error = nfs_readpage_sync(ctx, inode, page);
if (error < 0 && IS_SWAPFILE(inode))
printk("Aiee.. nfs swap-in of page failed!\n");
out:
put_nfs_open_context(ctx);
return error;
out_error:
unlock_page(page);
goto out;
return error;
}
struct nfs_readdesc {
struct list_head *head;
struct file *filp;
struct nfs_open_context *ctx;
};
static int
......@@ -552,7 +560,7 @@ readpage_async_filler(void *data, struct page *page)
len = nfs_page_length(inode, page);
if (len == 0)
return nfs_return_empty_page(page);
new = nfs_create_request(desc->filp, inode, page, 0, len);
new = nfs_create_request(desc->ctx, inode, page, 0, len);
if (IS_ERR(new)) {
SetPageError(page);
unlock_page(page);
......@@ -565,13 +573,11 @@ readpage_async_filler(void *data, struct page *page)
return 0;
}
int
nfs_readpages(struct file *filp, struct address_space *mapping,
int nfs_readpages(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages)
{
LIST_HEAD(head);
struct nfs_readdesc desc = {
.filp = filp,
.head = &head,
};
struct inode *inode = mapping->host;
......@@ -583,12 +589,20 @@ nfs_readpages(struct file *filp, struct address_space *mapping,
(long long)NFS_FILEID(inode),
nr_pages);
if (filp == NULL) {
desc.ctx = nfs_find_open_context(inode, FMODE_READ);
if (desc.ctx == NULL)
return -EBADF;
} else
desc.ctx = get_nfs_open_context((struct nfs_open_context *)
filp->private_data);
ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
if (!list_empty(&head)) {
int err = nfs_pagein_list(&head, server->rpages);
if (!ret)
ret = err;
}
put_nfs_open_context(desc.ctx);
return ret;
}
......
This diff is collapsed.
......@@ -83,6 +83,20 @@ struct nfs_access_entry {
int mask;
};
struct nfs4_state;
struct nfs_open_context {
atomic_t count;
struct dentry *dentry;
struct rpc_cred *cred;
struct nfs4_state *state;
fl_owner_t lockowner;
int mode;
int error;
struct list_head list;
wait_queue_head_t waitq;
};
/*
* nfs fs inode data in memory
*/
......@@ -156,8 +170,8 @@ struct nfs_inode {
ncommit,
npages;
/* Credentials for shared mmap */
struct rpc_cred *mm_cred;
/* Open contexts for shared mmap writes */
struct list_head open_files;
wait_queue_head_t nfs_i_wait;
......@@ -268,7 +282,6 @@ extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
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 *);
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 *);
......@@ -278,6 +291,12 @@ extern void nfs_end_attr_update(struct inode *);
extern void nfs_begin_data_update(struct inode *);
extern void nfs_end_data_update(struct inode *);
extern void nfs_end_data_update_defer(struct inode *);
extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred);
extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
extern void put_nfs_open_context(struct nfs_open_context *ctx);
extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode);
extern void nfs_file_clear_open_context(struct file *filp);
/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
extern u32 root_nfs_parse_addr(char *name); /*__init*/
......@@ -289,16 +308,15 @@ extern struct inode_operations nfs_file_inode_operations;
extern struct file_operations nfs_file_operations;
extern struct address_space_operations nfs_file_aops;
static __inline__ struct rpc_cred *
nfs_file_cred(struct file *file)
static inline struct rpc_cred *nfs_file_cred(struct file *file)
{
struct rpc_cred *cred = NULL;
if (file)
cred = (struct rpc_cred *)file->private_data;
#ifdef RPC_DEBUG
BUG_ON(cred && cred->cr_magic != RPCAUTH_CRED_MAGIC);
#endif
return cred;
if (file != NULL) {
struct nfs_open_context *ctx;
ctx = (struct nfs_open_context*)file->private_data;
return ctx->cred;
}
return NULL;
}
/*
......@@ -507,8 +525,6 @@ struct idmap;
enum nfs4_client_state {
NFS4CLNT_OK = 0,
NFS4CLNT_NEW,
NFS4CLNT_SETUP_STATE,
};
/*
......@@ -520,7 +536,6 @@ struct nfs4_client {
u64 cl_clientid; /* constant */
nfs4_verifier cl_confirm;
unsigned long cl_state;
long cl_generation;
u32 cl_lockowner_id;
......@@ -573,9 +588,7 @@ struct nfs4_state_owner {
u32 so_id; /* 32-bit identifier, unique */
struct semaphore so_sema;
u32 so_seqid; /* protected by so_sema */
unsigned int so_flags; /* protected by so_sema */
atomic_t so_count;
long so_generation;
struct rpc_cred *so_cred; /* Associated cred */
struct list_head so_states;
......@@ -596,7 +609,8 @@ struct nfs4_state_owner {
struct nfs4_lock_state {
struct list_head ls_locks; /* Other lock stateids */
fl_owner_t ls_owner; /* POSIX lock owner */
struct nfs4_state * ls_parent; /* Parent nfs4_state */
#define NFS_LOCK_INITIALIZED 1
int ls_flags;
u32 ls_seqid;
u32 ls_id;
nfs4_stateid ls_stateid;
......@@ -629,6 +643,11 @@ struct nfs4_state {
};
struct nfs4_exception {
long timeout;
int retry;
};
extern struct dentry_operations nfs4_dentry_operations;
extern struct inode_operations nfs4_dir_inode_operations;
......@@ -639,10 +658,12 @@ extern int nfs4_open_reclaim(struct nfs4_state_owner *, struct nfs4_state *);
extern int nfs4_proc_async_renew(struct nfs4_client *);
extern int nfs4_proc_renew(struct nfs4_client *);
extern int nfs4_do_close(struct inode *, struct nfs4_state *);
int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode);
extern int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode);
extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *);
extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
extern int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request);
/* nfs4renewd.c */
extern void nfs4_schedule_state_renewal(struct nfs4_client *);
......@@ -654,6 +675,7 @@ extern void init_nfsv4_state(struct nfs_server *);
extern void destroy_nfsv4_state(struct nfs_server *);
extern struct nfs4_client *nfs4_get_client(struct in_addr *);
extern void nfs4_put_client(struct nfs4_client *clp);
extern int nfs4_init_client(struct nfs4_client *clp);
extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
......@@ -663,14 +685,13 @@ extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct nfs4_state *, mode_t);
extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
extern int nfs4_handle_error(struct nfs_server *, int);
extern void nfs4_schedule_state_recovery(struct nfs4_client *);
extern struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t);
extern struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t);
extern struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t);
extern void nfs4_put_lock_state(struct nfs4_lock_state *state);
extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
extern void nfs4_notify_setlk(struct inode *, struct file_lock *, struct nfs4_lock_state *);
extern void nfs4_notify_unlck(struct inode *, struct file_lock *, struct nfs4_lock_state *);
extern void nfs4_notify_setlk(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
extern void nfs4_notify_unlck(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
......@@ -681,6 +702,7 @@ struct nfs4_mount_data;
#define destroy_nfsv4_state(server) do { } while (0)
#define nfs4_put_state_owner(inode, owner) do { } while (0)
#define nfs4_put_open_state(state) do { } while (0)
#define nfs4_close_state(a, b) do { } while (0)
#define nfs4_renewd_prepare_shutdown(server) do { } while (0)
#endif
......
......@@ -29,14 +29,9 @@
struct nfs_page {
struct list_head wb_list, /* Defines state of page: */
*wb_list_head; /* read/write/commit */
struct file *wb_file;
fl_owner_t wb_lockowner;
struct inode *wb_inode;
struct rpc_cred *wb_cred;
struct nfs4_state *wb_state;
struct page *wb_page; /* page to read in/write out */
struct nfs_open_context *wb_context; /* File state context info */
atomic_t wb_complete; /* i/os we're waiting for */
wait_queue_head_t wb_wait; /* wait queue */
unsigned long wb_index; /* Offset >> PAGE_CACHE_SHIFT */
unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */
wb_pgbase, /* Start of page data */
......@@ -50,9 +45,11 @@ struct nfs_page {
#define NFS_NEED_COMMIT(req) (test_bit(PG_NEED_COMMIT,&(req)->wb_flags))
#define NFS_NEED_RESCHED(req) (test_bit(PG_NEED_RESCHED,&(req)->wb_flags))
extern struct nfs_page *nfs_create_request(struct file *, struct inode *,
struct page *,
unsigned int, unsigned int);
extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
struct inode *inode,
struct page *page,
unsigned int offset,
unsigned int count);
extern void nfs_clear_request(struct nfs_page *req);
extern void nfs_release_request(struct nfs_page *req);
......@@ -64,6 +61,7 @@ extern int nfs_scan_list(struct list_head *, struct list_head *,
extern int nfs_coalesce_requests(struct list_head *, struct list_head *,
unsigned int);
extern int nfs_wait_on_request(struct nfs_page *);
extern void nfs_unlock_request(struct nfs_page *req);
/*
* Lock the page of an asynchronous request without incrementing the wb_count
......@@ -88,19 +86,6 @@ nfs_lock_request(struct nfs_page *req)
return 1;
}
static inline void
nfs_unlock_request(struct nfs_page *req)
{
if (!NFS_WBACK_BUSY(req)) {
printk(KERN_ERR "NFS: Invalid unlock attempted\n");
BUG();
}
smp_mb__before_clear_bit();
clear_bit(PG_BUSY, &req->wb_flags);
smp_mb__after_clear_bit();
wake_up_all(&req->wb_wait);
nfs_release_request(req);
}
/**
* nfs_list_remove_request - Remove a request from its wb_list
......
......@@ -235,8 +235,7 @@ struct nfs_lockres {
struct nfs_readargs {
struct nfs_fh * fh;
fl_owner_t lockowner;
struct nfs4_state * state;
struct nfs_open_context *context;
__u64 offset;
__u32 count;
unsigned int pgbase;
......@@ -259,8 +258,7 @@ struct nfs_readres {
struct nfs_writeargs {
struct nfs_fh * fh;
fl_owner_t lockowner;
struct nfs4_state * state;
struct nfs_open_context *context;
__u64 offset;
__u32 count;
enum nfs3_stable_how stable;
......@@ -597,13 +595,15 @@ struct nfs4_rename_res {
};
struct nfs4_setclientid {
nfs4_verifier sc_verifier; /* request */
char * sc_name; /* request */
const nfs4_verifier * sc_verifier; /* request */
unsigned int sc_name_len;
char sc_name[32]; /* request */
u32 sc_prog; /* request */
unsigned int sc_netid_len;
char sc_netid[4]; /* request */
unsigned int sc_uaddr_len;
char sc_uaddr[24]; /* request */
u32 sc_cb_ident; /* request */
struct nfs4_client * sc_state; /* response */
};
struct nfs4_statfs_arg {
......@@ -669,16 +669,17 @@ struct nfs_rpc_ops {
int (*getroot) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsinfo *);
int (*getattr) (struct inode *, struct nfs_fattr *);
int (*getattr) (struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *);
int (*setattr) (struct dentry *, struct nfs_fattr *,
struct iattr *);
int (*lookup) (struct inode *, struct qstr *,
struct nfs_fh *, struct nfs_fattr *);
int (*access) (struct inode *, struct nfs_access_entry *);
int (*readlink)(struct inode *, struct page *);
int (*read) (struct nfs_read_data *, struct file *);
int (*write) (struct nfs_write_data *, struct file *);
int (*commit) (struct nfs_write_data *, struct file *);
int (*read) (struct nfs_read_data *);
int (*write) (struct nfs_write_data *);
int (*commit) (struct nfs_write_data *);
struct inode * (*create) (struct inode *, struct qstr *,
struct iattr *, int);
int (*remove) (struct inode *, struct qstr *);
......@@ -710,8 +711,6 @@ struct nfs_rpc_ops {
void (*commit_setup) (struct nfs_write_data *, int how);
int (*file_open) (struct inode *, struct file *);
int (*file_release) (struct inode *, struct file *);
void (*request_init)(struct nfs_page *, struct file *);
int (*request_compatible)(struct nfs_page *, struct file *, struct page *);
int (*lock)(struct file *, int, struct file_lock *);
};
......
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