]> wimlib.net Git - wimlib/commitdiff
Fix lte ref counting
authorEric Biggers <ebiggers3@gmail.com>
Tue, 4 Sep 2012 05:50:10 +0000 (00:50 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 4 Sep 2012 05:50:10 +0000 (00:50 -0500)
src/dentry.c
src/lookup_table.c
src/lookup_table.h
src/mount.c
src/symlink.c

index f9126eb0d3fb3a5aba037729a5322f08273f1690..d92fb85263942593b02afa228a423b5d39e7507f 100644 (file)
@@ -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]));
index d23d21c3c9372795f4fd145d1f8fe17cffcb99c1..3a1e2d25fa6b7060504115f6d9d2876d19938d2e 100644 (file)
@@ -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
 
index cbf5daf36b091c8a1d82ebac4e9084f15e80abb2..0017320c5e4a82f439005c05249346f20a0a1e14 100644 (file)
@@ -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);
index 0da8eeeacd5c589b611c45aa36d3c81421b02b55..abc7fb938df074395860795554fa99bb203acee2 100644 (file)
@@ -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
index cf2f863b84671a68a7b685fed71dddb972e03786..83070ba5b3a976e3754df57269c9e2ccc4c94da8 100644 (file)
@@ -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);
        }