view release on metacpan or search on metacpan
libjio/bindings/preload/libjio_preload.c view on Meta::CPAN
fd_table[fd].fd = fd;
fd_table[fd].refcount = malloc(sizeof(unsigned int));
*fd_table[fd].refcount = 1;
fd_table[fd].fs = fs;
fd_unlock(fd);
printd("return %d\n", fd);
return fd;
}
/* close() is split in two functions: unlocked_close() that performs the real
* actual close and cleanup, and close() which takes care of the locking and
* calls unlocked_close(); this is because in dup*() we need to close with
* locks already held to avoid races. */
int unlocked_close(int fd)
{
int r;
if (*fd_table[fd].refcount > 1) {
/* we still have references, don't really close */
printd("not closing, refcount: %d\n", *fd_table[fd].refcount);
(*fd_table[fd].refcount)--;
fd_table[fd].fd = -1;
fd_table[fd].refcount = NULL;
fd_table[fd].fs = NULL;
libjio/bindings/preload/libjio_preload.c view on Meta::CPAN
return -1;
}
fs = fd_table[fd].fs;
if (fs == NULL) {
printd("NULL fs, fd %d\n", fd);
fd_unlock(fd);
return (*c_close)(fd);
}
printd("libjio\n");
r = unlocked_close(fd);
fd_unlock(fd);
printd("return %d\n", r);
return r;
}
int unlink(const char *pathname)
{
int r;
libjio/bindings/preload/libjio_preload.c view on Meta::CPAN
printd("libjio\n");
rec_inc();
r = (*c_dup2)(oldfd, newfd);
rec_dec();
if (r >= 0) {
fd_lock(newfd);
if (fd_table[newfd].fs != NULL) {
unlocked_close(newfd);
}
fd_table[newfd].fd = newfd;
fd_table[newfd].refcount = fd_table[oldfd].refcount;
(*fd_table[newfd].refcount)++;
fd_table[newfd].fs = fd_table[oldfd].fs;
fd_unlock(newfd);
}
fd_unlock(oldfd);
printd("return %d\n", r);
libjio/libjio/check.c view on Meta::CPAN
if (tfd < 0) {
if (errno == ENOENT) {
res->invalid++;
goto nounlink_loop;
} else {
ret = J_EIO;
goto exit;
}
}
/* try to lock the transaction file, if it's locked then it is
* currently being used so we skip it */
lr = plockf(tfd, F_TLOCKW, 0, 0);
if (lr == -1) {
res->in_progress++;
goto loop;
}
filelen = lseek(tfd, 0, SEEK_END);
if (filelen == 0) {
res->broken++;
libjio/libjio/libjio.h view on Meta::CPAN
* @see jtrans_free()
* @ingroup basic
*/
jtrans_t *jtrans_new(jfs_t *fs, unsigned int flags);
/** Add a write operation to a transaction.
*
* A write operation consists of a buffer, its length, and the offset to write
* it to.
*
* The file will not be touched (not even locked) until commit time, where the
* first count bytes of buf will be written at offset.
*
* Operations will be applied in order, and overlapping operations are
* permitted, in which case the latest one will prevail.
*
* The buffer will be copied internally and can be free()d right after this
* function returns.
*
* @param ts transaction
* @param buf buffer to write
libjio/libjio/libjio.h view on Meta::CPAN
* @returns 0 on success, -1 on error
* @ingroup basic
*/
int jtrans_add_w(jtrans_t *ts, const void *buf, size_t count, off_t offset);
/** Add a read operation to a transaction.
*
* An operation consists of a buffer, its length, and the offset to read it
* from.
*
* The file will not be touched (not even locked) until commit time, where the
* first count bytes at offset will be read into buf.
*
* Note that if there is not enough data in the file to read the specified
* amount of bytes, the commit will fail, so do not attempt to read beyond EOF
* (you can use jread() for that purpose).
*
* Operations will be applied in order, and overlapping operations are
* permitted, in which case the latest one will prevail.
*
* In case of an error in jtrans_commit(), the contents of the buffer are
libjio/libjio/trans.c view on Meta::CPAN
for (op = start_op; op != NULL; op = op->next) {
if (min_offset < op->offset)
continue;
min_offset = op->offset;
start_op = op->next;
if (mode == F_LOCKW) {
lr = plockf(ts->fs->fd, F_LOCKW, op->offset, op->len);
if (lr == -1)
goto error;
op->locked = 1;
} else if (mode == F_UNLOCK && op->locked) {
lr = plockf(ts->fs->fd, F_UNLOCK, op->offset,
op->len);
if (lr == -1)
goto error;
op->locked = 0;
}
}
nops++;
}
return 0;
error:
return -1;
libjio/libjio/trans.c view on Meta::CPAN
tmpop->next = op;
op->prev = tmpop;
}
pthread_mutex_unlock(&(ts->lock));
op->len = count;
op->offset = offset;
op->plen = 0;
op->pdata = NULL;
op->locked = 0;
op->direction = direction;
if (direction == D_WRITE) {
memcpy(op->buf, buf, count);
if (!(ts->flags & J_NOROLLBACK)) {
/* jtrans_commit() will want to read the current data,
* so we tell the kernel about that */
posix_fadvise(ts->fs->fd, offset, count,
POSIX_FADV_WILLNEED);
libjio/libjio/trans.c view on Meta::CPAN
rv = -1;
goto exit;
}
curop->offset = op->offset;
curop->len = op->plen;
curop->buf = op->pdata;
curop->plen = op->plen;
curop->pdata = op->pdata;
curop->direction = op->direction;
curop->locked = 0;
newts->numops_w++;
newts->len_w += curop->len;
/* add the new transaction to the list */
if (newts->op == NULL) {
newts->op = curop;
curop->prev = NULL;
curop->next = NULL;
} else {
libjio/libjio/trans.h view on Meta::CPAN
};
/** Possible operation directions */
enum op_direction {
D_READ = 1,
D_WRITE = 2,
};
/** A single operation */
struct operation {
/** Is the region locked? */
int locked;
/** Operation's offset */
off_t offset;
/** Data length, in bytes */
size_t len;
/** Data buffer */
void *buf;
libjio/tests/stress/jiostress view on Meta::CPAN
# public
self.start, self.end = randfrange(fsize, maxlen)
self.new_data = None
self.type = 'r'
# private
self.prev_data = None
self.new_data_ctx = None
self.read_buf = None
self.lockmgr = lockmgr
self.locked = False
# read an extended range so we can check we
# only wrote what we were supposed to
self.ext_start = max(0, self.start - 32)
self.ext_end = min(fsize, self.end + 32)
def __lt__(self, other):
return self.ext_start < other.ext_start
def __del__(self):
if self.locked:
self.lockmgr.unlock(self.ext_start, self.ext_end)
def overlaps(self, other):
if (other.ext_start <= self.ext_start <= other.ext_end) or \
(other.ext_start <= self.ext_end <= other.ext_end) or \
(self.ext_start <= other.ext_start <= self.ext_end) or \
(self.ext_start <= other.ext_end <= self.ext_end):
return True
return False
def prepare_r(self):
self.type = 'r'
self.read_buf = bytearray(self.end - self.start)
self.lockmgr.lock(self.ext_start, self.ext_end)
self.locked = True
def verify_r(self, fd):
real_data = pread(fd, self.start, self.end)
if real_data != self.read_buf:
print('Corruption detected')
self.show(fd)
raise ConsistencyError
def prepare_w(self, fd):
self.type = 'w'
self.lockmgr.lock(self.ext_start, self.ext_end)
self.locked = True
self.prev_data = pread(fd, self.ext_start, self.ext_end)
self.new_data = getbytes(self.end - self.start)
self.new_data_ctx = \
self.prev_data[:self.start - self.ext_start] \
+ self.new_data \
+ self.prev_data[- (self.ext_end - self.end):]
return self.new_data, self.start