X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fmount.c;h=dc1e7d91b6faa59f610a255ee9147f11af24fb4f;hp=834d5855303d7b42c59f3afa71e2696980312c99;hb=051a59e4c6d114fc7abfa14ff78436adab5defb9;hpb=1596d7ad7bf93f0e326b070a173a59004ab9b649 diff --git a/src/mount.c b/src/mount.c index 834d5855..dc1e7d91 100644 --- a/src/mount.c +++ b/src/mount.c @@ -146,6 +146,9 @@ static int alloc_wimlib_fd(struct inode *inode, { 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, @@ -155,16 +158,20 @@ static int alloc_wimlib_fd(struct inode *inode, 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; @@ -173,8 +180,10 @@ static int alloc_wimlib_fd(struct inode *inode, 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; @@ -184,17 +193,24 @@ static int alloc_wimlib_fd(struct inode *inode, 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); @@ -202,13 +218,17 @@ static void inode_put_fd(struct inode *inode, struct wimlib_fd *fd) 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 */ @@ -232,7 +252,7 @@ static int lte_put_fd(struct lookup_table_entry *lte, struct wimlib_fd *fd) 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); @@ -477,11 +497,9 @@ out_delete_staging_file: } /* - * Creates a randomly named staging directory and returns its name into the - * static variable staging_dir_name. - * - * If the staging directory cannot be created, staging_dir_name is set to NULL. - * */ + * Creates a randomly named staging directory and saves its name in the + * filesystem context structure. + */ static int make_staging_dir(struct wimfs_context *ctx) { /* XXX Give the user an option of where to stage files */ @@ -856,7 +874,7 @@ static int rebuild_wim(struct wimfs_context *ctx, bool check_integrity) DEBUG("Closing all staging file descriptors."); - list_for_each_entry(lte, &ctx->staging_list, staging_list) { + list_for_each_entry_safe(lte, tmp, &ctx->staging_list, staging_list) { ret = inode_close_fds(lte->lte_inode); if (ret != 0) return ret; @@ -1038,7 +1056,8 @@ static int wimfs_getxattr(const char *path, const char *name, char *value, if (res_size > size) return -ERANGE; - ret = read_full_wim_resource(lte, (u8*)value); + ret = read_full_wim_resource(lte, (u8*)value, + WIMLIB_RESOURCE_FLAG_MULTITHREADED); if (ret != 0) return -EIO; @@ -1086,7 +1105,7 @@ static int wimfs_link(const char *to, const char *from) lte->refcnt++; } - link_dentry(from_dentry, from_dentry_parent); + dentry_add_child(from_dentry_parent, from_dentry); return 0; } @@ -1152,7 +1171,7 @@ static int wimfs_mkdir(const char *path, mode_t mode) newdir->d_inode->attributes |= FILE_ATTRIBUTE_DIRECTORY; newdir->d_inode->resolved = true; newdir->d_inode->ino = ctx->next_ino++; - link_dentry(newdir, parent); + dentry_add_child(parent, newdir); return 0; } @@ -1204,7 +1223,7 @@ static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev) return -ENOMEM; dentry->d_inode->resolved = true; dentry->d_inode->ino = ctx->next_ino++; - link_dentry(dentry, parent); + dentry_add_child(parent, dentry); } return 0; } @@ -1316,6 +1335,8 @@ static int wimfs_read(const char *path, char *buf, size_t size, } else { /* Read from WIM */ + wimlib_assert(fd->f_lte->resource_location == RESOURCE_IN_WIM); + u64 res_size = wim_resource_size(fd->f_lte); if (offset > res_size) @@ -1324,7 +1345,8 @@ static int wimfs_read(const char *path, char *buf, size_t size, size = min(size, res_size - offset); if (read_wim_resource(fd->f_lte, (u8*)buf, - size, offset, false) != 0) + size, offset, + WIMLIB_RESOURCE_FLAG_MULTITHREADED) != 0) return -EIO; return size; } @@ -1378,7 +1400,8 @@ static int wimfs_readlink(const char *path, char *buf, size_t buf_len) if (!inode_is_symlink(inode)) return -EINVAL; - ret = inode_readlink(inode, buf, buf_len, ctx->wim); + ret = inode_readlink(inode, buf, buf_len, ctx->wim, + WIMLIB_RESOURCE_FLAG_MULTITHREADED); if (ret > 0) ret = 0; return ret; @@ -1491,7 +1514,7 @@ static int wimfs_rename(const char *from, const char *to) src->file_name_utf8_len = file_name_utf8_len; unlink_dentry(src); - link_dentry(src, parent_of_dst); + dentry_add_child(parent_of_dst, src); return 0; } @@ -1611,7 +1634,7 @@ static int wimfs_symlink(const char *to, const char *from) if (inode_set_symlink(inode, to, ctx->wim->lookup_table, NULL) != 0) goto out_free_dentry; - link_dentry(dentry, dentry_parent); + dentry_add_child(dentry_parent, dentry); return 0; out_free_dentry: free_dentry(dentry); @@ -1836,6 +1859,11 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir, if (ret != 0) return ret; + if ((flags & WIMLIB_MOUNT_FLAG_READWRITE) && (wim->hdr.total_parts != 1)) { + ERROR("Cannot mount a split WIM read-write"); + return WIMLIB_ERR_SPLIT_UNSUPPORTED; + } + if (num_additional_swms) { ret = new_joined_lookup_table(wim, additional_swms, num_additional_swms, @@ -1857,7 +1885,14 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir, if (imd->root_dentry->refcnt != 1) { ERROR("Cannot mount image that was just exported with " - "wimlib_export()"); + "wimlib_export_image()"); + ret = WIMLIB_ERR_INVALID_PARAM; + goto out; + } + + if (imd->modified) { + ERROR("Cannot mount image that was added " + "with wimlib_add_image()"); ret = WIMLIB_ERR_INVALID_PARAM; goto out; } @@ -1893,7 +1928,10 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir, 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";