From b3628f2ab2d1c67c744d22c96758e75f6c191054 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 18:41:33 +0000 Subject: [PATCH] Update APFS driver to v0.3.10-1 --- 8001-Add-APFS-driver.patch | 298 ++++++++++++++++++++++--------------- apfs_ver | 4 +- 2 files changed, 184 insertions(+), 118 deletions(-) diff --git a/8001-Add-APFS-driver.patch b/8001-Add-APFS-driver.patch index 6341f48..a27d7eb 100644 --- a/8001-Add-APFS-driver.patch +++ b/8001-Add-APFS-driver.patch @@ -1,12 +1,12 @@ -From ee7e48c3d799e405dde9f4a7404d9bef6dec1b83 Mon Sep 17 00:00:00 2001 +From c28b830fa91f07b7dd1874fae7f41b329d1c4ce0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> -Date: Sat, 8 Jun 2024 13:32:02 +0000 +Date: Tue, 16 Jul 2024 18:41:31 +0000 Subject: [PATCH] Add APFS driver --- fs/apfs/Makefile | 23 + - fs/apfs/apfs.h | 1188 ++++++++++ + fs/apfs/apfs.h | 1180 ++++++++++ fs/apfs/apfs_raw.h | 1562 +++++++++++++ fs/apfs/btree.c | 1174 ++++++++++ fs/apfs/compress.c | 474 ++++ @@ -36,17 +36,17 @@ Subject: [PATCH] Add APFS driver fs/apfs/namei.c | 142 ++ fs/apfs/node.c | 2069 ++++++++++++++++++ fs/apfs/object.c | 315 +++ - fs/apfs/snapshot.c | 612 ++++++ + fs/apfs/snapshot.c | 681 ++++++ fs/apfs/spaceman.c | 1305 +++++++++++ - fs/apfs/super.c | 1788 +++++++++++++++ + fs/apfs/super.c | 1795 +++++++++++++++ fs/apfs/symlink.c | 80 + - fs/apfs/transaction.c | 978 +++++++++ + fs/apfs/transaction.c | 976 +++++++++ fs/apfs/unicode.c | 3157 +++++++++++++++++++++++++++ fs/apfs/unicode.h | 27 + fs/apfs/version.h | 1 + fs/apfs/xattr.c | 922 ++++++++ fs/apfs/xfield.c | 171 ++ - 41 files changed, 28949 insertions(+) + 41 files changed, 29015 insertions(+) create mode 100644 fs/apfs/Makefile create mode 100644 fs/apfs/apfs.h create mode 100644 fs/apfs/apfs_raw.h @@ -120,10 +120,10 @@ index 000000000..ab4c49d55 + make -C $(KERNEL_DIR) M=$(PWD) clean diff --git a/fs/apfs/apfs.h b/fs/apfs/apfs.h new file mode 100644 -index 000000000..b6d135c63 +index 000000000..f09b3f6a5 --- /dev/null +++ b/fs/apfs/apfs.h -@@ -0,0 +1,1188 @@ +@@ -0,0 +1,1180 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2018 Ernesto A. Fernández @@ -276,9 +276,9 @@ index 000000000..b6d135c63 + struct buffer_head *sm_ip_bmaps[]; +}; + -+#define TRANSACTION_MAIN_QUEUE_MAX 4096 -+#define TRANSACTION_BUFFERS_MAX 65536 -+#define TRANSACTION_STARTS_MAX 65536 ++#define APFS_TRANS_MAIN_QUEUE_MAX 10000 ++#define APFS_TRANS_BUFFERS_MAX 65536 ++#define APFS_TRANS_STARTS_MAX 65536 + +/* Possible states for the container transaction structure */ +#define APFS_NX_TRANS_FORCE_COMMIT 1 /* Commit guaranteed */ @@ -292,22 +292,15 @@ index 000000000..b6d135c63 +struct apfs_nx_transaction { + unsigned int t_state; + ++ struct delayed_work t_work; /* Work task for transaction commits */ ++ struct super_block *t_work_sb; /* sb that last queued a commit */ ++ + struct list_head t_inodes; /* List of inodes in the transaction */ + struct list_head t_buffers; /* List of buffers in the transaction */ + size_t t_buffers_count; /* Count of items on the list */ + int t_starts_count; /* Count of starts for transaction */ +}; + -+/* -+ * Structure that keeps track of a volume transaction. -+ */ -+struct apfs_vol_transaction { -+ struct buffer_head *t_old_vsb; /* Volume superblock being replaced */ -+ -+ struct apfs_node t_old_omap_root; /* Omap root node being replaced */ -+ struct apfs_node t_old_cat_root; /* Catalog root node being replaced */ -+}; -+ +/* State bits for buffer heads in a transaction */ +#define BH_TRANS BH_PrivateStart /* Attached to a transaction */ +#define BH_CSUM (BH_PrivateStart + 1) /* Requires checksum update */ @@ -380,6 +373,7 @@ index 000000000..b6d135c63 + + struct apfs_spaceman *nx_spaceman; + struct apfs_nx_transaction nx_transaction; ++ int nx_trans_buffers_max; + + /* For now, a single semaphore for every operation */ + struct rw_semaphore nx_big_sem; @@ -459,9 +453,6 @@ index 000000000..b6d135c63 + + struct apfs_crypto_state_val *s_dflt_pfk; /* default per-file key */ + -+ struct apfs_vol_transaction s_transaction; -+ int s_trans_buffers_max; -+ + struct inode *s_private_dir; /* Inode for the private directory */ + struct work_struct s_orphan_cleanup_work; +}; @@ -1207,6 +1198,7 @@ index 000000000..b6d135c63 + +/* transaction.c */ +extern int apfs_cpoint_data_free(struct super_block *sb, u64 bno); ++extern void apfs_transaction_init(struct apfs_nx_transaction *trans); +extern int apfs_transaction_start(struct super_block *sb, struct apfs_max_ops maxops); +extern int apfs_transaction_commit(struct super_block *sb); +extern void apfs_inode_join_transaction(struct super_block *sb, struct inode *inode); @@ -6092,7 +6084,7 @@ index 000000000..416f42f02 +} diff --git a/fs/apfs/extents.c b/fs/apfs/extents.c new file mode 100644 -index 000000000..3ebcd296c +index 000000000..c8ae4092a --- /dev/null +++ b/fs/apfs/extents.c @@ -0,0 +1,2392 @@ @@ -7749,7 +7741,7 @@ index 000000000..3ebcd296c + int ret; + + fq = &sm_raw->sm_fq[APFS_SFQ_MAIN]; -+ if (le64_to_cpu(fq->sfq_count) > TRANSACTION_MAIN_QUEUE_MAX) ++ if (le64_to_cpu(fq->sfq_count) > APFS_TRANS_MAIN_QUEUE_MAX) + return -EAGAIN; + + query = apfs_alloc_query(sbi->s_cat_root, NULL /* parent */); @@ -7808,7 +7800,7 @@ index 000000000..3ebcd296c + } + } + -+ if (le64_to_cpu(fq->sfq_count) <= TRANSACTION_MAIN_QUEUE_MAX) ++ if (le64_to_cpu(fq->sfq_count) <= APFS_TRANS_MAIN_QUEUE_MAX) + goto next_extent; + ret = -EAGAIN; +out: @@ -20185,10 +20177,10 @@ index 000000000..9636a9a29 +} diff --git a/fs/apfs/snapshot.c b/fs/apfs/snapshot.c new file mode 100644 -index 000000000..77f83b455 +index 000000000..c9de8a155 --- /dev/null +++ b/fs/apfs/snapshot.c -@@ -0,0 +1,612 @@ +@@ -0,0 +1,681 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Ernesto A. Fernández @@ -20340,9 +20332,9 @@ index 000000000..77f83b455 + + err = apfs_btree_query(sb, &query); + if (err == 0) { -+ /* TODO: avoid transaction abort here */ -+ apfs_info(sb, "a snapshot with that name already exists"); -+ err = -EEXIST; ++ /* This should never happen here, the caller has checked */ ++ apfs_alert(sb, "snapshot name record already exists"); ++ err = -EFSCORRUPTED; + goto fail; + } + if (err != -ENODATA) { @@ -20524,6 +20516,56 @@ index 000000000..77f83b455 +} + +/** ++ * apfs_snapshot_name_check - Check if a snapshot with the given name exists ++ * @sb: filesystem superblock ++ * @name: name to check ++ * @name_len: length of @name ++ * @eexist: on return, whether the name exists or not ++ * ++ * Returns 0 on success, or a negative error code in case of failure. ++ */ ++static int apfs_snapshot_name_check(struct super_block *sb, const char *name, int name_len, bool *eexist) ++{ ++ struct apfs_sb_info *sbi = APFS_SB(sb); ++ struct apfs_superblock *vsb_raw = sbi->s_vsb_raw; ++ struct apfs_node *snap_root = NULL; ++ struct apfs_query *query = NULL; ++ int err; ++ ++ snap_root = apfs_read_node(sb, le64_to_cpu(vsb_raw->apfs_snap_meta_tree_oid), APFS_OBJ_PHYSICAL, false /* write */); ++ if (IS_ERR(snap_root)) { ++ apfs_err(sb, "failed to read snap meta root 0x%llx", le64_to_cpu(vsb_raw->apfs_snap_meta_tree_oid)); ++ return PTR_ERR(snap_root); ++ } ++ vsb_raw = NULL; ++ ++ query = apfs_alloc_query(snap_root, NULL /* parent */); ++ if (!query) { ++ err = -ENOMEM; ++ goto out; ++ } ++ apfs_init_snap_name_key(name, &query->key); ++ query->flags |= APFS_QUERY_SNAP_META | APFS_QUERY_EXACT; ++ ++ err = apfs_btree_query(sb, &query); ++ if (err == 0) { ++ *eexist = true; ++ } else if (err == -ENODATA) { ++ *eexist = false; ++ err = 0; ++ } else { ++ apfs_err(sb, "query failed (%s)", name); ++ } ++ ++out: ++ apfs_free_query(query); ++ query = NULL; ++ apfs_node_free(snap_root); ++ snap_root = NULL; ++ return err; ++} ++ ++/** + * apfs_do_ioc_takesnapshot - Actual work for apfs_ioc_take_snapshot() + * @mntpoint: inode of the mount point to snapshot + * @name: label for the snapshot @@ -20539,6 +20581,7 @@ index 000000000..77f83b455 + /* TODO: remember to update the maxops in the future */ + struct apfs_max_ops maxops = {0}; + u64 sblock_oid; ++ bool eexist = false; + int err; + + err = apfs_transaction_start(sb, maxops); @@ -20546,6 +20589,24 @@ index 000000000..77f83b455 + return err; + + /* ++ * This check can fail in normal operation, so run it before making any ++ * changes and exit the transaction cleanly if necessary. The name ++ * lookup will have to be repeated later, but it's ok because I don't ++ * expect snapshot creation to be a bottleneck for anyone. ++ */ ++ err = apfs_snapshot_name_check(sb, name, name_len, &eexist); ++ if (err) { ++ apfs_err(sb, "snapshot name existence check failed"); ++ goto fail; ++ } ++ if (eexist) { ++ err = apfs_transaction_commit(sb); ++ if (err) ++ goto fail; ++ return -EEXIST; ++ } ++ ++ /* + * Flush the extent caches to the extenref tree before it gets moved to + * the snapshot. It seems safer in general to avoid big unpredictable + * changes to the layout after the snapshot is set up. @@ -20803,7 +20864,7 @@ index 000000000..77f83b455 +} diff --git a/fs/apfs/spaceman.c b/fs/apfs/spaceman.c new file mode 100644 -index 000000000..1ac9f76e8 +index 000000000..b8d4b05f5 --- /dev/null +++ b/fs/apfs/spaceman.c @@ -0,0 +1,1305 @@ @@ -21357,7 +21418,7 @@ index 000000000..1ac9f76e8 + sfq_count = le64_to_cpu(fq->sfq_count); + if (qid == APFS_SFQ_IP && sfq_count * 6 <= le64_to_cpu(sm_raw->sm_ip_block_count)) + break; -+ if (qid == APFS_SFQ_MAIN && sfq_count <= TRANSACTION_MAIN_QUEUE_MAX - 200) ++ if (qid == APFS_SFQ_MAIN && sfq_count <= APFS_TRANS_MAIN_QUEUE_MAX - 200) + break; + } + @@ -22114,10 +22175,10 @@ index 000000000..1ac9f76e8 +} diff --git a/fs/apfs/super.c b/fs/apfs/super.c new file mode 100644 -index 000000000..393a97239 +index 000000000..993e9a000 --- /dev/null +++ b/fs/apfs/super.c -@@ -0,0 +1,1788 @@ +@@ -0,0 +1,1795 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2018 Ernesto A. Fernández @@ -22177,7 +22238,11 @@ index 000000000..393a97239 + */ +static int apfs_sb_set_blocksize(struct super_block *sb, int size) +{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 10, 0) + if (set_blocksize(APFS_NXI(sb)->nx_bdev_file, size)) ++#else ++ if (set_blocksize(APFS_NXI(sb)->nx_bdev, size)) ++#endif + return 0; + sb->s_blocksize = size; + sb->s_blocksize_bits = blksize_bits(size); @@ -22522,14 +22587,11 @@ index 000000000..393a97239 + struct apfs_omap *omap = NULL; + struct apfs_node *vnode; + struct buffer_head *bh; -+ struct apfs_vol_transaction *trans = &sbi->s_transaction; + u64 vol_id; + u64 vsb; + int err; + + ASSERT(msb_raw); -+ ASSERT(trans->t_old_vsb == sbi->s_vobject.o_bh); -+ (void)trans; + + /* Get the id for the requested volume number */ + if (sbi->s_vol_nr >= APFS_NX_MAX_FILE_SYSTEMS) { @@ -22796,10 +22858,15 @@ index 000000000..393a97239 +static void apfs_put_super(struct super_block *sb) +{ + struct apfs_sb_info *sbi = APFS_SB(sb); ++ struct apfs_nx_transaction *trans = NULL; + + /* Cleanups won't reschedule themselves during unmount */ + flush_work(&sbi->s_orphan_cleanup_work); + ++ /* We are about to commit anyway */ ++ trans = &APFS_NXI(sb)->nx_transaction; ++ cancel_delayed_work_sync(&trans->t_work); ++ + /* Stop flushing orphans and update the volume as needed */ + if (!(sb->s_flags & SB_RDONLY)) { + struct apfs_superblock *vsb_raw; @@ -23507,7 +23574,7 @@ index 000000000..393a97239 + +static void apfs_set_trans_buffer_limit(struct super_block *sb) +{ -+ struct apfs_sb_info *sbi = APFS_SB(sb); ++ struct apfs_nxsb_info *nxi = APFS_NXI(sb); + unsigned long memsize_in_blocks; + struct sysinfo info = {0}; + @@ -23520,10 +23587,10 @@ index 000000000..393a97239 + * commit often enough. This hack should make that happen in general, + * but I still need to get the reclaim to work eventually (TODO). + */ -+ if (memsize_in_blocks >= 16 * TRANSACTION_BUFFERS_MAX) -+ sbi->s_trans_buffers_max = TRANSACTION_BUFFERS_MAX; ++ if (memsize_in_blocks >= 16 * APFS_TRANS_BUFFERS_MAX) ++ nxi->nx_trans_buffers_max = APFS_TRANS_BUFFERS_MAX; + else -+ sbi->s_trans_buffers_max = memsize_in_blocks / 16; ++ nxi->nx_trans_buffers_max = memsize_in_blocks / 16; +} + +static int apfs_fill_super(struct super_block *sb, void *data, int silent) @@ -23771,6 +23838,7 @@ index 000000000..393a97239 + init_rwsem(&nxi->nx_big_sem); + list_add(&nxi->nx_list, &nxs); + INIT_LIST_HEAD(&nxi->vol_list); ++ apfs_transaction_init(&nxi->nx_transaction); + } + + list_add(&sbi->list, &nxi->vol_list); @@ -23994,10 +24062,10 @@ index 000000000..be4f9df8f +}; diff --git a/fs/apfs/transaction.c b/fs/apfs/transaction.c new file mode 100644 -index 000000000..a79a6a564 +index 000000000..ab0d51d2d --- /dev/null +++ b/fs/apfs/transaction.c -@@ -0,0 +1,978 @@ +@@ -0,0 +1,976 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2019 Ernesto A. Fernández @@ -24020,8 +24088,12 @@ index 000000000..a79a6a564 + struct apfs_nxsb_info *nxi = APFS_NXI(sb); + struct apfs_obj_phys *obj = &nxi->nx_raw->nx_o; + struct buffer_head *bh = NULL; -+ // struct inode *bdev_inode = nxi->nx_bdev->bd_inode; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 10, 0) + struct address_space *bdev_map = nxi->nx_bdev->bd_mapping; ++#else ++ struct inode *bdev_inode = nxi->nx_bdev->bd_inode; ++ struct address_space *bdev_map = bdev_inode->i_mapping; ++#endif + int err; + + ASSERT(!(sb->s_flags & SB_RDONLY)); @@ -24262,6 +24334,55 @@ index 000000000..a79a6a564 + return 0; +} + ++static void apfs_trans_commit_work(struct work_struct *work) ++{ ++ struct super_block *sb = NULL; ++ struct apfs_nxsb_info *nxi = NULL; ++ struct apfs_nx_transaction *trans = NULL; ++ int err; ++ ++ trans = container_of(to_delayed_work(work), struct apfs_nx_transaction, t_work); ++ nxi = container_of(trans, struct apfs_nxsb_info, nx_transaction); ++ sb = trans->t_work_sb; ++ ++ /* ++ * If sb is set then the transaction already started, there is no need ++ * for apfs_transaction_start() here. It would be cleaner to call it ++ * anyway (and check in there if sb is set), but maxops is a problem ++ * because we don't need any space. I really need to rethink that stuff ++ * (TODO). ++ */ ++ down_write(&nxi->nx_big_sem); ++ mutex_lock(&nxs_mutex); ++ if (!sb || sb->s_flags & SB_RDONLY) { ++ /* The commit already took place, or there was an abort */ ++ mutex_unlock(&nxs_mutex); ++ up_write(&nxi->nx_big_sem); ++ return; ++ } ++ ++ trans->t_state |= APFS_NX_TRANS_FORCE_COMMIT; ++ err = apfs_transaction_commit(sb); ++ if (err) { ++ apfs_err(sb, "queued commit failed (err:%d)", err); ++ apfs_transaction_abort(sb); ++ } ++} ++ ++/** ++ * apfs_transaction_init - Initialize the transaction struct for the container ++ * @trans: the transaction structure ++ */ ++void apfs_transaction_init(struct apfs_nx_transaction *trans) ++{ ++ trans->t_state = 0; ++ INIT_DELAYED_WORK(&trans->t_work, apfs_trans_commit_work); ++ INIT_LIST_HEAD(&trans->t_inodes); ++ INIT_LIST_HEAD(&trans->t_buffers); ++ trans->t_buffers_count = 0; ++ trans->t_starts_count = 0; ++} ++ +/** + * apfs_transaction_start - Begin a new transaction + * @sb: superblock structure @@ -24272,9 +24393,7 @@ index 000000000..a79a6a564 + */ +int apfs_transaction_start(struct super_block *sb, struct apfs_max_ops maxops) +{ -+ struct apfs_sb_info *sbi = APFS_SB(sb); + struct apfs_nxsb_info *nxi = APFS_NXI(sb); -+ struct apfs_vol_transaction *vol_trans = &sbi->s_transaction; + struct apfs_nx_transaction *nx_trans = &nxi->nx_transaction; + int err; + @@ -24306,9 +24425,6 @@ index 000000000..a79a6a564 + ++nxi->nx_xid; + nxi->nx_raw->nx_next_xid = cpu_to_le64(nxi->nx_xid + 1); + -+ INIT_LIST_HEAD(&nx_trans->t_inodes); -+ INIT_LIST_HEAD(&nx_trans->t_buffers); -+ + err = apfs_read_spaceman(sb); + if (err) { + apfs_err(sb, "failed to read the spaceman"); @@ -24328,16 +24444,7 @@ index 000000000..a79a6a564 + return -ENOSPC; + } + -+ if (!vol_trans->t_old_vsb) { -+ vol_trans->t_old_vsb = sbi->s_vobject.o_bh; -+ get_bh(vol_trans->t_old_vsb); -+ -+ /* Backup the old tree roots; the node struct issues make this ugly */ -+ vol_trans->t_old_cat_root = *sbi->s_cat_root; -+ get_bh(vol_trans->t_old_cat_root.object.o_bh); -+ vol_trans->t_old_omap_root = *sbi->s_omap->omap_root; -+ get_bh(vol_trans->t_old_omap_root.object.o_bh); -+ ++ if (nx_trans->t_starts_count == 0) { + err = apfs_map_volume_super(sb, true /* write */); + if (err) { + apfs_err(sb, "CoW failed for volume super"); @@ -24596,7 +24703,6 @@ index 000000000..a79a6a564 +{ + struct apfs_spaceman *sm = APFS_SM(sb); + struct apfs_nxsb_info *nxi = APFS_NXI(sb); -+ struct apfs_sb_info *sbi; + struct apfs_nx_transaction *nx_trans = &nxi->nx_transaction; + struct apfs_bh_info *bhi, *tmp; + int err = 0; @@ -24692,24 +24798,6 @@ index 000000000..a79a6a564 + return err; + } + -+ list_for_each_entry(sbi, &nxi->vol_list, list) { -+ struct apfs_vol_transaction *vol_trans = &sbi->s_transaction; -+ -+ if (!vol_trans->t_old_vsb) -+ continue; -+ -+ brelse(vol_trans->t_old_vsb); -+ vol_trans->t_old_vsb = NULL; -+ -+ /* XXX: forget the buffers for the b-tree roots */ -+ vol_trans->t_old_omap_root.object.data = NULL; -+ brelse(vol_trans->t_old_omap_root.object.o_bh); -+ vol_trans->t_old_omap_root.object.o_bh = NULL; -+ vol_trans->t_old_cat_root.object.data = NULL; -+ brelse(vol_trans->t_old_cat_root.object.o_bh); -+ vol_trans->t_old_cat_root.object.o_bh = NULL; -+ } -+ + for (bmap_idx = 0; bmap_idx < APFS_SM(sb)->sm_ip_bmaps_count; ++bmap_idx) { + brelse(APFS_SM(sb)->sm_ip_bmaps[bmap_idx]); + APFS_SM(sb)->sm_ip_bmaps[bmap_idx] = NULL; @@ -24749,9 +24837,9 @@ index 000000000..a79a6a564 + struct apfs_spaceman_phys *sm_raw = sm->sm_raw; + struct apfs_spaceman_free_queue *fq_ip = &sm_raw->sm_fq[APFS_SFQ_IP]; + struct apfs_spaceman_free_queue *fq_main = &sm_raw->sm_fq[APFS_SFQ_MAIN]; -+ int buffers_max = APFS_SB(sb)->s_trans_buffers_max; -+ int starts_max = TRANSACTION_STARTS_MAX; -+ int mq_max = TRANSACTION_MAIN_QUEUE_MAX; ++ int buffers_max = nxi->nx_trans_buffers_max; ++ int starts_max = APFS_TRANS_STARTS_MAX; ++ int mq_max = APFS_TRANS_MAIN_QUEUE_MAX; + + /* + * Try to avoid committing halfway through a data block write, @@ -24796,14 +24884,22 @@ index 000000000..a79a6a564 +int apfs_transaction_commit(struct super_block *sb) +{ + struct apfs_nxsb_info *nxi = APFS_NXI(sb); ++ struct apfs_nx_transaction *trans = NULL; + int err = 0; + ++ trans = &nxi->nx_transaction; ++ + if (apfs_transaction_need_commit(sb)) { + err = apfs_transaction_commit_nx(sb); + if (err) { + apfs_err(sb, "transaction commit failed"); + return err; + } ++ trans->t_work_sb = NULL; ++ cancel_delayed_work(&trans->t_work); ++ } else { ++ trans->t_work_sb = sb; ++ mod_delayed_work(system_wq, &trans->t_work, msecs_to_jiffies(100)); + } + + mutex_unlock(&nxs_mutex); @@ -24889,7 +24985,6 @@ index 000000000..a79a6a564 + */ +void apfs_transaction_abort(struct super_block *sb) +{ -+ struct apfs_sb_info *sbi; + struct apfs_nxsb_info *nxi = APFS_NXI(sb); + struct apfs_nx_transaction *nx_trans = &nxi->nx_transaction; + struct apfs_bh_info *bhi, *tmp; @@ -24924,35 +25019,6 @@ index 000000000..a79a6a564 + kfree(bhi); + } + -+ /* -+ * TODO: get rid of all this stuff, it makes little sense. Maybe do an -+ * actual read-only remount? -+ */ -+ list_for_each_entry(sbi, &nxi->vol_list, list) { -+ struct apfs_vol_transaction *vol_trans = &sbi->s_transaction; -+ -+ if (!vol_trans->t_old_vsb) -+ continue; -+ -+ /* Restore volume state for all volumes */ -+ brelse(sbi->s_vobject.o_bh); -+ sbi->s_vobject.o_bh = vol_trans->t_old_vsb; -+ sbi->s_vobject.data = sbi->s_vobject.o_bh->b_data; -+ sbi->s_vobject.block_nr = vol_trans->t_old_vsb->b_blocknr; -+ sbi->s_vsb_raw = (void *)vol_trans->t_old_vsb->b_data; -+ vol_trans->t_old_vsb = NULL; -+ -+ /* XXX: restore the old b-tree root nodes */ -+ brelse(sbi->s_omap->omap_root->object.o_bh); -+ *(sbi->s_omap->omap_root) = vol_trans->t_old_omap_root; -+ vol_trans->t_old_omap_root.object.o_bh = NULL; -+ vol_trans->t_old_omap_root.object.data = NULL; -+ brelse(sbi->s_cat_root->object.o_bh); -+ *(sbi->s_cat_root) = vol_trans->t_old_cat_root; -+ vol_trans->t_old_cat_root.object.o_bh = NULL; -+ vol_trans->t_old_cat_root.object.data = NULL; -+ } -+ + sm = APFS_SM(sb); + if (sm) { + for (bmap_idx = 0; bmap_idx < sm->sm_ip_bmaps_count; ++bmap_idx) { @@ -28174,11 +28240,11 @@ index 000000000..e3b7edc51 +#endif /* _APFS_UNICODE_H */ diff --git a/fs/apfs/version.h b/fs/apfs/version.h new file mode 100644 -index 000000000..10c2f7cc0 +index 000000000..3a8789fc1 --- /dev/null +++ b/fs/apfs/version.h @@ -0,0 +1 @@ -+#define GIT_COMMIT "v0.3.9" ++#define GIT_COMMIT "v0.3.10" diff --git a/fs/apfs/xattr.c b/fs/apfs/xattr.c new file mode 100644 index 000000000..0de1db140 diff --git a/apfs_ver b/apfs_ver index ffca825..c05f864 100644 --- a/apfs_ver +++ b/apfs_ver @@ -1,2 +1,2 @@ -CURRENT_HASH=d533b6be3a3d602d8ae584edd99c535146293306 -RELEASE_VER=0.3.9-1 +CURRENT_HASH=695455bfdb5e97155c377dae2b28d90ff7bb8fe9 +RELEASE_VER=0.3.10-1