--- linux-2.4.22/fs/nfs/write.c.orig Thu Sep 25 07:33:34 2003 +++ linux-2.4.22/fs/nfs/write.c Fri Sep 26 07:09:32 2003 @@ -318,14 +318,15 @@ /* * Insert a write request into an inode */ -static inline void +static inline int nfs_inode_remove_request(struct nfs_page *req) { struct inode *inode; + int need_iput = 0; spin_lock(&nfs_wreq_lock); if (list_empty(&req->wb_hash)) { spin_unlock(&nfs_wreq_lock); - return; + return 0; } if (!NFS_WBACK_BUSY(req)) printk(KERN_ERR "NFS: unlocked request attempted unhashed!\n"); @@ -335,13 +336,12 @@ inode->u.nfs_i.npages--; if ((inode->u.nfs_i.npages == 0) != list_empty(&inode->u.nfs_i.writeback)) printk(KERN_ERR "NFS: desynchronized value of nfs_i.npages.\n"); - if (list_empty(&inode->u.nfs_i.writeback)) { - spin_unlock(&nfs_wreq_lock); - iput(inode); - } else - spin_unlock(&nfs_wreq_lock); + if (list_empty(&inode->u.nfs_i.writeback)) + need_iput = 1; + spin_unlock(&nfs_wreq_lock); nfs_clear_request(req); nfs_release_request(req); + return need_iput; } /* @@ -1049,6 +1049,7 @@ */ nfs_write_attributes(inode, resp->fattr); while (!list_empty(&data->pages)) { + int need_iput = 0; req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); page = req->wb_page; @@ -1064,14 +1065,14 @@ SetPageError(page); if (req->wb_file) req->wb_file->f_error = task->tk_status; - nfs_inode_remove_request(req); + need_iput = nfs_inode_remove_request(req); dprintk(", error = %d\n", task->tk_status); goto next; } #ifdef CONFIG_NFS_V3 if (argp->stable != NFS_UNSTABLE || resp->verf->committed == NFS_FILE_SYNC) { - nfs_inode_remove_request(req); + need_iput = nfs_inode_remove_request(req); dprintk(" OK\n"); goto next; } @@ -1080,10 +1081,12 @@ nfs_mark_request_commit(req); dprintk(" marked for commit\n"); #else - nfs_inode_remove_request(req); + need_iput = nfs_inode_remove_request(req); #endif next: nfs_unlock_request(req); + if(need_iput) + iput(inode); } } @@ -1203,6 +1206,7 @@ nfs_write_attributes(inode, resp->fattr); while (!list_empty(&data->pages)) { + int need_iput = 0; req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); @@ -1214,7 +1218,7 @@ if (task->tk_status < 0) { if (req->wb_file) req->wb_file->f_error = task->tk_status; - nfs_inode_remove_request(req); + need_iput = nfs_inode_remove_request(req); dprintk(", error = %d\n", task->tk_status); goto next; } @@ -1223,7 +1227,7 @@ * returned by the server against all stored verfs. */ if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { /* We have a match */ - nfs_inode_remove_request(req); + need_iput = nfs_inode_remove_request(req); dprintk(" OK\n"); goto next; } @@ -1232,6 +1236,8 @@ nfs_mark_request_dirty(req); next: nfs_unlock_request(req); + if(need_iput) + iput(inode); } } #endif