Return errno in case of write failed

so make ::pwrite return an int
This commit is contained in:
benrubson 2017-03-11 19:38:17 +01:00
parent ac87a8ba0e
commit 63d11e6989
12 changed files with 43 additions and 38 deletions

View File

@ -94,15 +94,15 @@ ssize_t BlockFileIO::cacheReadOneBlock(const IORequest &req) const {
} }
} }
bool BlockFileIO::cacheWriteOneBlock(const IORequest &req) { int BlockFileIO::cacheWriteOneBlock(const IORequest &req) {
// cache results of write (before pass-thru, because it may be modified // cache results of write (before pass-thru, because it may be modified
// in-place) // in-place)
memcpy(_cache.data, req.data, req.dataLen); memcpy(_cache.data, req.data, req.dataLen);
_cache.offset = req.offset; _cache.offset = req.offset;
_cache.dataLen = req.dataLen; _cache.dataLen = req.dataLen;
bool ok = writeOneBlock(req); int res = writeOneBlock(req);
if (!ok) clearCache(_cache, _blockSize); if (res) clearCache(_cache, _blockSize);
return ok; return res;
} }
/** /**
@ -171,11 +171,11 @@ ssize_t BlockFileIO::read(const IORequest &req) const {
return result; return result;
} }
bool BlockFileIO::write(const IORequest &req) { int BlockFileIO::write(const IORequest &req) {
CHECK(_blockSize != 0); CHECK(_blockSize != 0);
off_t fileSize = getSize(); off_t fileSize = getSize();
if (fileSize < 0) return false; if (fileSize < 0) return fileSize;
// where write request begins // where write request begins
off_t blockNum = req.offset / _blockSize; off_t blockNum = req.offset / _blockSize;
@ -213,7 +213,7 @@ bool BlockFileIO::write(const IORequest &req) {
blockReq.data = NULL; blockReq.data = NULL;
blockReq.dataLen = _blockSize; blockReq.dataLen = _blockSize;
bool ok = true; int res = 0;
size_t size = req.dataLen; size_t size = req.dataLen;
unsigned char *inPtr = req.data; unsigned char *inPtr = req.data;
while (size) { while (size) {
@ -251,8 +251,8 @@ bool BlockFileIO::write(const IORequest &req) {
} }
// Finally, write the damn thing! // Finally, write the damn thing!
if (!cacheWriteOneBlock(blockReq)) { res = cacheWriteOneBlock(blockReq);
ok = false; if (res) {
break; break;
} }
@ -265,7 +265,7 @@ bool BlockFileIO::write(const IORequest &req) {
if (mb.data) MemoryPool::release(mb); if (mb.data) MemoryPool::release(mb);
return ok; return res;
} }
int BlockFileIO::blockSize() const { return _blockSize; } int BlockFileIO::blockSize() const { return _blockSize; }
@ -378,9 +378,9 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
// write back out partial block // write back out partial block
req.dataLen = partialBlock; req.dataLen = partialBlock;
bool wrRes = cacheWriteOneBlock(req); int wrRes = cacheWriteOneBlock(req);
if ((rdSz < 0) || (!wrRes)) { if ((rdSz < 0) || (wrRes)) {
// rwarning - unlikely to ever occur.. // rwarning - unlikely to ever occur..
RLOG(WARNING) << "truncate failure: read " << rdSz RLOG(WARNING) << "truncate failure: read " << rdSz
<< " bytes, partial block of " << partialBlock; << " bytes, partial block of " << partialBlock;

View File

@ -43,7 +43,7 @@ class BlockFileIO : public FileIO {
// implemented in terms of blocks. // implemented in terms of blocks.
virtual ssize_t read(const IORequest &req) const; virtual ssize_t read(const IORequest &req) const;
virtual bool write(const IORequest &req); virtual int write(const IORequest &req);
virtual int blockSize() const; virtual int blockSize() const;
@ -54,10 +54,10 @@ class BlockFileIO : public FileIO {
// same as read(), except that the request.offset field is guarenteed to be // same as read(), except that the request.offset field is guarenteed to be
// block aligned, and the request size will not be larger then 1 block. // block aligned, and the request size will not be larger then 1 block.
virtual ssize_t readOneBlock(const IORequest &req) const = 0; virtual ssize_t readOneBlock(const IORequest &req) const = 0;
virtual bool writeOneBlock(const IORequest &req) = 0; virtual int writeOneBlock(const IORequest &req) = 0;
ssize_t cacheReadOneBlock(const IORequest &req) const; ssize_t cacheReadOneBlock(const IORequest &req) const;
bool cacheWriteOneBlock(const IORequest &req); int cacheWriteOneBlock(const IORequest &req);
int _blockSize; int _blockSize;
bool _allowHoles; bool _allowHoles;

View File

@ -346,12 +346,12 @@ ssize_t CipherFileIO::readOneBlock(const IORequest &req) const {
return readSize; return readSize;
} }
bool CipherFileIO::writeOneBlock(const IORequest &req) { int CipherFileIO::writeOneBlock(const IORequest &req) {
if (haveHeader && fsConfig->reverseEncryption) { if (haveHeader && fsConfig->reverseEncryption) {
VLOG(1) VLOG(1)
<< "writing to a reverse mount with per-file IVs is not implemented"; << "writing to a reverse mount with per-file IVs is not implemented";
return false; return -EPERM;
} }
int bs = blockSize(); int bs = blockSize();
@ -366,19 +366,20 @@ bool CipherFileIO::writeOneBlock(const IORequest &req) {
ok = blockWrite(req.data, (int)req.dataLen, blockNum ^ fileIV); ok = blockWrite(req.data, (int)req.dataLen, blockNum ^ fileIV);
} }
int res = 0;
if (ok) { if (ok) {
if (haveHeader) { if (haveHeader) {
IORequest tmpReq = req; IORequest tmpReq = req;
tmpReq.offset += HEADER_SIZE; tmpReq.offset += HEADER_SIZE;
ok = base->write(tmpReq); res = base->write(tmpReq);
} else } else
ok = base->write(req); res = base->write(req);
} else { } else {
VLOG(1) << "encodeBlock failed for block " << blockNum << ", size " VLOG(1) << "encodeBlock failed for block " << blockNum << ", size "
<< req.dataLen; << req.dataLen;
ok = false; res = -EBADMSG;
} }
return ok; return res;
} }
bool CipherFileIO::blockWrite(unsigned char *buf, int size, bool CipherFileIO::blockWrite(unsigned char *buf, int size,

View File

@ -65,7 +65,7 @@ class CipherFileIO : public BlockFileIO {
private: private:
virtual ssize_t readOneBlock(const IORequest &req) const; virtual ssize_t readOneBlock(const IORequest &req) const;
virtual bool writeOneBlock(const IORequest &req); virtual int writeOneBlock(const IORequest &req);
virtual void generateReverseHeader(unsigned char *data); virtual void generateReverseHeader(unsigned char *data);
void initHeader(); void initHeader();

View File

@ -68,7 +68,7 @@ class FileIO {
virtual off_t getSize() const = 0; virtual off_t getSize() const = 0;
virtual ssize_t read(const IORequest &req) const = 0; virtual ssize_t read(const IORequest &req) const = 0;
virtual bool write(const IORequest &req) = 0; virtual int write(const IORequest &req) = 0;
virtual int truncate(off_t size) = 0; virtual int truncate(off_t size) = 0;

View File

@ -209,7 +209,7 @@ ssize_t FileNode::read(off_t offset, unsigned char *data, ssize_t size) const {
return io->read(req); return io->read(req);
} }
bool FileNode::write(off_t offset, unsigned char *data, ssize_t size) { int FileNode::write(off_t offset, unsigned char *data, ssize_t size) {
VLOG(1) << "FileNode::write offset " << offset << ", data size " << size; VLOG(1) << "FileNode::write offset " << offset << ", data size " << size;
IORequest req; IORequest req;

View File

@ -68,7 +68,7 @@ class FileNode {
off_t getSize() const; off_t getSize() const;
ssize_t read(off_t offset, unsigned char *data, ssize_t size) const; ssize_t read(off_t offset, unsigned char *data, ssize_t size) const;
bool write(off_t offset, unsigned char *data, ssize_t size); int write(off_t offset, unsigned char *data, ssize_t size);
// truncate the file to a particular size // truncate the file to a particular size
int truncate(off_t size); int truncate(off_t size);

View File

@ -208,7 +208,7 @@ ssize_t MACFileIO::readOneBlock(const IORequest &req) const {
return readSize; return readSize;
} }
bool MACFileIO::writeOneBlock(const IORequest &req) { int MACFileIO::writeOneBlock(const IORequest &req) {
int headerSize = macBytes + randBytes; int headerSize = macBytes + randBytes;
int bs = blockSize() + headerSize; int bs = blockSize() + headerSize;
@ -225,7 +225,7 @@ bool MACFileIO::writeOneBlock(const IORequest &req) {
memcpy(newReq.data + headerSize, req.data, req.dataLen); memcpy(newReq.data + headerSize, req.data, req.dataLen);
if (randBytes > 0) { if (randBytes > 0) {
if (!cipher->randomize(newReq.data + macBytes, randBytes, false)) if (!cipher->randomize(newReq.data + macBytes, randBytes, false))
return false; return -EBADMSG;
} }
if (macBytes > 0) { if (macBytes > 0) {
@ -240,11 +240,11 @@ bool MACFileIO::writeOneBlock(const IORequest &req) {
} }
// now, we can let the next level have it.. // now, we can let the next level have it..
bool ok = base->write(newReq); int res = base->write(newReq);
MemoryPool::release(mb); MemoryPool::release(mb);
return ok; return res;
} }
int MACFileIO::truncate(off_t size) { int MACFileIO::truncate(off_t size) {

View File

@ -64,7 +64,7 @@ class MACFileIO : public BlockFileIO {
private: private:
virtual ssize_t readOneBlock(const IORequest &req) const; virtual ssize_t readOneBlock(const IORequest &req) const;
virtual bool writeOneBlock(const IORequest &req); virtual int writeOneBlock(const IORequest &req);
std::shared_ptr<FileIO> base; std::shared_ptr<FileIO> base;
std::shared_ptr<Cipher> cipher; std::shared_ptr<Cipher> cipher;

View File

@ -206,7 +206,7 @@ ssize_t RawFileIO::read(const IORequest &req) const {
return readSize; return readSize;
} }
bool RawFileIO::write(const IORequest &req) { int RawFileIO::write(const IORequest &req) {
rAssert(fd >= 0); rAssert(fd >= 0);
rAssert(true == canWrite); rAssert(true == canWrite);
@ -215,14 +215,17 @@ bool RawFileIO::write(const IORequest &req) {
ssize_t bytes = req.dataLen; ssize_t bytes = req.dataLen;
off_t offset = req.offset; off_t offset = req.offset;
int eno = 0;
while (bytes && retrys > 0) { while (bytes && retrys > 0) {
errno = 0;
ssize_t writeSize = ::pwrite(fd, buf, bytes, offset); ssize_t writeSize = ::pwrite(fd, buf, bytes, offset);
eno = errno;
if (writeSize < 0) { if (writeSize < 0) {
knownSize = false; knownSize = false;
RLOG(WARNING) << "write failed at offset " << offset << " for " << bytes RLOG(WARNING) << "write failed at offset " << offset << " for " << bytes
<< " bytes: " << strerror(errno); << " bytes: " << strerror(eno);
return false; return -eno;
} }
bytes -= writeSize; bytes -= writeSize;
@ -235,14 +238,14 @@ bool RawFileIO::write(const IORequest &req) {
RLOG(ERROR) << "Write error: wrote " << req.dataLen - bytes << " bytes of " RLOG(ERROR) << "Write error: wrote " << req.dataLen - bytes << " bytes of "
<< req.dataLen << ", max retries reached"; << req.dataLen << ", max retries reached";
knownSize = false; knownSize = false;
return false; return (eno) ? -eno : -EIO;
} else { } else {
if (knownSize) { if (knownSize) {
off_t last = req.offset + req.dataLen; off_t last = req.offset + req.dataLen;
if (last > fileSize) fileSize = last; if (last > fileSize) fileSize = last;
} }
return true; return 0;
} }
} }

View File

@ -46,7 +46,7 @@ class RawFileIO : public FileIO {
virtual off_t getSize() const; virtual off_t getSize() const;
virtual ssize_t read(const IORequest &req) const; virtual ssize_t read(const IORequest &req) const;
virtual bool write(const IORequest &req); virtual int write(const IORequest &req);
virtual int truncate(off_t size); virtual int truncate(off_t size);

View File

@ -619,10 +619,11 @@ int encfs_fsync(const char *path, int dataSync, struct fuse_file_info *file) {
} }
int _do_write(FileNode *fnode, unsigned char *ptr, size_t size, off_t offset) { int _do_write(FileNode *fnode, unsigned char *ptr, size_t size, off_t offset) {
if (fnode->write(offset, ptr, size)) int res = fnode->write(offset, ptr, size);
if (!res)
return size; return size;
else else
return -EIO; return res;
} }
int encfs_write(const char *path, const char *buf, size_t size, off_t offset, int encfs_write(const char *path, const char *buf, size_t size, off_t offset,