From 89198eafbaf6afac99dc74f77753466f9c1bc7f0 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 4 Sep 2012 00:50:10 -0500 Subject: [PATCH] Fix lte ref counting --- src/dentry.c | 13 +++++++----- src/lookup_table.c | 26 ++++++++--------------- src/lookup_table.h | 20 +++++------------- src/mount.c | 51 ++++++++++++++++++++++++++-------------------- src/symlink.c | 1 - 5 files changed, 50 insertions(+), 61 deletions(-) diff --git a/src/dentry.c b/src/dentry.c index f9126eb0..d92fb852 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -594,6 +594,9 @@ static struct inode *new_timeless_inode() return NULL; inode->security_id = -1; inode->link_count = 1; +#ifdef WITH_FUSE + inode->next_stream_id = 1; +#endif INIT_LIST_HEAD(&inode->dentry_list); return inode; } @@ -1068,7 +1071,7 @@ struct ads_entry *inode_add_ads(struct inode *inode, const char *stream_name) struct ads_entry *ads_entries; struct ads_entry *new_entry; - DEBUG("Add alternate data stream `%s'", stream_name); + DEBUG("Add alternate data stream \"%s\"", stream_name); if (inode->num_ads >= 0xfffe) { ERROR("Too many alternate data streams in one inode!"); @@ -1102,19 +1105,19 @@ void inode_remove_ads(struct inode *inode, u16 idx, struct ads_entry *ads_entry; struct lookup_table_entry *lte; + wimlib_assert(idx < inode->num_ads); + wimlib_assert(inode->resolved); + ads_entry = &inode->ads_entries[idx]; - wimlib_assert(ads_entry); - wimlib_assert(inode->resolved); + DEBUG("Remove alternate data stream \"%s\"", ads_entry->stream_name_utf8); lte = ads_entry->lte; - if (lte) lte_decrement_refcnt(lte, lookup_table); destroy_ads_entry(ads_entry); - wimlib_assert(inode->num_ads); memcpy(&inode->ads_entries[idx], &inode->ads_entries[idx + 1], (inode->num_ads - idx - 1) * sizeof(inode->ads_entries[0])); diff --git a/src/lookup_table.c b/src/lookup_table.c index d23d21c3..3a1e2d25 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -158,8 +158,8 @@ static void finalize_lte(struct lookup_table_entry *lte) * reference count reaches 0, it is unlinked from the lookup table. If, * furthermore, the entry has no opened file descriptors associated with it, the * entry is freed. */ -struct lookup_table_entry * -lte_decrement_refcnt(struct lookup_table_entry *lte, struct lookup_table *table) +void lte_decrement_refcnt(struct lookup_table_entry *lte, + struct lookup_table *table) { wimlib_assert(lte); wimlib_assert(lte->refcnt); @@ -168,28 +168,18 @@ lte_decrement_refcnt(struct lookup_table_entry *lte, struct lookup_table *table) #ifdef WITH_FUSE if (lte->num_opened_fds == 0) #endif - { finalize_lte(lte); - lte = NULL; - } } - return lte; } #ifdef WITH_FUSE -struct lookup_table_entry * -lte_decrement_num_opened_fds(struct lookup_table_entry *lte, - struct lookup_table *table) +void lte_decrement_num_opened_fds(struct lookup_table_entry *lte, + struct lookup_table *table) { - if (lte) { - wimlib_assert(lte->num_opened_fds); - if (--lte->num_opened_fds == 0 && lte->refcnt == 0) { - lookup_table_unlink(table, lte); - finalize_lte(lte); - lte = NULL; - } - } - return lte; + wimlib_assert(lte); + wimlib_assert(lte->num_opened_fds); + if (--lte->num_opened_fds == 0 && lte->refcnt == 0) + finalize_lte(lte); } #endif diff --git a/src/lookup_table.h b/src/lookup_table.h index cbf5daf3..0017320c 100644 --- a/src/lookup_table.h +++ b/src/lookup_table.h @@ -234,21 +234,6 @@ static inline void lookup_table_unlink(struct lookup_table *table, table->num_entries--; } - -extern struct lookup_table_entry * -lookup_table_decrement_refcnt(struct lookup_table* table, const u8 hash[]); - -#ifdef WITH_FUSE -extern struct lookup_table_entry * -lte_decrement_num_opened_fds(struct lookup_table_entry *lte, - struct lookup_table *table); -#endif - -extern struct lookup_table_entry * -lte_decrement_refcnt(struct lookup_table_entry *lte, - struct lookup_table *table); - - extern struct lookup_table_entry *new_lookup_table_entry(); extern int for_lookup_table_entry(struct lookup_table *table, @@ -263,6 +248,11 @@ extern int lookup_resource(WIMStruct *w, const char *path, struct lookup_table_entry **lte_ret, u16 *stream_idx_ret); +extern void lte_decrement_refcnt(struct lookup_table_entry *lte, + struct lookup_table *table); +extern void lte_decrement_num_opened_fds(struct lookup_table_entry *lte, + struct lookup_table *table); + extern int lte_zero_out_refcnt(struct lookup_table_entry *entry, void *ignore); extern int lte_zero_real_refcnt(struct lookup_table_entry *entry, void *ignore); extern int lte_free_extracted_file(struct lookup_table_entry *lte, void *ignone); diff --git a/src/mount.c b/src/mount.c index 0da8eeea..abc7fb93 100644 --- a/src/mount.c +++ b/src/mount.c @@ -186,7 +186,6 @@ static int lte_put_fd(struct lookup_table_entry *lte, struct wimlib_fd *fd) return 0; /* Close staging file descriptor if needed. */ - wimlib_assert(lte->num_opened_fds); if (lte->resource_location == RESOURCE_IN_STAGING_FILE && fd->staging_fd != -1) @@ -322,6 +321,9 @@ static int extract_resource_to_staging_dir(struct inode *inode, int fd; struct lookup_table_entry *old_lte, *new_lte; + DEBUG("Extracting resource to staging dir: inode %"PRIu64", " + "stream id %"PRIu32, inode->ino, stream_id); + old_lte = *lte; fd = create_staging_file(&staging_file_name, O_WRONLY); if (fd == -1) @@ -915,7 +917,7 @@ static int wimfs_getxattr(const char *path, const char *name, char *value, size_t size) { int ret; - struct dentry *dentry; + struct inode *inode; struct ads_entry *ads_entry; size_t res_size; struct lookup_table_entry *lte; @@ -927,10 +929,11 @@ static int wimfs_getxattr(const char *path, const char *name, char *value, return -ENOATTR; name += 5; - dentry = get_dentry(w, path); - if (!dentry) + inode = wim_pathname_to_inode(w, path); + if (!inode) return -ENOENT; - ads_entry = inode_get_ads_entry(dentry->d_inode, name, NULL); + + ads_entry = inode_get_ads_entry(inode, name, NULL); if (!ads_entry) return -ENOATTR; @@ -939,11 +942,14 @@ static int wimfs_getxattr(const char *path, const char *name, char *value, if (size == 0) return res_size; + if (res_size > size) return -ERANGE; + ret = read_full_wim_resource(lte, (u8*)value); if (ret != 0) return -EIO; + return res_size; } #endif @@ -994,21 +1000,19 @@ static int wimfs_link(const char *to, const char *from) #ifdef ENABLE_XATTR static int wimfs_listxattr(const char *path, char *list, size_t size) { - struct dentry *dentry; int ret; - char *p = list; size_t needed_size; unsigned i; struct inode *inode; + if (!(mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR)) return -ENOTSUP; /* List alternate data streams, or get the list size */ - ret = lookup_resource(w, path, get_lookup_flags(), &dentry, NULL, NULL); - if (ret != 0) - return ret; - inode = dentry->d_inode; + inode = wim_pathname_to_inode(w, path); + if (!inode) + return -ENOENT; if (size == 0) { needed_size = 0; @@ -1016,6 +1020,7 @@ static int wimfs_listxattr(const char *path, char *list, size_t size) needed_size += inode->ads_entries[i].stream_name_utf8_len + 6; return needed_size; } else { + char *p = list; for (i = 0; i < inode->num_ads; i++) { needed_size = inode->ads_entries[i].stream_name_utf8_len + 6; if (needed_size > size) @@ -1066,20 +1071,22 @@ static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev) && (stream_name = path_stream_name(path))) { /* Make an alternate data stream */ struct ads_entry *new_entry; - struct dentry *dentry; + struct inode *inode; char *p = (char*)stream_name - 1; wimlib_assert(*p == ':'); *p = '\0'; - dentry = get_dentry(w, path); - if (!dentry || !dentry_is_regular_file(dentry)) + inode = wim_pathname_to_inode(w, path); + if (!inode) + return -ENOENT; + if (!inode_is_regular_file(inode)) return -ENOENT; - if (inode_get_ads_entry(dentry->d_inode, stream_name, NULL)) + if (inode_get_ads_entry(inode, stream_name, NULL)) return -EEXIST; - new_entry = inode_add_ads(dentry->d_inode, stream_name); + new_entry = inode_add_ads(inode, stream_name); if (!new_entry) - return -ENOENT; + return -ENOMEM; } else { struct dentry *dentry, *parent; const char *basename; @@ -1291,7 +1298,7 @@ static int wimfs_releasedir(const char *path, struct fuse_file_info *fi) /* Remove an alternate data stream through the XATTR interface */ static int wimfs_removexattr(const char *path, const char *name) { - struct dentry *dentry; + struct inode *inode; struct ads_entry *ads_entry; u16 ads_idx; if (!(mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR)) @@ -1301,14 +1308,14 @@ static int wimfs_removexattr(const char *path, const char *name) return -ENOATTR; name += 5; - dentry = get_dentry(w, path); - if (!dentry) + inode = wim_pathname_to_inode(w, path); + if (!inode) return -ENOENT; - ads_entry = inode_get_ads_entry(dentry->d_inode, name, &ads_idx); + ads_entry = inode_get_ads_entry(inode, name, &ads_idx); if (!ads_entry) return -ENOATTR; - inode_remove_ads(dentry->d_inode, ads_idx, w->lookup_table); + inode_remove_ads(inode, ads_idx, w->lookup_table); return 0; } #endif diff --git a/src/symlink.c b/src/symlink.c index cf2f863b..83070ba5 100644 --- a/src/symlink.c +++ b/src/symlink.c @@ -259,7 +259,6 @@ int inode_set_symlink(struct inode *inode, const char *target, lte->attached_buffer = symlink_buf; lte->resource_entry.original_size = symlink_buf_len; lte->resource_entry.size = symlink_buf_len; - lte->resource_entry.flags = 0; copy_hash(lte->hash, symlink_buf_hash); } -- 2.43.0