[ewg] [PATCH] NFS-RDMA: Fix page leak

Jon Mason jon at opengridcomputing.com
Thu Apr 2 12:47:09 PDT 2009


In the conversion from splice_direct_to_actor to sendfile, the callback
routine was converted to the previous version without reference to the
new changes to the callback route that calls the put_page.  Previously,
it had been called in svc_release_buffer, but due to significant changes
in the logic of that function it cannot be done there (and this more
closely matches what is in 2.6.28).

This fixes Bugzilla Bug 1574

Signed-Off-By: Jon Mason <jon at opengridcomputing.com>

diff --git a/kernel_patches/backport/2.6.18-EL5.1/rnfs_fs.patch b/kernel_patches/backport/2.6.18-EL5.1/rnfs_fs.patch
index 6176bed..5bcc84c 100644
--- a/kernel_patches/backport/2.6.18-EL5.1/rnfs_fs.patch
+++ b/kernel_patches/backport/2.6.18-EL5.1/rnfs_fs.patch
@@ -1660,7 +1660,7 @@ index 80292ff..47eb160 100644
 +
 +MODULE_LICENSE("Dual BSD/GPL");
 diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
-index 18060be..c08b4dc 100644
+index 18060be..becacce 100644
 --- a/fs/nfsd/vfs.c
 +++ b/fs/nfsd/vfs.c
 @@ -23,7 +23,6 @@
@@ -1685,7 +1685,7 @@ index 18060be..c08b4dc 100644
  	mutex_unlock(&inode->i_mutex);
  
  	return err;
-@@ -828,53 +827,33 @@ found:
+@@ -828,53 +827,39 @@ found:
  	return ra;
  }
  
@@ -1700,17 +1700,17 @@ index 18060be..c08b4dc 100644
 +nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
  {
 -	struct svc_rqst *rqstp = sd->u.data;
--	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
++	unsigned long count = desc->count;
++	struct svc_rqst *rqstp = desc->arg.data;
+ 	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
 -	struct page *page = buf->page;
 -	size_t size;
 -	int ret;
-+	unsigned long count = desc->count;
-+	struct svc_rqst *rqstp = desc->arg.data;
- 
+-
 -	ret = buf->ops->confirm(pipe, buf);
 -	if (unlikely(ret))
 -		return ret;
--
+ 
 -	size = sd->len;
 +	if (size > count)
 +		size = count;
@@ -1721,15 +1721,17 @@ index 18060be..c08b4dc 100644
 -		*pp = page;
 -		rqstp->rq_resused++;
 -		rqstp->rq_res.page_base = buf->offset;
++		if (*pp)
++			put_page(*pp);
 +		rqstp->rq_respages[rqstp->rq_resused++] = page;
 +		rqstp->rq_res.page_base = offset;
  		rqstp->rq_res.page_len = size;
 -	} else if (page != pp[-1]) {
 +	} else if (page != rqstp->rq_respages[rqstp->rq_resused-1]) {
  		get_page(page);
--		if (*pp)
--			put_page(*pp);
--		*pp = page;
+ 		if (*pp)
+ 			put_page(*pp);
+ 		*pp = page;
 -		rqstp->rq_resused++;
 +		rqstp->rq_respages[rqstp->rq_resused++] = page;
  		rqstp->rq_res.page_len += size;
@@ -1752,7 +1754,7 @@ index 18060be..c08b4dc 100644
  static inline int svc_msnfs(struct svc_fh *ffhp)
  {
  #ifdef MSNFS
-@@ -895,7 +874,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -895,7 +880,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	int		host_err;
  
  	err = nfserr_perm;
@@ -1761,7 +1763,7 @@ index 18060be..c08b4dc 100644
  
  	if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count))
  		goto out;
-@@ -906,16 +885,9 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -906,16 +891,9 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	if (ra && ra->p_set)
  		file->f_ra = ra->p_ra;
  
@@ -1780,7 +1782,7 @@ index 18060be..c08b4dc 100644
  	} else {
  		oldfs = get_fs();
  		set_fs(KERNEL_DS);
-@@ -937,7 +909,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -937,7 +915,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  		nfsdstats.io_read += host_err;
  		*count = host_err;
  		err = 0;
@@ -1789,7 +1791,7 @@ index 18060be..c08b4dc 100644
  	} else 
  		err = nfserrno(host_err);
  out:
-@@ -971,11 +943,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -971,11 +949,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	err = nfserr_perm;
  
  	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
@@ -1803,7 +1805,7 @@ index 18060be..c08b4dc 100644
  	inode = dentry->d_inode;
  	exp   = fhp->fh_export;
  
-@@ -1004,7 +976,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -1004,7 +982,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	set_fs(oldfs);
  	if (host_err >= 0) {
  		nfsdstats.io_write += cnt;
diff --git a/kernel_patches/backport/2.6.18-EL5.2/rnfs_fs.patch b/kernel_patches/backport/2.6.18-EL5.2/rnfs_fs.patch
index 5e9cda3..7610c66 100644
--- a/kernel_patches/backport/2.6.18-EL5.2/rnfs_fs.patch
+++ b/kernel_patches/backport/2.6.18-EL5.2/rnfs_fs.patch
@@ -1578,7 +1578,7 @@ index 80292ff..47eb160 100644
 +
 +MODULE_LICENSE("Dual BSD/GPL");
 diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
-index 18060be..be88d9d 100644
+index 18060be..ca19ab2 100644
 --- a/fs/nfsd/vfs.c
 +++ b/fs/nfsd/vfs.c
 @@ -23,7 +23,6 @@
@@ -1614,7 +1614,7 @@ index 18060be..be88d9d 100644
  	mutex_unlock(&inode->i_mutex);
  
  	return err;
-@@ -828,53 +827,33 @@ found:
+@@ -828,53 +827,39 @@ found:
  	return ra;
  }
  
@@ -1629,17 +1629,17 @@ index 18060be..be88d9d 100644
 +nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
  {
 -	struct svc_rqst *rqstp = sd->u.data;
--	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
++	unsigned long count = desc->count;
++	struct svc_rqst *rqstp = desc->arg.data;
+ 	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
 -	struct page *page = buf->page;
 -	size_t size;
 -	int ret;
--
+ 
 -	ret = buf->ops->confirm(pipe, buf);
 -	if (unlikely(ret))
 -		return ret;
-+	unsigned long count = desc->count;
-+	struct svc_rqst *rqstp = desc->arg.data;
- 
+-
 -	size = sd->len;
 +	if (size > count)
 +		size = count;
@@ -1650,15 +1650,17 @@ index 18060be..be88d9d 100644
 -		*pp = page;
 -		rqstp->rq_resused++;
 -		rqstp->rq_res.page_base = buf->offset;
++		if (*pp)
++			put_page(*pp);
 +		rqstp->rq_respages[rqstp->rq_resused++] = page;
 +		rqstp->rq_res.page_base = offset;
  		rqstp->rq_res.page_len = size;
 -	} else if (page != pp[-1]) {
 +	} else if (page != rqstp->rq_respages[rqstp->rq_resused-1]) {
  		get_page(page);
--		if (*pp)
--			put_page(*pp);
--		*pp = page;
+ 		if (*pp)
+ 			put_page(*pp);
+ 		*pp = page;
 -		rqstp->rq_resused++;
 +		rqstp->rq_respages[rqstp->rq_resused++] = page;
  		rqstp->rq_res.page_len += size;
@@ -1681,7 +1683,7 @@ index 18060be..be88d9d 100644
  static inline int svc_msnfs(struct svc_fh *ffhp)
  {
  #ifdef MSNFS
-@@ -886,7 +865,7 @@ static inline int svc_msnfs(struct svc_fh *ffhp)
+@@ -886,7 +871,7 @@ static inline int svc_msnfs(struct svc_fh *ffhp)
  
  static __be32
  nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
@@ -1690,7 +1692,7 @@ index 18060be..be88d9d 100644
  {
  	struct inode *inode;
  	struct raparms	*ra;
-@@ -895,7 +874,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -895,7 +880,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	int		host_err;
  
  	err = nfserr_perm;
@@ -1699,7 +1701,7 @@ index 18060be..be88d9d 100644
  
  	if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count))
  		goto out;
-@@ -906,16 +885,9 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -906,16 +891,9 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	if (ra && ra->p_set)
  		file->f_ra = ra->p_ra;
  
@@ -1718,7 +1720,7 @@ index 18060be..be88d9d 100644
  	} else {
  		oldfs = get_fs();
  		set_fs(KERNEL_DS);
-@@ -937,7 +909,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -937,7 +915,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  		nfsdstats.io_read += host_err;
  		*count = host_err;
  		err = 0;
@@ -1727,7 +1729,7 @@ index 18060be..be88d9d 100644
  	} else 
  		err = nfserrno(host_err);
  out:
-@@ -971,11 +943,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -971,11 +949,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	err = nfserr_perm;
  
  	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
@@ -1741,7 +1743,7 @@ index 18060be..be88d9d 100644
  	inode = dentry->d_inode;
  	exp   = fhp->fh_export;
  
-@@ -1004,7 +976,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -1004,7 +982,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	set_fs(oldfs);
  	if (host_err >= 0) {
  		nfsdstats.io_write += cnt;
@@ -1750,7 +1752,7 @@ index 18060be..be88d9d 100644
  	}
  
  	/* clear setuid/setgid flag after write */
-@@ -1129,7 +1101,7 @@ out:
+@@ -1129,7 +1107,7 @@ out:
   */
  __be32
  nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
@@ -1759,7 +1761,7 @@ index 18060be..be88d9d 100644
  {
  	struct file	*file;
  	__be32		err;
-@@ -1316,7 +1288,7 @@ __be32
+@@ -1316,7 +1294,7 @@ __be32
  nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
  		char *fname, int flen, struct iattr *iap,
  		struct svc_fh *resfhp, int createmode, u32 *verifier,
diff --git a/kernel_patches/backport/2.6.18-EL5.3/rnfs_fs.patch b/kernel_patches/backport/2.6.18-EL5.3/rnfs_fs.patch
index f91e162..c773b6f 100644
--- a/kernel_patches/backport/2.6.18-EL5.3/rnfs_fs.patch
+++ b/kernel_patches/backport/2.6.18-EL5.3/rnfs_fs.patch
@@ -1117,7 +1117,7 @@ index 412738d..b17f14a 100644
  	.follow_link	= nfs_follow_link,
  	.put_link	= page_put_link,
 diff --git a/fs/nfs/write.c b/fs/nfs/write.c
-index 3229e21..08df526 100644
+index 3229e21..a405394 100644
 --- a/fs/nfs/write.c
 +++ b/fs/nfs/write.c
 @@ -12,6 +12,7 @@
@@ -1128,7 +1128,7 @@ index 3229e21..08df526 100644
  #include <linux/swap.h>
  
  #include <linux/sunrpc/clnt.h>
-@@ -726,8 +726,8 @@ int nfs_updatepage(struct file *file, struct page *page,
+@@ -726,8 +727,8 @@ int nfs_updatepage(struct file *file, struct page *page,
  	nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
  
  	dprintk("NFS:       nfs_updatepage(%s/%s %d@%lld)\n",
@@ -1560,7 +1560,7 @@ index 80292ff..47eb160 100644
 +
 +MODULE_LICENSE("Dual BSD/GPL");
 diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
-index 18060be..3298a87 100644
+index 18060be..fbd0f97 100644
 --- a/fs/nfsd/vfs.c
 +++ b/fs/nfsd/vfs.c
 @@ -23,7 +23,6 @@
@@ -1587,7 +1587,7 @@ index 18060be..3298a87 100644
  	mutex_unlock(&inode->i_mutex);
  
  	return err;
-@@ -828,53 +827,33 @@ found:
+@@ -828,53 +827,39 @@ found:
  	return ra;
  }
  
@@ -1602,17 +1602,17 @@ index 18060be..3298a87 100644
 +nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
  {
 -	struct svc_rqst *rqstp = sd->u.data;
--	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
++	unsigned long count = desc->count;
++	struct svc_rqst *rqstp = desc->arg.data;
+ 	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
 -	struct page *page = buf->page;
 -	size_t size;
 -	int ret;
--
+ 
 -	ret = buf->ops->confirm(pipe, buf);
 -	if (unlikely(ret))
 -		return ret;
-+	unsigned long count = desc->count;
-+	struct svc_rqst *rqstp = desc->arg.data;
- 
+-
 -	size = sd->len;
 +	if (size > count)
 +		size = count;
@@ -1623,15 +1623,17 @@ index 18060be..3298a87 100644
 -		*pp = page;
 -		rqstp->rq_resused++;
 -		rqstp->rq_res.page_base = buf->offset;
++		if (*pp)
++			put_page(*pp);
 +		rqstp->rq_respages[rqstp->rq_resused++] = page;
 +		rqstp->rq_res.page_base = offset;
  		rqstp->rq_res.page_len = size;
 -	} else if (page != pp[-1]) {
 +	} else if (page != rqstp->rq_respages[rqstp->rq_resused-1]) {
  		get_page(page);
--		if (*pp)
--			put_page(*pp);
--		*pp = page;
+ 		if (*pp)
+ 			put_page(*pp);
+ 		*pp = page;
 -		rqstp->rq_resused++;
 +		rqstp->rq_respages[rqstp->rq_resused++] = page;
  		rqstp->rq_res.page_len += size;
@@ -1654,7 +1656,7 @@ index 18060be..3298a87 100644
  static inline int svc_msnfs(struct svc_fh *ffhp)
  {
  #ifdef MSNFS
-@@ -895,7 +874,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -895,7 +880,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	int		host_err;
  
  	err = nfserr_perm;
@@ -1663,7 +1665,7 @@ index 18060be..3298a87 100644
  
  	if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count))
  		goto out;
-@@ -906,16 +885,9 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -906,16 +891,9 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	if (ra && ra->p_set)
  		file->f_ra = ra->p_ra;
  
@@ -1682,7 +1684,7 @@ index 18060be..3298a87 100644
  	} else {
  		oldfs = get_fs();
  		set_fs(KERNEL_DS);
-@@ -937,7 +909,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -937,7 +915,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  		nfsdstats.io_read += host_err;
  		*count = host_err;
  		err = 0;
@@ -1691,7 +1693,7 @@ index 18060be..3298a87 100644
  	} else 
  		err = nfserrno(host_err);
  out:
-@@ -971,11 +943,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -971,11 +949,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	err = nfserr_perm;
  
  	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
@@ -1705,7 +1707,7 @@ index 18060be..3298a87 100644
  	inode = dentry->d_inode;
  	exp   = fhp->fh_export;
  
-@@ -1004,7 +976,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+@@ -1004,7 +982,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
  	set_fs(oldfs);
  	if (host_err >= 0) {
  		nfsdstats.io_write += cnt;



More information about the ewg mailing list