diff -u --recursive --new-file linux-2.5.3-cto/fs/nfs/pagelist.c linux-2.5.3-fix_put/fs/nfs/pagelist.c --- linux-2.5.3-cto/fs/nfs/pagelist.c Mon Jan 7 21:55:16 2002 +++ linux-2.5.3-fix_put/fs/nfs/pagelist.c Thu Jan 31 16:05:53 2002 @@ -53,7 +53,7 @@ /** * nfs_create_request - Create an NFS read/write request. - * @file: file that owns this request + * @cred: RPC credential to use * @inode: inode to which the request is attached * @page: page to write * @offset: starting offset within the page for the write @@ -66,7 +66,7 @@ * 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 rpc_cred *cred, struct inode *inode, struct page *page, unsigned int offset, unsigned int count) { @@ -107,34 +107,49 @@ req->wb_offset = offset; req->wb_bytes = count; - /* If we have a struct file, use its cached credentials */ - if (file) { - req->wb_file = file; - get_file(file); - req->wb_cred = nfs_file_cred(file); - } + if (cred) + req->wb_cred = get_rpccred(cred); req->wb_inode = inode; req->wb_count = 1; return req; } +/** + * nfs_clear_request - Free up all resources allocated to the request + * @req: + * + * Release all resources associated with a write request after it + * has completed. + */ +void nfs_clear_request(struct nfs_page *req) +{ + /* 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; + atomic_dec(&NFS_REQUESTLIST(req->wb_inode)->nr_requests); + } +} + /** * nfs_release_request - Release the count on an NFS read/write request * @req: request to release * - * Release all resources associated with a write request after it - * has been committed to stable storage - * * Note: Should never be called with the spinlock held! */ void nfs_release_request(struct nfs_page *req) { - struct inode *inode = req->wb_inode; - struct nfs_reqlist *cache = NFS_REQUESTLIST(inode); - spin_lock(&nfs_wreq_lock); if (--req->wb_count) { spin_unlock(&nfs_wreq_lock); @@ -142,7 +157,6 @@ } __nfs_del_lru(req); spin_unlock(&nfs_wreq_lock); - atomic_dec(&cache->nr_requests); #ifdef NFS_PARANOIA if (!list_empty(&req->wb_list)) @@ -151,16 +165,12 @@ BUG(); if (NFS_WBACK_BUSY(req)) BUG(); - if (atomic_read(&cache->nr_requests) < 0) + if (atomic_read(&NFS_REQUESTLIST(req->wb_inode)->nr_requests) < 0) BUG(); #endif /* Release struct file or cached credential */ - if (req->wb_file) - fput(req->wb_file); - else if (req->wb_cred) - put_rpccred(req->wb_cred); - page_cache_release(req->wb_page); + nfs_clear_request(req); nfs_page_free(req); } diff -u --recursive --new-file linux-2.5.3-cto/fs/nfs/read.c linux-2.5.3-fix_put/fs/nfs/read.c --- linux-2.5.3-cto/fs/nfs/read.c Tue Jan 22 00:37:32 2002 +++ linux-2.5.3-fix_put/fs/nfs/read.c Thu Jan 31 16:05:53 2002 @@ -171,7 +171,7 @@ struct nfs_inode *nfsi = NFS_I(inode); struct nfs_page *new; - new = nfs_create_request(file, inode, page, 0, PAGE_CACHE_SIZE); + new = nfs_create_request(nfs_file_cred(file), inode, page, 0, PAGE_CACHE_SIZE); if (IS_ERR(new)) return PTR_ERR(new); nfs_mark_request_read(new); @@ -227,8 +227,9 @@ nfs_list_remove_request(req); SetPageError(page); UnlockPage(page); - nfs_unlock_request(req); + nfs_clear_request(req); nfs_release_request(req); + nfs_unlock_request(req); } } @@ -433,6 +434,7 @@ (long long)NFS_FILEID(req->wb_inode), req->wb_bytes, (long long)(page_offset(page) + req->wb_offset)); + nfs_clear_request(req); nfs_release_request(req); nfs_unlock_request(req); } diff -u --recursive --new-file linux-2.5.3-cto/fs/nfs/write.c linux-2.5.3-fix_put/fs/nfs/write.c --- linux-2.5.3-cto/fs/nfs/write.c Tue Jan 22 00:37:32 2002 +++ linux-2.5.3-fix_put/fs/nfs/write.c Thu Jan 31 16:05:53 2002 @@ -354,6 +354,7 @@ iput(inode); } else spin_unlock(&nfs_wreq_lock); + nfs_clear_request(req); nfs_release_request(req); } @@ -684,9 +685,13 @@ } spin_unlock(&nfs_wreq_lock); - new = nfs_create_request(file, inode, page, offset, bytes); + new = nfs_create_request(nfs_file_cred(file), inode, page, offset, bytes); if (IS_ERR(new)) return new; + if (file) { + new->wb_file = file; + get_file(file); + } /* If the region is locked, adjust the timeout */ if (region_locked(inode, new)) new->wb_timeout = jiffies + NFS_WRITEBACK_LOCKDELAY; diff -u --recursive --new-file linux-2.5.3-cto/include/linux/nfs_fs.h linux-2.5.3-fix_put/include/linux/nfs_fs.h --- linux-2.5.3-cto/include/linux/nfs_fs.h Thu Jan 31 15:06:03 2002 +++ linux-2.5.3-fix_put/include/linux/nfs_fs.h Thu Jan 31 16:06:40 2002 @@ -250,7 +250,9 @@ static __inline__ struct rpc_cred * nfs_file_cred(struct file *file) { - struct rpc_cred *cred = (struct rpc_cred *)(file->private_data); + struct rpc_cred *cred = NULL; + if (file) + cred = (struct rpc_cred *)file->private_data; #ifdef RPC_DEBUG if (cred && cred->cr_magic != RPCAUTH_CRED_MAGIC) BUG(); diff -u --recursive --new-file linux-2.5.3-cto/include/linux/nfs_page.h linux-2.5.3-fix_put/include/linux/nfs_page.h --- linux-2.5.3-cto/include/linux/nfs_page.h Thu Jan 31 15:13:24 2002 +++ linux-2.5.3-fix_put/include/linux/nfs_page.h Thu Jan 31 16:05:53 2002 @@ -41,9 +41,10 @@ #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) -extern struct nfs_page *nfs_create_request(struct file *, struct inode *, +extern struct nfs_page *nfs_create_request(struct rpc_cred *, struct inode *, struct page *, unsigned int, unsigned int); +extern void nfs_clear_request(struct nfs_page *req); extern void nfs_release_request(struct nfs_page *req);