]> git.hungrycats.org Git - linux/commitdiff
NFSv2/v3/v4: Place NFS nfs_page shared data into a single structure
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Mon, 23 Aug 2004 15:19:03 +0000 (11:19 -0400)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Mon, 23 Aug 2004 15:19:03 +0000 (11:19 -0400)
   that hangs off filp->private_data. As a side effect, this also
   cleans up the NFSv4 private file state info.

Signed-off-by: Trond Myklebust <trond.myklebust@fys.uio.no>
13 files changed:
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/pagelist.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/write.c
include/linux/nfs_fs.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h

index e4e228ea968a2f9720830ab1ca0764ae3a7454e5..080e3e7b6c07fcbc9c939efb628b3cd8fe57a692 100644 (file)
@@ -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,11 @@ 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,
+                       .lockowner      = ctx->lockowner,
+                       .state          = ctx->state,
                },
                .res            = {
                        .fattr          = &rdata.fattr,
@@ -151,7 +153,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 +185,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 +195,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 +218,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 +241,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 +249,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 +259,11 @@ 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,
+                       .lockowner      = ctx->lockowner,
+                       .state          = ctx->state,
                },
                .res            = {
                        .fattr          = &wdata.fattr,
@@ -290,7 +294,7 @@ retry:
                        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 +329,7 @@ retry:
                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 +353,7 @@ sync_retry:
  * 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 +362,7 @@ sync_retry:
  * 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 +385,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 +417,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 +427,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 +476,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 +509,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 +549,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 +598,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)
index 1b0c4ae4556ed4c772b8d1d89fe615c594fd9bef..0bd5913f690bad28169b16b5f329bc2a6d691722 100644 (file)
@@ -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;
index 98f04ecec8594a03ba86b838bd8c50873629cde1..6bc28939de68dc8faf3ab2c86b71a842ed016fc4 100644 (file)
@@ -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;
 }
 
@@ -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);
 }
 
 
@@ -1717,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;
 }
@@ -1737,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;
index 0bf9af7678b777a404e4f75afc4c15c736072861..bbceb6d3f2ce4b7c13805f923682f0b82811bf01 100644 (file)
@@ -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.
  */
@@ -233,8 +221,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 +230,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 +244,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 +253,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 +267,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 +275,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 +825,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 +864,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,
 };
index 257f3c6597d185e7d73c974000994fee1a9ac299..7b92c071101555c5e5df73e544af13c3579b3181 100644 (file)
@@ -975,7 +975,7 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page)
        return err;
 }
 
-static int _nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int _nfs4_proc_read(struct nfs_read_data *rdata)
 {
        int flags = rdata->flags;
        struct inode *inode = rdata->inode;
@@ -985,6 +985,7 @@ static int _nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_READ],
                .rpc_argp       = &rdata->args,
                .rpc_resp       = &rdata->res,
+               .rpc_cred       = rdata->cred,
        };
        unsigned long timestamp = jiffies;
        int status;
@@ -992,19 +993,6 @@ static int _nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
        dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
                        (long long) rdata->args.offset);
 
-       /*
-        * Try first to use O_RDONLY, then O_RDWR stateid.
-        */
-       if (filp) {
-               struct nfs4_state *state;
-               state = (struct nfs4_state *)filp->private_data;
-               rdata->args.state = state;
-               msg.rpc_cred = state->owner->so_cred;
-       } else {
-               rdata->args.state = NULL;
-               msg.rpc_cred = NFS_I(inode)->mm_cred;
-       }
-
        fattr->valid = 0;
        status = rpc_call_sync(server->client, &msg, flags);
        if (!status)
@@ -1013,19 +1001,19 @@ static int _nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
        return status;
 }
 
-static int nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int nfs4_proc_read(struct nfs_read_data *rdata)
 {
        struct nfs4_exception exception = { };
        int err;
        do {
                err = nfs4_handle_exception(NFS_SERVER(rdata->inode),
-                               _nfs4_proc_read(rdata, filp),
+                               _nfs4_proc_read(rdata),
                                &exception);
        } while (exception.retry);
        return err;
 }
 
-static int _nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int _nfs4_proc_write(struct nfs_write_data *wdata)
 {
        int rpcflags = wdata->flags;
        struct inode *inode = wdata->inode;
@@ -1035,44 +1023,32 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_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);
 
-       /*
-        * Try first to use O_WRONLY, then O_RDWR stateid.
-        */
-       if (filp) {
-               struct nfs4_state *state;
-               state = (struct nfs4_state *)filp->private_data;
-               wdata->args.state = state;
-               msg.rpc_cred = state->owner->so_cred;
-       } else {
-               wdata->args.state = NULL;
-               msg.rpc_cred = NFS_I(inode)->mm_cred;
-       }
-
        fattr->valid = 0;
        status = rpc_call_sync(server->client, &msg, rpcflags);
        dprintk("NFS reply write: %d\n", status);
        return status;
 }
 
-static int nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int nfs4_proc_write(struct nfs_write_data *wdata)
 {
        struct nfs4_exception exception = { };
        int err;
        do {
                err = nfs4_handle_exception(NFS_SERVER(wdata->inode),
-                               _nfs4_proc_write(wdata, filp),
+                               _nfs4_proc_write(wdata),
                                &exception);
        } while (exception.retry);
        return err;
 }
 
-static int _nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp)
+static int _nfs4_proc_commit(struct nfs_write_data *cdata)
 {
        struct inode *inode = cdata->inode;
        struct nfs_fattr *fattr = cdata->res.fattr;
@@ -1081,33 +1057,26 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp)
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_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);
 
-       /*
-        * Try first to use O_WRONLY, then O_RDWR stateid.
-        */
-       if (filp)
-               msg.rpc_cred = ((struct nfs4_state *)filp->private_data)->owner->so_cred;
-       else
-               msg.rpc_cred = NFS_I(inode)->mm_cred;
-
        fattr->valid = 0;
        status = rpc_call_sync(server->client, &msg, 0);
        dprintk("NFS reply commit: %d\n", status);
        return status;
 }
 
-static int nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp)
+static int nfs4_proc_commit(struct nfs_write_data *cdata)
 {
        struct nfs4_exception exception = { };
        int err;
        do {
                err = nfs4_handle_exception(NFS_SERVER(cdata->inode),
-                               _nfs4_proc_commit(cdata, filp),
+                               _nfs4_proc_commit(cdata),
                                &exception);
        } while (exception.retry);
        return err;
@@ -1797,8 +1766,10 @@ static int
 nfs4_proc_file_open(struct inode *inode, struct file *filp)
 {
        struct dentry *dentry = filp->f_dentry;
-       struct nfs4_state *state;
+       struct nfs_open_context *ctx;
+       struct nfs4_state *state = NULL;
        struct rpc_cred *cred;
+       int status = -ENOMEM;
 
        dprintk("nfs4_proc_file_open: starting on (%.*s/%.*s)\n",
                               (int)dentry->d_parent->d_name.len,
@@ -1808,21 +1779,28 @@ nfs4_proc_file_open(struct inode *inode, struct file *filp)
 
        /* Find our open stateid */
        cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
-       state = nfs4_find_state(inode, cred, filp->f_mode);
+       if (unlikely(cred == NULL))
+               return -ENOMEM;
+       ctx = alloc_nfs_open_context(dentry, cred);
        put_rpccred(cred);
-       if (state == NULL) {
-               printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
-               return -EIO; /* ERACE actually */
-       }
+       if (unlikely(ctx == NULL))
+               return -ENOMEM;
+       status = -EIO; /* ERACE actually */
+       state = nfs4_find_state(inode, cred, filp->f_mode);
+       if (unlikely(state == NULL))
+               goto no_state;
+       ctx->state = state;
        nfs4_close_state(state, filp->f_mode);
-       if (filp->f_mode & FMODE_WRITE) {
-               lock_kernel();
-               nfs_set_mmcred(inode, state->owner->so_cred);
+       ctx->mode = filp->f_mode;
+       nfs_file_set_open_context(filp, ctx);
+       put_nfs_open_context(ctx);
+       if (filp->f_mode & FMODE_WRITE)
                nfs_begin_data_update(inode);
-               unlock_kernel();
-       }
-       filp->private_data = state;
        return 0;
+no_state:
+       printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
+       put_nfs_open_context(ctx);
+       return status;
 }
 
 /*
@@ -1831,37 +1809,12 @@ nfs4_proc_file_open(struct inode *inode, struct file *filp)
 static int
 nfs4_proc_file_release(struct inode *inode, struct file *filp)
 {
-       struct nfs4_state *state = (struct nfs4_state *)filp->private_data;
-
-       if (state)
-               nfs4_close_state(state, filp->f_mode);
-       if (filp->f_mode & FMODE_WRITE) {
-               lock_kernel();
+       if (filp->f_mode & FMODE_WRITE)
                nfs_end_data_update(inode);
-               unlock_kernel();
-       }
+       nfs_file_clear_open_context(filp);
        return 0;
 }
 
-/*
- * Set up the nfspage struct with the right state info and credentials
- */
-static void
-nfs4_request_init(struct nfs_page *req, struct file *filp)
-{
-       struct nfs4_state *state;
-
-       if (!filp) {
-               req->wb_cred = get_rpccred(NFS_I(req->wb_inode)->mm_cred);
-               req->wb_state = NULL;
-               return;
-       }
-       state = (struct nfs4_state *)filp->private_data;
-       req->wb_state = state;
-       req->wb_cred = get_rpccred(state->owner->so_cred);
-       req->wb_lockowner = current->files;
-}
-
 static int
 nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
 {
@@ -1974,28 +1927,6 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
        return nfs4_map_errors(ret);
 }
 
-
-static int
-nfs4_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
-{
-       struct nfs4_state *state = NULL;
-       struct rpc_cred *cred = NULL;
-
-       if (req->wb_file != filp)
-               return 0;
-       if (req->wb_page != page)
-               return 0;
-       state = (struct nfs4_state *)filp->private_data;
-       if (req->wb_state != state)
-               return 0;
-       if (req->wb_lockowner != current->files)
-               return 0;
-       cred = state->owner->so_cred;
-       if (req->wb_cred != cred)
-               return 0;
-       return 1;
-}
-
 int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
 {
        static nfs4_verifier sc_verifier;
@@ -2353,13 +2284,14 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
 static int
 nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
 {
+       struct nfs_open_context *ctx;
        struct nfs4_state *state;
        unsigned long timeout = NFS4_LOCK_MINTIMEOUT;
        int status;
 
        /* verify open state */
-       state = (struct nfs4_state *)filp->private_data;
-       BUG_ON(!state);
+       ctx = (struct nfs_open_context *)filp->private_data;
+       state = ctx->state;
 
        if (request->fl_start < 0 || request->fl_end < 0)
                return -EINVAL;
@@ -2419,8 +2351,6 @@ struct nfs_rpc_ops        nfs_v4_clientops = {
        .commit_setup   = nfs4_proc_commit_setup,
        .file_open      = nfs4_proc_file_open,
        .file_release   = nfs4_proc_file_release,
-       .request_init   = nfs4_request_init,
-       .request_compatible = nfs4_request_compatible,
        .lock           = nfs4_proc_lock,
 };
 
index 60a52170a07f13e27a3cbb4572a58b5df3984e18..0b67691034fc32a8d85e90b73e5263c793c970cb 100644 (file)
@@ -728,7 +728,7 @@ static int nfs4_reclaim_locks(struct nfs4_state *state)
        for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
                if (!(fl->fl_flags & FL_POSIX))
                        continue;
-               if ((struct nfs4_state *)fl->fl_file->private_data != state)
+               if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
                        continue;
                status = nfs4_lock_reclaim(state, fl);
                if (status >= 0)
index dc496624345f290d206829a695ff589c012fe7b0..4f1ba723848de91e95d51547a30ff40141cb1a36 100644 (file)
@@ -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;
index 279ddad6ee4edf037e40d7046a06e4638d3de96f..2e2fff50f25b13e6f0322c8ef340c36618eb1e5f 100644 (file)
 
 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.
  */
@@ -167,8 +155,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 +164,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 +184,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 +193,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 +606,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 +646,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,
 };
index 2d32aba43fbbefb290ed10b34eb4a098a89e8d26..54df1a48843d1b3e62d2feeb8508003d2bf297d0 100644 (file)
@@ -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,12 @@ 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.lockowner = ctx->lockowner;
+       rdata->args.state = ctx->state;
        rdata->args.pages = &page;
        rdata->args.pgbase = 0UL;
        rdata->args.count = rsize;
@@ -134,7 +136,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 +171,8 @@ io_error:
        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 +181,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 +204,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 +219,16 @@ 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.lockowner = req->wb_context->lockowner;
+       data->args.state  = req->wb_context->state;
 
        data->res.fattr   = &data->fattr;
        data->res.count   = count;
@@ -396,7 +398,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 +502,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 +521,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 +562,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 +575,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 +591,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;
 }
 
index fe99d21dd3dda00b9557f64949fae87761a8fb2d..c956b6f9b1d0fb6e58ec3baa8bef3bebd3f0e03d 100644 (file)
@@ -71,7 +71,8 @@
 /*
  * Local function declarations
  */
-static struct nfs_page * nfs_update_request(struct file*, struct inode *,
+static struct nfs_page * nfs_update_request(struct nfs_open_context*,
+                                           struct inode *,
                                            struct page *,
                                            unsigned int, unsigned int);
 static void nfs_writeback_done_partial(struct nfs_write_data *, int);
@@ -173,7 +174,7 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int
  * Write a page synchronously.
  * Offset is the data offset within the page.
  */
-static int nfs_writepage_sync(struct file *file, struct inode *inode,
+static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
                struct page *page, unsigned int offset, unsigned int count,
                int how)
 {
@@ -187,9 +188,11 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
 
        memset(wdata, 0, sizeof(*wdata));
        wdata->flags = how;
+       wdata->cred = ctx->cred;
        wdata->inode = inode;
        wdata->args.fh = NFS_FH(inode);
-       wdata->args.lockowner = current->files;
+       wdata->args.lockowner = ctx->lockowner;
+       wdata->args.state = ctx->state;
        wdata->args.pages = &page;
        wdata->args.stable = NFS_FILE_SYNC;
        wdata->args.pgbase = offset;
@@ -208,7 +211,7 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
                        wdata->args.count = count;
                wdata->args.offset = page_offset(page) + wdata->args.pgbase;
 
-               result = NFS_PROTO(inode)->write(wdata, file);
+               result = NFS_PROTO(inode)->write(wdata);
 
                if (result < 0) {
                        /* Must mark the page invalid after I/O error */
@@ -234,20 +237,19 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
 
 io_error:
        nfs_end_data_update_defer(inode);
-       if (wdata->cred)
-               put_rpccred(wdata->cred);
 
        kfree(wdata);
        return written ? written : result;
 }
 
-static int nfs_writepage_async(struct file *file, struct inode *inode,
-               struct page *page, unsigned int offset, unsigned int count)
+static int nfs_writepage_async(struct nfs_open_context *ctx,
+               struct inode *inode, struct page *page,
+               unsigned int offset, unsigned int count)
 {
        struct nfs_page *req;
        int             status;
 
-       req = nfs_update_request(file, inode, page, offset, count);
+       req = nfs_update_request(ctx, inode, page, offset, count);
        status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
        if (status < 0)
                goto out;
@@ -274,6 +276,7 @@ static int wb_priority(struct writeback_control *wbc)
  */
 int nfs_writepage(struct page *page, struct writeback_control *wbc)
 {
+       struct nfs_open_context *ctx;
        struct inode *inode = page->mapping->host;
        unsigned long end_index;
        unsigned offset = PAGE_CACHE_SIZE;
@@ -308,16 +311,21 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
        if (page->index >= end_index+1 || !offset)
                goto out;
 do_it:
+       ctx = nfs_find_open_context(inode, FMODE_WRITE);
+       if (ctx == NULL) {
+               err = -EBADF;
+               goto out;
+       }
        lock_kernel();
        if (!IS_SYNC(inode) && inode_referenced) {
-               err = nfs_writepage_async(NULL, inode, page, 0, offset);
+               err = nfs_writepage_async(ctx, inode, page, 0, offset);
                if (err >= 0) {
                        err = 0;
                        if (wbc->for_reclaim)
                                nfs_flush_inode(inode, 0, 0, FLUSH_STABLE);
                }
        } else {
-               err = nfs_writepage_sync(NULL, inode, page, 0,
+               err = nfs_writepage_sync(ctx, inode, page, 0,
                                                offset, priority);
                if (err >= 0) {
                        if (err != offset)
@@ -326,6 +334,7 @@ do_it:
                }
        }
        unlock_kernel();
+       put_nfs_open_context(ctx);
 out:
        unlock_page(page);
        if (inode_referenced)
@@ -396,10 +405,9 @@ nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
 /*
  * Insert a write request into an inode
  */
-static void
-nfs_inode_remove_request(struct nfs_page *req)
+static void nfs_inode_remove_request(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_inode;
+       struct inode *inode = req->wb_context->dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
 
        BUG_ON (!NFS_WBACK_BUSY(req));
@@ -450,7 +458,7 @@ nfs_find_request(struct inode *inode, unsigned long index)
 static void
 nfs_mark_request_dirty(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_inode;
+       struct inode *inode = req->wb_context->dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
 
        spin_lock(&nfsi->req_lock);
@@ -467,7 +475,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
 static inline int
 nfs_dirty_request(struct nfs_page *req)
 {
-       struct nfs_inode *nfsi = NFS_I(req->wb_inode);
+       struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
        return !list_empty(&req->wb_list) && req->wb_list_head == &nfsi->dirty;
 }
 
@@ -478,7 +486,7 @@ nfs_dirty_request(struct nfs_page *req)
 static void
 nfs_mark_request_commit(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_inode;
+       struct inode *inode = req->wb_context->dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
 
        spin_lock(&nfsi->req_lock);
@@ -619,9 +627,9 @@ static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr)
  *
  * Note: Should always be called with the Page Lock held!
  */
-static struct nfs_page *
-nfs_update_request(struct file* file, struct inode *inode, struct page *page,
-                  unsigned int offset, unsigned int bytes)
+static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
+               struct inode *inode, struct page *page,
+               unsigned int offset, unsigned int bytes)
 {
        struct nfs_server *server = NFS_SERVER(inode);
        struct nfs_inode *nfsi = NFS_I(inode);
@@ -669,13 +677,9 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
                }
                spin_unlock(&nfsi->req_lock);
 
-               new = nfs_create_request(file, inode, page, offset, bytes);
+               new = nfs_create_request(ctx, inode, page, offset, bytes);
                if (IS_ERR(new))
                        return new;
-               if (file) {
-                       new->wb_file = file;
-                       get_file(file);
-               }
        }
 
        /* We have a request for our page.
@@ -685,7 +689,7 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
         * request.
         */
        rqend = req->wb_offset + req->wb_bytes;
-       if (req->wb_file != file
+       if (req->wb_context != ctx
            || req->wb_page != page
            || !nfs_dirty_request(req)
            || offset > rqend || end < req->wb_offset) {
@@ -706,9 +710,9 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
        return req;
 }
 
-int
-nfs_flush_incompatible(struct file *file, struct page *page)
+int nfs_flush_incompatible(struct file *file, struct page *page)
 {
+       struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
        struct inode    *inode = page->mapping->host;
        struct nfs_page *req;
        int             status = 0;
@@ -722,7 +726,7 @@ nfs_flush_incompatible(struct file *file, struct page *page)
         */
        req = nfs_find_request(inode, page->index);
        if (req) {
-               if (!NFS_PROTO(inode)->request_compatible(req, file, page))
+               if (req->wb_page != page || ctx != req->wb_context)
                        status = nfs_wb_page(inode, page);
                nfs_release_request(req);
        }
@@ -738,6 +742,7 @@ nfs_flush_incompatible(struct file *file, struct page *page)
 int nfs_updatepage(struct file *file, struct page *page,
                unsigned int offset, unsigned int count)
 {
+       struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
        struct dentry   *dentry = file->f_dentry;
        struct inode    *inode = page->mapping->host;
        struct nfs_page *req;
@@ -748,7 +753,7 @@ int nfs_updatepage(struct file *file, struct page *page,
                count, (long long)(page_offset(page) +offset));
 
        if (IS_SYNC(inode)) {
-               status = nfs_writepage_sync(file, inode, page, offset, count, 0);
+               status = nfs_writepage_sync(ctx, inode, page, offset, count, 0);
                if (status > 0) {
                        if (offset == 0 && status == PAGE_CACHE_SIZE)
                                SetPageUptodate(page);
@@ -785,7 +790,7 @@ int nfs_updatepage(struct file *file, struct page *page,
         * it out now.
         */
        do {
-               req = nfs_update_request(file, inode, page, offset, count);
+               req = nfs_update_request(ctx, inode, page, offset, count);
                status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
                if (status != -EBUSY)
                        break;
@@ -861,16 +866,16 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
         * NB: take care not to mess about with data->commit et al. */
 
        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.lockowner = req->wb_context->lockowner;
+       data->args.state  = req->wb_context->state;
 
        data->res.fattr   = &data->fattr;
        data->res.count   = count;
@@ -1030,7 +1035,7 @@ nfs_flush_list(struct list_head *head, int wpages, int how)
        while (!list_empty(head)) {
                pages += nfs_coalesce_requests(head, &one_request, wpages);
                req = nfs_list_entry(one_request.next);
-               error = nfs_flush_one(&one_request, req->wb_inode, how);
+               error = nfs_flush_one(&one_request, req->wb_context->dentry->d_inode, how);
                if (error < 0)
                        break;
        }
@@ -1055,16 +1060,15 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
        struct page             *page = req->wb_page;
 
        dprintk("NFS: write (%s/%Ld %d@%Ld)",
-               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));
 
        if (status < 0) {
                ClearPageUptodate(page);
                SetPageError(page);
-               if (req->wb_file)
-                       req->wb_file->f_error = status;
+               req->wb_context->error = status;
                dprintk(", error = %d\n", status);
        } else {
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
@@ -1105,16 +1109,15 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
                page = req->wb_page;
 
                dprintk("NFS: write (%s/%Ld %d@%Ld)",
-                       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));
 
                if (status < 0) {
                        ClearPageUptodate(page);
                        SetPageError(page);
-                       if (req->wb_file)
-                               req->wb_file->f_error = status;
+                       req->wb_context->error = status;
                        end_page_writeback(page);
                        nfs_inode_remove_request(req);
                        dprintk(", error = %d\n", status);
@@ -1233,7 +1236,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
        list_splice_init(head, &data->pages);
        first = nfs_list_entry(data->pages.next);
        last = nfs_list_entry(data->pages.prev);
-       inode = first->wb_inode;
+       inode = first->wb_context->dentry->d_inode;
 
        /*
         * Determine the offset range of requests in the COMMIT call.
@@ -1247,7 +1250,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
                len = 0;
 
        data->inode       = inode;
-       data->cred        = first->wb_cred;
+       data->cred        = first->wb_context->cred;
 
        data->args.fh     = NFS_FH(data->inode);
        data->args.offset = start;
@@ -1314,13 +1317,12 @@ nfs_commit_done(struct rpc_task *task)
                nfs_list_remove_request(req);
 
                dprintk("NFS: commit (%s/%Ld %d@%Ld)",
-                       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));
                if (task->tk_status < 0) {
-                       if (req->wb_file)
-                               req->wb_file->f_error = task->tk_status;
+                       req->wb_context->error = task->tk_status;
                        nfs_inode_remove_request(req);
                        dprintk(", error = %d\n", task->tk_status);
                        goto next;
index f72279a6a36c22a5684c7417a74d40874031af77..0b9fb290b1b24b50219f159961eedd762f2c197f 100644 (file)
@@ -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;
 }
 
 /*
@@ -684,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
 
index 12a6758cc8591126ff793cbb30b51b557bd11daf..39e4895bcdb421b54ff147abe68580ffb0a598a8 100644 (file)
 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
index 427ec6708d20dead6f47d8b6962edfd79868d91f..340ff5c8f3df0f06faf61c9eb846f070f576a24a 100644 (file)
@@ -678,9 +678,9 @@ struct nfs_rpc_ops {
                            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 *);
@@ -712,8 +712,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 *);
 };