Skip to content

client: do not allow zero‑length reads#65656

Open
dparmar18 wants to merge 3 commits intoceph:mainfrom
dparmar18:i73037
Open

client: do not allow zero‑length reads#65656
dparmar18 wants to merge 3 commits intoceph:mainfrom
dparmar18:i73037

Conversation

@dparmar18
Copy link
Contributor

@dparmar18 dparmar18 commented Sep 24, 2025

Contribution Guidelines

  • To sign and title your commits, please refer to Submitting Patches to Ceph.

  • If you are submitting a fix for a stable branch (e.g. "quincy"), please refer to Submitting Patches to Ceph - Backports for the proper workflow.

  • When filling out the below checklist, you may click boxes directly in the GitHub web UI. When entering or editing the entire PR message in the GitHub web UI editor, you may also select a checklist item by adding an x between the brackets: [x]. Spaces and capitalization matter when checking off items this way.

Checklist

  • Tracker (select at least one)
    • References tracker ticket
    • Very recent bug; references commit where it was introduced
    • New feature (ticket optional)
    • Doc update (no ticket needed)
    • Code cleanup (no ticket needed)
  • Component impact
    • Affects Dashboard, opened tracker ticket
    • Affects Orchestrator, opened tracker ticket
    • No impact that needs to be tracked
  • Documentation (select at least one)
    • Updates relevant documentation
    • No doc update is appropriate
  • Tests (select at least one)
Show available Jenkins commands

You must only issue one Jenkins command per-comment. Jenkins does not understand
comments with more than one command.

@github-actions github-actions bot added cephfs Ceph File System tests labels Sep 24, 2025
@dparmar18 dparmar18 requested a review from a team September 24, 2025 11:52
@dparmar18 dparmar18 force-pushed the i73037 branch 5 times, most recently from 6232c76 to b31d6a8 Compare October 31, 2025 08:12
{
ceph_assert(ceph_mutex_is_locked_by_me(client_lock));

// zero bytes read is not supported by osd
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm thinking more about this approach. If we put this up this high, we'll miss the check for f->mode & CEPH_FILE_MODE_RD) == 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can move that check above before declaring all those variables

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this current form, we still exit if size == 0, but f->mode doesn't have CEPH_FILE_MODE_RD. It should fail in that case regardless of size. We should probably still do this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you take a look now? I've moved the ldout statement to top, first check the file handle mode and then the size.

// is duplicated and modified and exists in
// C_Read_Sync_NonBlocking::finish().

// trim read based on file size?
Copy link
Contributor

@chrisphoffman chrisphoffman Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to keep things consistent. Right now case 1 (_read_async) and case 3 (_read_sync) both check again if the size/len is 0 within the functions. They both are only called from _read(). Do we want to remove those checks, or add a check to C_Read_Sync_NonBlocking to complete immediately in retry() if len == 0? That way we can potentially avoid bugs later on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now case 1 (_read_async) and case 3 (_read_sync) both check again if the size/len is 0 within the functions. They both are only called from _read()

I did thought about this initially but then wondered - what if in future these member functions are called independently from some new API? I felt that considering they are helper functions to carry out async/sync read; i kept those functions intact. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a check to C_Read_Sync_NonBlocking to complete immediately in retry() if len == 0? That way we can potentially avoid bugs later on.

Yeah, doable. It's called from case 2 right now and fixing the retry() could help prevent future bugs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also what about C_Read_Async_Finisher::finish? In Client::do_readahead - pair<uint64_t, uint64_t> readahead_extent = f->readahead.update(off, len, in->size); returns an extent and the extent.second would be readahead_length and then is passed in

int r2 = objectcacher->file_read(&in->oset, &in->layout, in->snapid,
				       readahead_extent.first, readahead_extent.second,
				       NULL, 0, onfinish2);

this could again crash

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some new API? I felt that considering they are helper functions to carry out async/sync read; i kept those functions intact. WDYT?

Yeah we can keep those, if _read_sync and _read_async both bail if the size is zero that will keep it from failing on unchecked new code paths.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also what about C_Read_Async_Finisher::finish?

Unless I'm missing something, that has a check, that skips do_readahead if size is 0.

ceph/src/client/Client.cc

Lines 11825 to 11826 in 9d82c94

if (r != 0)
clnt->do_readahead(f, in, off, len);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also what about C_Read_Async_Finisher::finish?

Unless I'm missing something, that has a check, that skips do_readahead if size is 0.

ceph/src/client/Client.cc

Lines 11825 to 11826 in 9d82c94

if (r != 0)
clnt->do_readahead(f, in, off, len);

oh glad it is, wonder how i missed it but thanks for pointing out!

@github-actions
Copy link

github-actions bot commented Nov 6, 2025

This pull request can no longer be automatically merged: a rebase is needed and changes have to be manually resolved

@vshankar
Copy link
Contributor

@dparmar18 please rebase

@dparmar18
Copy link
Contributor Author

@dparmar18 please rebase

@vshankar this is ready

Copy link
Contributor

@anoopcs9 anoopcs9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the commit message subject and PR title: client: do not allow zero‑length reads or client: disallow zero length reads

Please fix the typo in the commit message subject: src/test: test zero-length async-fsync read using ll_preadv_pwritev -> s/async/sync.

@dparmar18 dparmar18 force-pushed the i73037 branch 2 times, most recently from fd60702 to d3ca82b Compare December 3, 2025 11:32
@dparmar18
Copy link
Contributor Author

Please fix the typo in the commit message subject: src/test: test zero-length async-fsync read using ll_preadv_pwritev -> s/async/sync.

from the https://tracker.ceph.com/issues/73037 description, i think it should be async

@dparmar18 dparmar18 changed the title client: no do allow zero length read client: do not allow zero‑length reads Dec 3, 2025
@anoopcs9 anoopcs9 dismissed their stale review December 4, 2025 11:11

Requested changes have been made in the updated version.

Copy link
Contributor

@chrisphoffman chrisphoffman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all my comments were addressed. lgtm

ldout(cct, 10) << " nothing to flush" << dendl;
return;
}
if (size == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: a new line before here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@github-actions
Copy link

This pull request can no longer be automatically merged: a rebase is needed and changes have to be manually resolved

@dparmar18
Copy link
Contributor Author

@vshankar request for a teuthology run

@dparmar18
Copy link
Contributor Author

@vshankar ping

@vshankar
Copy link
Contributor

vshankar commented Jan 5, 2026

@vshankar request for a teuthology run

I don't have access to the new lab yet. Working it out...

…_readv_writev

Fixes: https://tracker.ceph.com/issues/73037
Signed-off-by: Dhairya Parmar <dparmar@redhat.com>
fixing this in Client::_read which is called by both async and sync code paths.

Fixes: https://tracker.ceph.com/issues/73037
Signed-off-by: Dhairya Parmar <dparmar@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants