void lte_decrement_refcnt(struct lookup_table_entry *lte,
struct lookup_table *table)
{
- wimlib_assert(lte);
- wimlib_assert(lte->refcnt);
+ wimlib_assert(lte != NULL);
+ wimlib_assert(lte->refcnt != 0);
if (--lte->refcnt == 0) {
lookup_table_unlink(table, lte);
#ifdef WITH_FUSE
#ifdef WITH_FUSE
void lte_decrement_num_opened_fds(struct lookup_table_entry *lte)
{
- wimlib_assert(lte);
- wimlib_assert(lte->num_opened_fds);
- if (--lte->num_opened_fds == 0 && lte->refcnt == 0)
+ wimlib_assert(lte != NULL);
+ wimlib_assert(lte->num_opened_fds != 0);
+ if (atomic_dec(<e->num_opened_fds) == 0 && lte->refcnt == 0)
finalize_lte(lte);
}
#endif
{
static const u16 fds_per_alloc = 8;
static const u16 max_fds = 0xffff;
+ int ret;
+
+ pthread_mutex_lock(&inode->i_mutex);
DEBUG("Allocating fd for stream ID %u from inode %lx (open = %u, allocated = %u)",
stream_id, inode->ino, inode->num_opened_fds,
struct wimlib_fd **fds;
u16 num_new_fds;
- if (inode->num_allocated_fds == max_fds)
- return -EMFILE;
+ if (inode->num_allocated_fds == max_fds) {
+ ret = -EMFILE;
+ goto out;
+ }
num_new_fds = min(fds_per_alloc,
max_fds - inode->num_allocated_fds);
fds = REALLOC(inode->fds,
(inode->num_allocated_fds + num_new_fds) *
sizeof(inode->fds[0]));
- if (!fds)
- return -ENOMEM;
+ if (!fds) {
+ ret = -ENOMEM;
+ goto out;
+ }
memset(&fds[inode->num_allocated_fds], 0,
num_new_fds * sizeof(fds[0]));
inode->fds = fds;
for (u16 i = 0; ; i++) {
if (!inode->fds[i]) {
struct wimlib_fd *fd = CALLOC(1, sizeof(*fd));
- if (!fd)
- return -ENOMEM;
+ if (!fd) {
+ ret = -ENOMEM;
+ break;
+ }
fd->f_inode = inode;
fd->f_lte = lte;
fd->staging_fd = -1;
inode->fds[i] = fd;
inode->num_opened_fds++;
if (lte)
- lte->num_opened_fds++;
+ atomic_inc(<e->num_opened_fds);
DEBUG("Allocated fd (idx = %u)", fd->idx);
- return 0;
+ ret = 0;
+ break;
}
}
+out:
+ pthread_mutex_unlock(&inode->i_mutex);
+ return ret;
}
static void inode_put_fd(struct inode *inode, struct wimlib_fd *fd)
{
wimlib_assert(fd != NULL);
wimlib_assert(inode != NULL);
+
+ pthread_mutex_lock(&inode->i_mutex);
+
wimlib_assert(fd->f_inode == inode);
wimlib_assert(inode->num_opened_fds != 0);
wimlib_assert(fd->idx < inode->num_allocated_fds);
inode->fds[fd->idx] = NULL;
FREE(fd);
- if (--inode->num_opened_fds == 0 && inode->link_count == 0)
+ if (--inode->num_opened_fds == 0 && inode->link_count == 0) {
+ pthread_mutex_unlock(&inode->i_mutex);
free_inode(inode);
+ } else {
+ pthread_mutex_unlock(&inode->i_mutex);
+ }
}
static int lte_put_fd(struct lookup_table_entry *lte, struct wimlib_fd *fd)
{
- wimlib_assert(fd);
+ wimlib_assert(fd != NULL);
wimlib_assert(fd->f_lte == lte);
if (!lte) /* Empty stream with no lookup table entry */
static int close_wimlib_fd(struct wimlib_fd *fd)
{
int ret;
- wimlib_assert(fd);
+ wimlib_assert(fd != NULL);
DEBUG("Closing fd (inode = %lu, opened = %u, allocated = %u)",
fd->f_inode->ino, fd->f_inode->num_opened_fds,
fd->f_inode->num_allocated_fds);
argv[argc++] = "imagex";
argv[argc++] = dir_copy;
- argv[argc++] = "-s"; /* disable multi-threaded operation */
+
+ /* disable multi-threaded operation for read-write mounts */
+ if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
+ argv[argc++] = "-s";
if (flags & WIMLIB_MOUNT_FLAG_DEBUG)
argv[argc++] = "-d";
# define HOT
#endif /* __GNUC__ */
+#ifdef WITH_FUSE
+/*
+ * Compare-and-swap. Equivalent to the folliwng, but executed
+ * atomically:
+ *
+ * Q tmp = *ptr;
+ * if (tmp == oval)
+ * *ptr = nval;
+ * return tmp;
+ */
+#define atomic_inc(ptr) \
+ __sync_fetch_and_add(ptr, 1)
+
+#define atomic_dec(ptr) \
+ __sync_sub_and_fetch(ptr, 1)
+
+#define cas(ptr, oval, nval) \
+ __sync_val_compare_and_swap(ptr, oval, nval);
+
+#define cas_bool(ptr, oval, nval) \
+ __sync_bool_compare_and_swap(ptr, oval, nval);
+#endif
+
#ifndef _NTFS_TYPES_H
typedef uint8_t u8;
typedef uint16_t u16;