@@ -10655,8 +10655,6 @@ int Client::read(int fd, char *buf, loff_t size, loff_t offset)
1065510655
1065610656int 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
1122011218int 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
1122711223int64_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
1595615991int Client::ll_flush (Fh *fh)
0 commit comments