Message ID | 20220305115259.1076790-1-xiubli@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3] ceph: fix memory leakage in ceph_readdir | expand |
On Sat, 2022-03-05 at 19:52 +0800, xiubli@redhat.com wrote: > From: Xiubo Li <xiubli@redhat.com> > > Reset the last_readdir at the same time. > > Signed-off-by: Xiubo Li <xiubli@redhat.com> > --- > 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 6be0c1f793c2..6df2a91af236 100644 > --- a/fs/ceph/dir.c > +++ b/fs/ceph/dir.c > @@ -498,8 +498,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; > goto out; > + } Looks good, but this doesn't apply cleanly to the testing branch since it still does a "return 0" there instead of "goto out". I adapted it to work with testing branch and will do some testing with it today. > } else if (req->r_reply_info.dir_end) { > dfi->next_offset = 2; > /* keep last name */ > @@ -552,6 +555,12 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) > if (!dir_emit(ctx, oname.name, oname.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"); > err = 0; > goto out;
On 3/8/22 11:06 PM, Jeff Layton wrote: > On Sat, 2022-03-05 at 19:52 +0800, xiubli@redhat.com wrote: >> From: Xiubo Li <xiubli@redhat.com> >> >> Reset the last_readdir at the same time. >> >> Signed-off-by: Xiubo Li <xiubli@redhat.com> >> --- >> 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 6be0c1f793c2..6df2a91af236 100644 >> --- a/fs/ceph/dir.c >> +++ b/fs/ceph/dir.c >> @@ -498,8 +498,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; >> goto out; >> + } > Looks good, but this doesn't apply cleanly to the testing branch since > it still does a "return 0" there instead of "goto out". I adapted it to > work with testing branch and will do some testing with it today. > I think I was working on the wip-fscrypt branch. Thanks Jeff. - Xiubo >> } else if (req->r_reply_info.dir_end) { >> dfi->next_offset = 2; >> /* keep last name */ >> @@ -552,6 +555,12 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) >> if (!dir_emit(ctx, oname.name, oname.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"); >> err = 0; >> goto out;
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 6be0c1f793c2..6df2a91af236 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -498,8 +498,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; goto out; + } } else if (req->r_reply_info.dir_end) { dfi->next_offset = 2; /* keep last name */ @@ -552,6 +555,12 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) if (!dir_emit(ctx, oname.name, oname.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"); err = 0; goto out;