Verify open/read/write/truncate returned values

This commit is contained in:
benrubson 2017-03-20 14:23:19 +01:00
parent b88da06a08
commit 13ae4de830
4 changed files with 62 additions and 54 deletions

View File

@ -195,7 +195,9 @@ int BlockFileIO::write(const IORequest &req) {
if (req.offset > fileSize) { if (req.offset > fileSize) {
// extend file first to fill hole with 0's.. // extend file first to fill hole with 0's..
const bool forceWrite = false; const bool forceWrite = false;
padFile(fileSize, req.offset, forceWrite); int res = padFile(fileSize, req.offset, forceWrite);
if (res)
return res;
} }
// check against edge cases where we can just let the base class handle the // check against edge cases where we can just let the base class handle the
@ -244,7 +246,10 @@ int BlockFileIO::write(const IORequest &req) {
} else { } else {
// have to merge with existing block data.. // have to merge with existing block data..
blockReq.dataLen = _blockSize; blockReq.dataLen = _blockSize;
blockReq.dataLen = cacheReadOneBlock(blockReq); if ((blockReq.dataLen = cacheReadOneBlock(blockReq)) < 0) {
res = blockReq.dataLen;
break;
}
// extend data if necessary.. // extend data if necessary..
if (partialOffset + toCopy > blockReq.dataLen) if (partialOffset + toCopy > blockReq.dataLen)
@ -274,10 +279,11 @@ int BlockFileIO::write(const IORequest &req) {
int BlockFileIO::blockSize() const { return _blockSize; } int BlockFileIO::blockSize() const { return _blockSize; }
void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) { int BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
off_t oldLastBlock = oldSize / _blockSize; off_t oldLastBlock = oldSize / _blockSize;
off_t newLastBlock = newSize / _blockSize; off_t newLastBlock = newSize / _blockSize;
int newBlockSize = newSize % _blockSize; int newBlockSize = newSize % _blockSize;
int res = 0;
IORequest req; IORequest req;
MemBlock mb; MemBlock mb;
@ -296,9 +302,10 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
if (outSize) { if (outSize) {
memset(mb.data, 0, outSize); memset(mb.data, 0, outSize);
cacheReadOneBlock(req); if ((res = cacheReadOneBlock(req)) >= 0) {
req.dataLen = outSize; req.dataLen = outSize;
cacheWriteOneBlock(req); res = cacheWriteOneBlock(req);
}
} }
} else } else
VLOG(1) << "optimization: not padding last block"; VLOG(1) << "optimization: not padding last block";
@ -317,33 +324,36 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
if (req.dataLen != 0) { if (req.dataLen != 0) {
VLOG(1) << "padding block " << oldLastBlock; VLOG(1) << "padding block " << oldLastBlock;
memset(mb.data, 0, _blockSize); memset(mb.data, 0, _blockSize);
cacheReadOneBlock(req); if ((res = cacheReadOneBlock(req)) >= 0) {
req.dataLen = _blockSize; // expand to full block size req.dataLen = _blockSize; // expand to full block size
cacheWriteOneBlock(req); res = cacheWriteOneBlock(req);
}
++oldLastBlock; ++oldLastBlock;
} }
// 2, pad zero blocks unless holes are allowed // 2, pad zero blocks unless holes are allowed
if (!_allowHoles) { if (!_allowHoles) {
for (; oldLastBlock != newLastBlock; ++oldLastBlock) { for (; !res && (oldLastBlock != newLastBlock); ++oldLastBlock) {
VLOG(1) << "padding block " << oldLastBlock; VLOG(1) << "padding block " << oldLastBlock;
req.offset = oldLastBlock * _blockSize; req.offset = oldLastBlock * _blockSize;
req.dataLen = _blockSize; req.dataLen = _blockSize;
memset(mb.data, 0, req.dataLen); memset(mb.data, 0, req.dataLen);
cacheWriteOneBlock(req); res = cacheWriteOneBlock(req);
} }
} }
// 3. only necessary if write is forced and block is non 0 length // 3. only necessary if write is forced and block is non 0 length
if (forceWrite && newBlockSize) { if (!res && forceWrite && newBlockSize) {
req.offset = newLastBlock * _blockSize; req.offset = newLastBlock * _blockSize;
req.dataLen = newBlockSize; req.dataLen = newBlockSize;
memset(mb.data, 0, req.dataLen); memset(mb.data, 0, req.dataLen);
cacheWriteOneBlock(req); res = cacheWriteOneBlock(req);
} }
} }
if (mb.data) MemoryPool::release(mb); if (mb.data) MemoryPool::release(mb);
return res;
} }
int BlockFileIO::truncateBase(off_t size, FileIO *base) { int BlockFileIO::truncateBase(off_t size, FileIO *base) {
@ -357,10 +367,11 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
// states that it will pad with 0's. // states that it will pad with 0's.
// do the truncate so that the underlying filesystem can allocate // do the truncate so that the underlying filesystem can allocate
// the space, and then we'll fill it in padFile.. // the space, and then we'll fill it in padFile..
if (base) base->truncate(size); if (base) res = base->truncate(size);
const bool forceWrite = true; const bool forceWrite = true;
padFile(oldSize, size, forceWrite); if (!res)
res = padFile(oldSize, size, forceWrite);
} else if (size == oldSize) { } else if (size == oldSize) {
// the easiest case, but least likely.... // the easiest case, but least likely....
} else if (partialBlock) { } else if (partialBlock) {
@ -376,19 +387,17 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
req.data = mb.data; req.data = mb.data;
ssize_t rdSz = cacheReadOneBlock(req); ssize_t rdSz = cacheReadOneBlock(req);
if (rdSz < 0)
res = rdSz;
// do the truncate // do the truncate
if (base) res = base->truncate(size); else if (base)
res = base->truncate(size);
// write back out partial block // write back out partial block
req.dataLen = partialBlock; req.dataLen = partialBlock;
int wrRes = cacheWriteOneBlock(req); if (!res)
res = cacheWriteOneBlock(req);
if ((rdSz < 0) || (wrRes)) {
// rwarning - unlikely to ever occur..
RLOG(WARNING) << "truncate failure: read " << rdSz
<< " bytes, partial block of " << partialBlock;
}
MemoryPool::release(mb); MemoryPool::release(mb);
} else { } else {

View File

@ -49,7 +49,7 @@ class BlockFileIO : public FileIO {
protected: protected:
int truncateBase(off_t size, FileIO *base); int truncateBase(off_t size, FileIO *base);
void padFile(off_t oldSize, off_t newSize, bool forceWrite); int padFile(off_t oldSize, off_t newSize, bool forceWrite);
// 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.

View File

@ -95,20 +95,20 @@ bool CipherFileIO::setIV(uint64_t iv) {
} else if (haveHeader) { } else if (haveHeader) {
// we have an old IV, and now a new IV, so we need to update the fileIV // we have an old IV, and now a new IV, so we need to update the fileIV
// on disk. // on disk.
if (fileIV == 0) { // ensure the file is open for read/write..
// ensure the file is open for read/write.. int newFlags = lastFlags | O_RDWR;
int newFlags = lastFlags | O_RDWR; int res = base->open(newFlags);
int res = base->open(newFlags); if (res < 0) {
if (res < 0) { if (res == -EISDIR) {
if (res == -EISDIR) { // duh -- there are no file headers for directories!
// duh -- there are no file headers for directories! externalIV = iv;
externalIV = iv; return base->setIV(iv);
return base->setIV(iv); } else {
} else { VLOG(1) << "setIV failed to re-open for write";
VLOG(1) << "writeHeader failed to re-open for write"; return false;
return false;
}
} }
}
if (fileIV == 0) {
if (initHeader() < 0) if (initHeader() < 0)
return false; return false;
} }
@ -184,7 +184,9 @@ int CipherFileIO::initHeader() {
req.offset = 0; req.offset = 0;
req.data = buf; req.data = buf;
req.dataLen = 8; req.dataLen = 8;
base->read(req); ssize_t readSize = base->read(req);
if(readSize < 0)
return readSize;
if(!cipher->streamDecode(buf, sizeof(buf), externalIV, key)) if(!cipher->streamDecode(buf, sizeof(buf), externalIV, key))
return -EBADMSG; return -EBADMSG;
@ -219,7 +221,9 @@ int CipherFileIO::initHeader() {
req.data = buf; req.data = buf;
req.dataLen = 8; req.dataLen = 8;
base->write(req); int res = base->write(req);
if (res)
return res;
} else { } else {
VLOG(1) << "base not writable, IV not written.."; VLOG(1) << "base not writable, IV not written..";
} }
@ -229,15 +233,6 @@ int CipherFileIO::initHeader() {
} }
bool CipherFileIO::writeHeader() { bool CipherFileIO::writeHeader() {
if (!base->isWritable()) {
// open for write..
int newFlags = lastFlags | O_RDWR;
if (base->open(newFlags) < 0) {
VLOG(1) << "writeHeader failed to re-open for write";
return false;
}
}
if (fileIV == 0) { if (fileIV == 0) {
RLOG(ERROR) << "Internal error: fileIV == 0 in writeHeader!!!"; RLOG(ERROR) << "Internal error: fileIV == 0 in writeHeader!!!";
} }
@ -257,7 +252,8 @@ bool CipherFileIO::writeHeader() {
req.data = buf; req.data = buf;
req.dataLen = 8; req.dataLen = 8;
base->write(req); if (base->write(req))
return false;
return true; return true;
} }
@ -351,7 +347,7 @@ ssize_t CipherFileIO::readOneBlock(const IORequest &req) const {
<< readSize; << readSize;
readSize = -EBADMSG; readSize = -EBADMSG;
} }
} else { } else if (readSize == 0) {
VLOG(1) << "readSize zero for offset " << req.offset; VLOG(1) << "readSize zero for offset " << req.offset;
} }
@ -450,8 +446,11 @@ int CipherFileIO::truncate(off_t size) {
if (!base->isWritable()) { if (!base->isWritable()) {
// open for write.. // open for write..
int newFlags = lastFlags | O_RDWR; int newFlags = lastFlags | O_RDWR;
if (base->open(newFlags) < 0) int res = base->open(newFlags);
VLOG(1) << "writeHeader failed to re-open for write"; if (res < 0) {
VLOG(1) << "truncate failed to re-open for write";
return res;
}
} }
int res = initHeader(); int res = initHeader();
if (res < 0) if (res < 0)
@ -462,7 +461,7 @@ int CipherFileIO::truncate(off_t size) {
// the wrong size.. // the wrong size..
res = BlockFileIO::truncateBase(size, 0); res = BlockFileIO::truncateBase(size, 0);
if (res == 0) base->truncate(size + HEADER_SIZE); if (res == 0) res = base->truncate(size + HEADER_SIZE);
} }
return res; return res;
} }

View File

@ -253,7 +253,7 @@ int MACFileIO::truncate(off_t size) {
int res = BlockFileIO::truncateBase(size, 0); int res = BlockFileIO::truncateBase(size, 0);
if (res == 0) base->truncate(locWithHeader(size, bs, headerSize)); if (res == 0) res = base->truncate(locWithHeader(size, bs, headerSize));
return res; return res;
} }