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) {
// extend file first to fill hole with 0's..
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
@ -244,7 +246,10 @@ int BlockFileIO::write(const IORequest &req) {
} else {
// have to merge with existing block data..
blockReq.dataLen = _blockSize;
blockReq.dataLen = cacheReadOneBlock(blockReq);
if ((blockReq.dataLen = cacheReadOneBlock(blockReq)) < 0) {
res = blockReq.dataLen;
break;
}
// extend data if necessary..
if (partialOffset + toCopy > blockReq.dataLen)
@ -274,10 +279,11 @@ int BlockFileIO::write(const IORequest &req) {
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 newLastBlock = newSize / _blockSize;
int newBlockSize = newSize % _blockSize;
int res = 0;
IORequest req;
MemBlock mb;
@ -296,9 +302,10 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
if (outSize) {
memset(mb.data, 0, outSize);
cacheReadOneBlock(req);
req.dataLen = outSize;
cacheWriteOneBlock(req);
if ((res = cacheReadOneBlock(req)) >= 0) {
req.dataLen = outSize;
res = cacheWriteOneBlock(req);
}
}
} else
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) {
VLOG(1) << "padding block " << oldLastBlock;
memset(mb.data, 0, _blockSize);
cacheReadOneBlock(req);
req.dataLen = _blockSize; // expand to full block size
cacheWriteOneBlock(req);
if ((res = cacheReadOneBlock(req)) >= 0) {
req.dataLen = _blockSize; // expand to full block size
res = cacheWriteOneBlock(req);
}
++oldLastBlock;
}
// 2, pad zero blocks unless holes are allowed
if (!_allowHoles) {
for (; oldLastBlock != newLastBlock; ++oldLastBlock) {
for (; !res && (oldLastBlock != newLastBlock); ++oldLastBlock) {
VLOG(1) << "padding block " << oldLastBlock;
req.offset = oldLastBlock * _blockSize;
req.dataLen = _blockSize;
memset(mb.data, 0, req.dataLen);
cacheWriteOneBlock(req);
res = cacheWriteOneBlock(req);
}
}
// 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.dataLen = newBlockSize;
memset(mb.data, 0, req.dataLen);
cacheWriteOneBlock(req);
res = cacheWriteOneBlock(req);
}
}
if (mb.data) MemoryPool::release(mb);
return res;
}
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.
// do the truncate so that the underlying filesystem can allocate
// 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;
padFile(oldSize, size, forceWrite);
if (!res)
res = padFile(oldSize, size, forceWrite);
} else if (size == oldSize) {
// the easiest case, but least likely....
} else if (partialBlock) {
@ -376,19 +387,17 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
req.data = mb.data;
ssize_t rdSz = cacheReadOneBlock(req);
if (rdSz < 0)
res = rdSz;
// do the truncate
if (base) res = base->truncate(size);
else if (base)
res = base->truncate(size);
// write back out partial block
req.dataLen = partialBlock;
int wrRes = cacheWriteOneBlock(req);
if ((rdSz < 0) || (wrRes)) {
// rwarning - unlikely to ever occur..
RLOG(WARNING) << "truncate failure: read " << rdSz
<< " bytes, partial block of " << partialBlock;
}
if (!res)
res = cacheWriteOneBlock(req);
MemoryPool::release(mb);
} else {

View File

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

View File

@ -253,7 +253,7 @@ int MACFileIO::truncate(off_t size) {
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;
}