Skip to content

Commit 6896b9d

Browse files
committed
Merge PR ceph#54690 into main
* refs/pull/54690/head: client: handle callback completion if the async I/O failed client: make sure the callback is finished when returning ENOTCONN client: do not accept zero byte write request client: check for negative value of iovcnt src/test: test zero bytes async i/o src/test: test async I/O with negative iov structures count src/test: test async I/O if the client is not mounted src/test: test async I/O with read only file src/test: test async I/O with a file created with O_PATH Reviewed-by: Frank S. Filz <[email protected]> Reviewed-by: Milind Changire <[email protected]> Reviewed-by: Venky Shankar <[email protected]> Reviewed-by: Rishabh Dave <[email protected]> Reviewed-by: Matt Benjamin <[email protected]>
2 parents bab43e8 + 9d4ae97 commit 6896b9d

File tree

3 files changed

+372
-18
lines changed

3 files changed

+372
-18
lines changed

src/client/Client.cc

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10655,8 +10655,6 @@ int Client::read(int fd, char *buf, loff_t size, loff_t offset)
1065510655

1065610656
int Client::preadv(int fd, const struct iovec *iov, int iovcnt, loff_t offset)
1065710657
{
10658-
if (iovcnt < 0)
10659-
return -CEPHFS_EINVAL;
1066010658
return _preadv_pwritev(fd, iov, iovcnt, offset, false);
1066110659
}
1066210660

@@ -11219,13 +11217,11 @@ int Client::write(int fd, const char *buf, loff_t size, loff_t offset)
1121911217

1122011218
int Client::pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset)
1122111219
{
11222-
if (iovcnt < 0)
11223-
return -CEPHFS_EINVAL;
1122411220
return _preadv_pwritev(fd, iov, iovcnt, offset, true);
1122511221
}
1122611222

1122711223
int64_t Client::_preadv_pwritev_locked(Fh *fh, const struct iovec *iov,
11228-
unsigned iovcnt, int64_t offset,
11224+
int iovcnt, int64_t offset,
1122911225
bool write, bool clamp_to_int,
1123011226
Context *onfinish, bufferlist *blp,
1123111227
bool do_fsync, bool syncdataonly)
@@ -11236,8 +11232,11 @@ int64_t Client::_preadv_pwritev_locked(Fh *fh, const struct iovec *iov,
1123611232
if (fh->flags & O_PATH)
1123711233
return -CEPHFS_EBADF;
1123811234
#endif
11235+
if(iovcnt < 0) {
11236+
return -CEPHFS_EINVAL;
11237+
}
1123911238
loff_t totallen = 0;
11240-
for (unsigned i = 0; i < iovcnt; i++) {
11239+
for (int i = 0; i < iovcnt; i++) {
1124111240
totallen += iov[i].iov_len;
1124211241
}
1124311242

@@ -11260,11 +11259,6 @@ int64_t Client::_preadv_pwritev_locked(Fh *fh, const struct iovec *iov,
1126011259
onfinish);
1126111260
ldout(cct, 3) << "preadv(" << fh << ", " << offset << ") = " << r << dendl;
1126211261
if (r <= 0) {
11263-
if (r < 0 && onfinish != nullptr) {
11264-
client_lock.unlock();
11265-
onfinish->complete(r);
11266-
client_lock.lock();
11267-
}
1126811262
return r;
1126911263
}
1127011264

@@ -11275,7 +11269,7 @@ int64_t Client::_preadv_pwritev_locked(Fh *fh, const struct iovec *iov,
1127511269
}
1127611270
}
1127711271

11278-
int Client::_preadv_pwritev(int fd, const struct iovec *iov, unsigned iovcnt,
11272+
int Client::_preadv_pwritev(int fd, const struct iovec *iov, int iovcnt,
1127911273
int64_t offset, bool write, Context *onfinish,
1128011274
bufferlist *blp)
1128111275
{
@@ -11442,6 +11436,10 @@ int64_t Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
1144211436
CWF_iofinish *cwf_iofinish = NULL;
1144311437
C_SaferCond *cond_iofinish = NULL;
1144411438

11439+
if (size < 1) { // zero bytes write is not supported by osd
11440+
return -CEPHFS_EINVAL;
11441+
}
11442+
1144511443
if ( (uint64_t)(offset+size) > mdsmap->get_max_filesize() && //exceeds config
1144611444
(uint64_t)(offset+size) > in->size ) { //exceeds filesize
1144711445
return -CEPHFS_EFBIG;
@@ -15945,12 +15943,49 @@ int64_t Client::ll_preadv_pwritev(struct Fh *fh, const struct iovec *iov,
1594515943
bool do_fsync, bool syncdataonly)
1594615944
{
1594715945
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
15948-
if (!mref_reader.is_state_satisfied())
15949-
return -CEPHFS_ENOTCONN;
15946+
if (!mref_reader.is_state_satisfied()) {
15947+
int64_t rc = -CEPHFS_ENOTCONN;
15948+
if (onfinish != nullptr) {
15949+
onfinish->complete(rc);
15950+
/* async call should always return zero to caller and allow the
15951+
caller to wait on callback for the actual errno. */
15952+
rc = 0;
15953+
}
15954+
return rc;
15955+
}
1595015956

1595115957
std::scoped_lock cl(client_lock);
15952-
return _preadv_pwritev_locked(fh, iov, iovcnt, offset, write, true,
15953-
onfinish, bl, do_fsync, syncdataonly);
15958+
15959+
int64_t retval = _preadv_pwritev_locked(fh, iov, iovcnt, offset, write,
15960+
true, onfinish, bl, do_fsync,
15961+
syncdataonly);
15962+
/* There are two scenarios with each having two cases to handle here
15963+
1) async io
15964+
1.a) r == 0:
15965+
async call in progress, the context will be automatically invoked,
15966+
so just return the retval (i.e. zero).
15967+
1.b) r < 0:
15968+
There was an error; no context completion should've took place so
15969+
complete the context with retval followed by returning zero to the
15970+
caller.
15971+
2) sync io
15972+
2.a) r >= 0:
15973+
sync call success; return the no. of bytes read/written.
15974+
2.b) r < 0:
15975+
sync call failed; return the errno. */
15976+
15977+
if (retval < 0) {
15978+
if (onfinish != nullptr) {
15979+
//async io failed
15980+
client_lock.unlock();
15981+
onfinish->complete(retval);
15982+
client_lock.lock();
15983+
/* async call should always return zero to caller and allow the
15984+
caller to wait on callback for the actual errno/retval. */
15985+
retval = 0;
15986+
}
15987+
}
15988+
return retval;
1595415989
}
1595515990

1595615991
int Client::ll_flush(Fh *fh)

src/client/Client.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,12 +1677,12 @@ class Client : public Dispatcher, public md_config_obs_t {
16771677
const struct iovec *iov, int iovcnt, Context *onfinish = nullptr,
16781678
bool do_fsync = false, bool syncdataonly = false);
16791679
int64_t _preadv_pwritev_locked(Fh *fh, const struct iovec *iov,
1680-
unsigned iovcnt, int64_t offset,
1680+
int iovcnt, int64_t offset,
16811681
bool write, bool clamp_to_int,
16821682
Context *onfinish = nullptr,
16831683
bufferlist *blp = nullptr,
16841684
bool do_fsync = false, bool syncdataonly = false);
1685-
int _preadv_pwritev(int fd, const struct iovec *iov, unsigned iovcnt,
1685+
int _preadv_pwritev(int fd, const struct iovec *iov, int iovcnt,
16861686
int64_t offset, bool write, Context *onfinish = nullptr,
16871687
bufferlist *blp = nullptr);
16881688
int _flush(Fh *fh);

0 commit comments

Comments
 (0)