| From 1133bac425a3877b5860d4edfcd0109587396a54 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 5 Mar 2022 19:52:59 +0800 |
| Subject: ceph: fix memory leak in ceph_readdir when note_last_dentry returns |
| error |
| |
| From: Xiubo Li <xiubli@redhat.com> |
| |
| [ Upstream commit f639d9867eea647005dc824e0e24f39ffc50d4e4 ] |
| |
| Reset the last_readdir at the same time, and add a comment explaining |
| why we don't free last_readdir when dir_emit returns false. |
| |
| Signed-off-by: Xiubo Li <xiubli@redhat.com> |
| Reviewed-by: Jeff Layton <jlayton@kernel.org> |
| Signed-off-by: Ilya Dryomov <idryomov@gmail.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/ceph/dir.c | 11 ++++++++++- |
| 1 file changed, 10 insertions(+), 1 deletion(-) |
| |
| diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c |
| index 133dbd9338e7..d91fa53e12b3 100644 |
| --- a/fs/ceph/dir.c |
| +++ b/fs/ceph/dir.c |
| @@ -478,8 +478,11 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) |
| 2 : (fpos_off(rde->offset) + 1); |
| err = note_last_dentry(dfi, rde->name, rde->name_len, |
| next_offset); |
| - if (err) |
| + if (err) { |
| + ceph_mdsc_put_request(dfi->last_readdir); |
| + dfi->last_readdir = NULL; |
| return err; |
| + } |
| } else if (req->r_reply_info.dir_end) { |
| dfi->next_offset = 2; |
| /* keep last name */ |
| @@ -520,6 +523,12 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) |
| if (!dir_emit(ctx, rde->name, rde->name_len, |
| ceph_present_ino(inode->i_sb, le64_to_cpu(rde->inode.in->ino)), |
| le32_to_cpu(rde->inode.in->mode) >> 12)) { |
| + /* |
| + * NOTE: Here no need to put the 'dfi->last_readdir', |
| + * because when dir_emit stops us it's most likely |
| + * doesn't have enough memory, etc. So for next readdir |
| + * it will continue. |
| + */ |
| dout("filldir stopping us...\n"); |
| return 0; |
| } |
| -- |
| 2.35.1 |
| |