diff options
author | Peng Tao <tao.peng@primarydata.com> | 2014-11-05 09:36:50 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-11-12 14:22:51 -0500 |
commit | 8c393f9a721c30a030049a680e1bf896669bb279 (patch) | |
tree | 391e4b574115434947a4f94e9cfcac72553fedc8 | |
parent | dca780016dab84d6ac500b1d84fdfe1628802a59 (diff) |
nfs: fix pnfs direct write memory leak
For pNFS direct writes, layout driver may dynamically allocate ds_cinfo.buckets.
So we need to take care to free them when freeing dreq.
Ideally this needs to be done inside layout driver where ds_cinfo.buckets
are allocated. But buckets are attached to dreq and reused across LD IO iterations.
So I feel it's OK to free them in the generic layer.
Cc: stable@vger.kernel.org [v3.4+]
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/direct.c | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 11 |
2 files changed, 12 insertions, 0 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 20cffc830468..10bf07280f4a 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -266,6 +266,7 @@ static void nfs_direct_req_free(struct kref *kref) | |||
266 | { | 266 | { |
267 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); | 267 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); |
268 | 268 | ||
269 | nfs_free_pnfs_ds_cinfo(&dreq->ds_cinfo); | ||
269 | if (dreq->l_ctx != NULL) | 270 | if (dreq->l_ctx != NULL) |
270 | nfs_put_lock_context(dreq->l_ctx); | 271 | nfs_put_lock_context(dreq->l_ctx); |
271 | if (dreq->ctx != NULL) | 272 | if (dreq->ctx != NULL) |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 983876f24aed..47ebb4fafd87 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1224,11 +1224,22 @@ struct nfs41_free_stateid_res { | |||
1224 | unsigned int status; | 1224 | unsigned int status; |
1225 | }; | 1225 | }; |
1226 | 1226 | ||
1227 | static inline void | ||
1228 | nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo) | ||
1229 | { | ||
1230 | kfree(cinfo->buckets); | ||
1231 | } | ||
1232 | |||
1227 | #else | 1233 | #else |
1228 | 1234 | ||
1229 | struct pnfs_ds_commit_info { | 1235 | struct pnfs_ds_commit_info { |
1230 | }; | 1236 | }; |
1231 | 1237 | ||
1238 | static inline void | ||
1239 | nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo) | ||
1240 | { | ||
1241 | } | ||
1242 | |||
1232 | #endif /* CONFIG_NFS_V4_1 */ | 1243 | #endif /* CONFIG_NFS_V4_1 */ |
1233 | 1244 | ||
1234 | #ifdef CONFIG_NFS_V4_2 | 1245 | #ifdef CONFIG_NFS_V4_2 |