mirror of
https://github.com/linux-apfs/linux-apfs-rw.git
synced 2026-08-18 02:19:59 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a2db9bd68 | ||
|
|
96e6d41bb7 | ||
|
|
6c2ce34a67 | ||
|
|
a34220c93d | ||
|
|
49507c65bc | ||
|
|
dfdafd2a07 | ||
|
|
2920180ed6 | ||
|
|
0667dbff17 | ||
|
|
af2ee526c0 | ||
|
|
44f4b4f631 | ||
|
|
b44d2a37bf | ||
|
|
4881d7c707 | ||
|
|
2982c8655f | ||
|
|
707d91b486 | ||
|
|
3e5c902a9a |
No files matched your search
@@ -117,6 +117,11 @@ static inline bool apfs_node_has_fixed_kv_size(struct apfs_node *node)
|
||||
return (node->flags & APFS_BTNODE_FIXED_KV_SIZE) != 0;
|
||||
}
|
||||
|
||||
struct apfs_ip_bitmap_block_info {
|
||||
bool dirty; /* Do we need to commit this block to disk? */
|
||||
void *block; /* In-memory address of the bitmap block */
|
||||
};
|
||||
|
||||
/*
|
||||
* Space manager data in memory.
|
||||
*/
|
||||
@@ -147,7 +152,7 @@ struct apfs_spaceman {
|
||||
/* Number of ip bitmaps */
|
||||
u32 sm_ip_bmaps_count;
|
||||
/* List of ip bitmaps, in order */
|
||||
struct buffer_head *sm_ip_bmaps[];
|
||||
struct apfs_ip_bitmap_block_info sm_ip_bmaps[];
|
||||
};
|
||||
|
||||
#define APFS_TRANS_MAIN_QUEUE_MAX 10000
|
||||
@@ -217,6 +222,11 @@ struct apfs_ephemeral_object_info {
|
||||
/* Mount option flags for a container */
|
||||
#define APFS_CHECK_NODES 1
|
||||
#define APFS_READWRITE 2
|
||||
/*
|
||||
* Mount options for a container are decided on its first mount. This flag lets
|
||||
* future mounts know that has happened already.
|
||||
*/
|
||||
#define APFS_FLAGS_SET 4
|
||||
|
||||
/*
|
||||
* Container superblock data in memory
|
||||
@@ -1061,6 +1071,7 @@ extern int apfs_read_spaceman(struct super_block *sb);
|
||||
extern int apfs_free_queue_insert_nocache(struct super_block *sb, u64 bno, u64 count);
|
||||
extern int apfs_free_queue_insert(struct super_block *sb, u64 bno, u64 count);
|
||||
extern int apfs_spaceman_allocate_block(struct super_block *sb, u64 *bno, bool backwards);
|
||||
extern int apfs_write_ip_bitmaps(struct super_block *sb);
|
||||
|
||||
/* super.c */
|
||||
extern int apfs_map_volume_super_bno(struct super_block *sb, u64 bno, bool check);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
PACKAGE_NAME="linux-apfs-rw"
|
||||
PACKAGE_VERSION="0.3.10"
|
||||
PACKAGE_VERSION="0.3.12"
|
||||
|
||||
BUILT_MODULE_NAME[0]="apfs"
|
||||
DEST_MODULE_LOCATION[0]="/extra"
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include <linux/blk_types.h>
|
||||
#include "apfs.h"
|
||||
|
||||
#define MAX(X, Y) ((X) <= (Y) ? (Y) : (X))
|
||||
|
||||
/**
|
||||
* apfs_ext_is_hole - Does this extent represent a hole in a sparse file?
|
||||
* @extent: the extent to check
|
||||
@@ -1973,7 +1971,7 @@ restart:
|
||||
prev_end = prev_ext.bno + prev_ext.blkcount;
|
||||
if (prev_end < *paddr_end) {
|
||||
/* The extent to put is part of a snapshot */
|
||||
tmp.phys_block_num = MAX(prev_end, paddr_min);
|
||||
tmp.phys_block_num = max(prev_end, paddr_min);
|
||||
tmp.len = (*paddr_end - tmp.phys_block_num) << sb->s_blocksize_bits;
|
||||
ret = apfs_create_update_pext(query, &tmp, -1);
|
||||
*paddr_end = tmp.phys_block_num;
|
||||
@@ -2113,7 +2111,7 @@ restart:
|
||||
prev_end = prev_ext.bno + prev_ext.blkcount;
|
||||
if (prev_end < *paddr_end) {
|
||||
/* The extent to take is part of a snapshot */
|
||||
tmp.phys_block_num = MAX(prev_end, paddr_min);
|
||||
tmp.phys_block_num = max(prev_end, paddr_min);
|
||||
tmp.len = (*paddr_end - tmp.phys_block_num) << sb->s_blocksize_bits;
|
||||
ret = apfs_create_update_pext(query, &tmp, +1);
|
||||
*paddr_end = tmp.phys_block_num;
|
||||
|
||||
@@ -565,7 +565,11 @@ int __apfs_write_begin(struct file *file, struct address_space *mapping, loff_t
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
err = __block_write_begin(page_folio(page), pos, len, apfs_get_new_block);
|
||||
#else
|
||||
err = __block_write_begin(page, pos, len, apfs_get_new_block);
|
||||
#endif
|
||||
if (err) {
|
||||
apfs_err(sb, "CoW failed in inode 0x%llx", apfs_ino(inode));
|
||||
goto out_put_page;
|
||||
@@ -580,7 +584,11 @@ out_put_page:
|
||||
return err;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
static int apfs_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len,
|
||||
struct folio **foliop, void **fsdata)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
static int apfs_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len,
|
||||
struct page **pagep, void **fsdata)
|
||||
@@ -592,6 +600,10 @@ static int apfs_write_begin(struct file *file, struct address_space *mapping,
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
struct page *page = NULL;
|
||||
struct page **pagep = &page;
|
||||
#endif
|
||||
int blkcount = (len + sb->s_blocksize - 1) >> inode->i_blkbits;
|
||||
struct apfs_max_ops maxops;
|
||||
int err;
|
||||
@@ -615,6 +627,9 @@ static int apfs_write_begin(struct file *file, struct address_space *mapping,
|
||||
err = __apfs_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
|
||||
if (err)
|
||||
goto fail;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
*foliop = page_folio(page);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -628,7 +643,11 @@ int __apfs_write_end(struct file *file, struct address_space *mapping, loff_t po
|
||||
struct apfs_dstream_info *dstream = &APFS_I(inode)->i_dstream;
|
||||
int ret, err;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
ret = generic_write_end(file, mapping, pos, len, copied, page_folio(page), fsdata);
|
||||
#else
|
||||
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
|
||||
#endif
|
||||
dstream->ds_size = i_size_read(inode);
|
||||
if (ret < len && pos + len > inode->i_size) {
|
||||
truncate_pagecache(inode, inode->i_size);
|
||||
@@ -641,13 +660,22 @@ int __apfs_write_end(struct file *file, struct address_space *mapping, loff_t po
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
static int apfs_write_end(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len, unsigned int copied,
|
||||
struct folio *folio, void *fsdata)
|
||||
#else
|
||||
static int apfs_write_end(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len, unsigned int copied,
|
||||
struct page *page, void *fsdata)
|
||||
#endif
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct apfs_nx_transaction *trans = &APFS_NXI(sb)->nx_transaction;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
struct page *page = &folio->page;
|
||||
#endif
|
||||
int ret, err;
|
||||
|
||||
ret = __apfs_write_end(file, mapping, pos, len, copied, page, fsdata);
|
||||
@@ -693,9 +721,9 @@ static const struct address_space_operations apfs_aops = {
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
||||
.readahead = apfs_readahead,
|
||||
.readahead = apfs_readahead,
|
||||
#else
|
||||
.readpages = apfs_readpages,
|
||||
.readpages = apfs_readpages,
|
||||
#endif
|
||||
|
||||
.write_begin = apfs_write_begin,
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include <linux/string.h>
|
||||
#include "libzbitmap.h"
|
||||
|
||||
#define MIN(x, y) ((x) > (y) ? (y) : (x))
|
||||
|
||||
#define ZBM_MAGIC "ZBM\x09"
|
||||
#define ZBM_MAGIC_SZ 4
|
||||
|
||||
|
||||
+262
-134
File diff suppressed because it is too large.
Load diff
+58
-46
@@ -101,13 +101,18 @@ static bool apfs_transaction_has_room(struct super_block *sb, struct apfs_max_op
|
||||
static int apfs_read_single_ephemeral_object(struct super_block *sb, struct apfs_checkpoint_mapping *map)
|
||||
{
|
||||
struct apfs_nxsb_info *nxi = APFS_NXI(sb);
|
||||
struct apfs_nx_superblock *raw_sb = NULL;
|
||||
struct apfs_ephemeral_object_info *list = NULL;
|
||||
struct buffer_head *bh = NULL;
|
||||
char *object = NULL;
|
||||
int count;
|
||||
u32 size;
|
||||
u64 bno, oid;
|
||||
int err, i;
|
||||
u32 data_blks, size;
|
||||
u64 data_base, bno, oid;
|
||||
int err, i, data_idx;
|
||||
|
||||
raw_sb = nxi->nx_raw;
|
||||
data_base = le64_to_cpu(raw_sb->nx_xp_data_base);
|
||||
data_blks = le32_to_cpu(raw_sb->nx_xp_data_blocks);
|
||||
|
||||
list = nxi->nx_eph_list;
|
||||
count = nxi->nx_eph_count;
|
||||
@@ -135,8 +140,9 @@ static int apfs_read_single_ephemeral_object(struct super_block *sb, struct apfs
|
||||
if (!object)
|
||||
return -ENOMEM;
|
||||
|
||||
data_idx = bno - data_base;
|
||||
for (i = 0; i < size >> sb->s_blocksize_bits; ++i) {
|
||||
bh = apfs_sb_bread(sb, bno + i);
|
||||
bh = apfs_sb_bread(sb, data_base + data_idx);
|
||||
if (!bh) {
|
||||
apfs_err(sb, "failed to read ephemeral block");
|
||||
err = -EIO;
|
||||
@@ -145,6 +151,9 @@ static int apfs_read_single_ephemeral_object(struct super_block *sb, struct apfs
|
||||
memcpy(object + (i << sb->s_blocksize_bits), bh->b_data, sb->s_blocksize);
|
||||
brelse(bh);
|
||||
bh = NULL;
|
||||
/* Somewhat surprisingly, objects can wrap around */
|
||||
if (++data_idx == data_blks)
|
||||
data_idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -285,10 +294,8 @@ static void apfs_trans_commit_work(struct work_struct *work)
|
||||
* (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;
|
||||
}
|
||||
@@ -330,11 +337,9 @@ int apfs_transaction_start(struct super_block *sb, struct apfs_max_ops maxops)
|
||||
int err;
|
||||
|
||||
down_write(&nxi->nx_big_sem);
|
||||
mutex_lock(&nxs_mutex); /* Don't mount during a transaction */
|
||||
|
||||
if (sb->s_flags & SB_RDONLY) {
|
||||
/* A previous transaction has failed; this should be rare */
|
||||
mutex_unlock(&nxs_mutex);
|
||||
up_write(&nxi->nx_big_sem);
|
||||
return -EROFS;
|
||||
}
|
||||
@@ -346,7 +351,6 @@ int apfs_transaction_start(struct super_block *sb, struct apfs_max_ops maxops)
|
||||
if (!nxi->nx_eph_list) {
|
||||
err = apfs_read_ephemeral_objects(sb);
|
||||
if (err) {
|
||||
mutex_unlock(&nxs_mutex);
|
||||
up_write(&nxi->nx_big_sem);
|
||||
apfs_err(sb, "failed to read the ephemeral objects");
|
||||
return err;
|
||||
@@ -440,14 +444,12 @@ int apfs_transaction_flush_all_inodes(struct super_block *sb)
|
||||
list_del_init(&ai->i_list);
|
||||
|
||||
nx_trans->t_state |= APFS_NX_TRANS_COMMITTING;
|
||||
mutex_unlock(&nxs_mutex);
|
||||
up_write(&nxi->nx_big_sem);
|
||||
|
||||
/* Unlocked, so it may call evict() and wait for writeback */
|
||||
iput(inode);
|
||||
|
||||
down_write(&nxi->nx_big_sem);
|
||||
mutex_lock(&nxs_mutex);
|
||||
nx_trans->t_state = 0;
|
||||
|
||||
/* Transaction aborted during writeback, error code is lost */
|
||||
@@ -471,18 +473,24 @@ int apfs_transaction_flush_all_inodes(struct super_block *sb)
|
||||
static int apfs_write_single_ephemeral_object(struct super_block *sb, struct apfs_obj_phys *obj_raw, const struct apfs_checkpoint_mapping *map)
|
||||
{
|
||||
struct apfs_nxsb_info *nxi = APFS_NXI(sb);
|
||||
struct apfs_nx_superblock *raw_sb = NULL;
|
||||
struct buffer_head *bh = NULL;
|
||||
u64 bno;
|
||||
u32 size;
|
||||
int err, i;
|
||||
u64 data_base, bno;
|
||||
u32 data_blks, size;
|
||||
int err, i, data_idx;
|
||||
|
||||
raw_sb = nxi->nx_raw;
|
||||
data_base = le64_to_cpu(raw_sb->nx_xp_data_base);
|
||||
data_blks = le32_to_cpu(raw_sb->nx_xp_data_blocks);
|
||||
|
||||
bno = le64_to_cpu(map->cpm_paddr);
|
||||
size = le32_to_cpu(map->cpm_size);
|
||||
obj_raw->o_xid = cpu_to_le64(nxi->nx_xid);
|
||||
apfs_multiblock_set_csum((char *)obj_raw, size);
|
||||
|
||||
data_idx = bno - data_base;
|
||||
for (i = 0; i < size >> sb->s_blocksize_bits; ++i) {
|
||||
bh = apfs_getblk(sb, bno + i);
|
||||
bh = apfs_getblk(sb, data_base + data_idx);
|
||||
if (!bh) {
|
||||
apfs_err(sb, "failed to map ephemeral block");
|
||||
return -EIO;
|
||||
@@ -496,6 +504,9 @@ static int apfs_write_single_ephemeral_object(struct super_block *sb, struct apf
|
||||
memcpy(bh->b_data, (char *)obj_raw + (i << sb->s_blocksize_bits), sb->s_blocksize);
|
||||
brelse(bh);
|
||||
bh = NULL;
|
||||
/* Somewhat surprisingly, objects can wrap around */
|
||||
if (++data_idx == data_blks)
|
||||
data_idx = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -571,15 +582,6 @@ static int apfs_write_ephemeral_objects(struct super_block *sb)
|
||||
eph_info = &nxi->nx_eph_list[i];
|
||||
data_next = (data_index + data_len) % data_blks;
|
||||
obj_blkcnt = eph_info->size >> sb->s_blocksize_bits;
|
||||
if (obj_blkcnt > data_blks - data_next) {
|
||||
/*
|
||||
* This multiblock object does not fit in what's left
|
||||
* of the ring buffer, so move it to the beginning and
|
||||
* leave some empty blocks.
|
||||
*/
|
||||
data_len += data_blks - data_next;
|
||||
data_next = 0;
|
||||
}
|
||||
|
||||
err = apfs_create_cpoint_map(sb, cpm, eph_info->object, data_base + data_next, eph_info->size);
|
||||
if (err) {
|
||||
@@ -638,7 +640,6 @@ static int apfs_transaction_commit_nx(struct super_block *sb)
|
||||
struct apfs_nx_transaction *nx_trans = &nxi->nx_transaction;
|
||||
struct apfs_bh_info *bhi, *tmp;
|
||||
int err = 0;
|
||||
u32 bmap_idx;
|
||||
|
||||
ASSERT(!(sb->s_flags & SB_RDONLY));
|
||||
|
||||
@@ -662,6 +663,16 @@ static int apfs_transaction_commit_nx(struct super_block *sb)
|
||||
}
|
||||
sm->sm_free_cache_base = sm->sm_free_cache_blkcnt = 0;
|
||||
}
|
||||
/*
|
||||
* Writing the ip bitmaps modifies the spaceman, so it must happen
|
||||
* before we commit the ephemeral objects. It must also happen after we
|
||||
* flush the free queue, in case the last freed range was in the ip.
|
||||
*/
|
||||
err = apfs_write_ip_bitmaps(sb);
|
||||
if (err) {
|
||||
apfs_err(sb, "failed to commit the ip bitmaps");
|
||||
return err;
|
||||
}
|
||||
err = apfs_write_ephemeral_objects(sb);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -682,7 +693,11 @@ static int apfs_transaction_commit_nx(struct super_block *sb)
|
||||
}
|
||||
list_for_each_entry_safe(bhi, tmp, &nx_trans->t_buffers, list) {
|
||||
struct buffer_head *bh = bhi->bh;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0)
|
||||
struct folio *folio = NULL;
|
||||
#else
|
||||
struct page *page = NULL;
|
||||
#endif
|
||||
bool is_metadata;
|
||||
|
||||
ASSERT(buffer_trans(bh));
|
||||
@@ -702,27 +717,44 @@ static int apfs_transaction_commit_nx(struct super_block *sb)
|
||||
kfree(bhi);
|
||||
bhi = NULL;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0)
|
||||
folio = page_folio(bh->b_page);
|
||||
folio_get(folio);
|
||||
#else
|
||||
page = bh->b_page;
|
||||
get_page(page);
|
||||
#endif
|
||||
|
||||
is_metadata = buffer_csum(bh);
|
||||
clear_buffer_csum(bh);
|
||||
put_bh(bh);
|
||||
bh = NULL;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0)
|
||||
folio_lock(folio);
|
||||
folio_mkclean(folio);
|
||||
#else
|
||||
/* Future writes to mmapped areas should fault for CoW */
|
||||
lock_page(page);
|
||||
page_mkclean(page);
|
||||
#endif
|
||||
/* XXX: otherwise, the page cache fills up and crashes the machine */
|
||||
if (!is_metadata) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0)
|
||||
try_to_free_buffers(folio);
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
try_to_free_buffers(page_folio(page));
|
||||
#else
|
||||
try_to_free_buffers(page);
|
||||
#endif
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0)
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
#else
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
#endif
|
||||
}
|
||||
err = apfs_checkpoint_end(sb);
|
||||
if (err) {
|
||||
@@ -730,12 +762,6 @@ static int apfs_transaction_commit_nx(struct super_block *sb)
|
||||
return err;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
APFS_SM(sb)->sm_raw = NULL;
|
||||
|
||||
nx_trans->t_starts_count = 0;
|
||||
nx_trans->t_buffers_count = 0;
|
||||
return 0;
|
||||
@@ -834,7 +860,6 @@ int apfs_transaction_commit(struct super_block *sb)
|
||||
mod_delayed_work(system_wq, &trans->t_work, msecs_to_jiffies(100));
|
||||
}
|
||||
|
||||
mutex_unlock(&nxs_mutex);
|
||||
up_write(&nxi->nx_big_sem);
|
||||
return 0;
|
||||
}
|
||||
@@ -921,14 +946,11 @@ void apfs_transaction_abort(struct super_block *sb)
|
||||
struct apfs_nx_transaction *nx_trans = &nxi->nx_transaction;
|
||||
struct apfs_bh_info *bhi, *tmp;
|
||||
struct apfs_inode_info *ai, *ai_tmp;
|
||||
struct apfs_spaceman *sm = NULL;
|
||||
u32 bmap_idx;
|
||||
|
||||
if (sb->s_flags & SB_RDONLY) {
|
||||
/* Transaction already aborted, do nothing */
|
||||
ASSERT(list_empty(&nx_trans->t_inodes));
|
||||
ASSERT(list_empty(&nx_trans->t_buffers));
|
||||
mutex_unlock(&nxs_mutex);
|
||||
up_write(&nxi->nx_big_sem);
|
||||
return;
|
||||
}
|
||||
@@ -951,22 +973,12 @@ void apfs_transaction_abort(struct super_block *sb)
|
||||
kfree(bhi);
|
||||
}
|
||||
|
||||
sm = APFS_SM(sb);
|
||||
if (sm) {
|
||||
for (bmap_idx = 0; bmap_idx < sm->sm_ip_bmaps_count; ++bmap_idx) {
|
||||
brelse(sm->sm_ip_bmaps[bmap_idx]);
|
||||
sm->sm_ip_bmaps[bmap_idx] = NULL;
|
||||
}
|
||||
APFS_SM(sb)->sm_raw = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's not possible to undo in-memory changes from old operations in
|
||||
* the aborted transaction. To avoid corruption, never write again.
|
||||
*/
|
||||
apfs_force_readonly(nxi);
|
||||
|
||||
mutex_unlock(&nxs_mutex);
|
||||
up_write(&nxi->nx_big_sem);
|
||||
|
||||
list_for_each_entry_safe(ai, ai_tmp, &nx_trans->t_inodes, i_list) {
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/nls.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/version.h>
|
||||
#include "unicode.h"
|
||||
|
||||
#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
|
||||
|
||||
/* The arrays of unicode data are defined at the bottom of the file */
|
||||
/* TODO: would a single trie with all the data be more efficient? */
|
||||
static u16 apfs_nfd_trie[];
|
||||
@@ -234,7 +233,7 @@ static int apfs_get_normalization_length(const char *utf8str, unsigned int total
|
||||
while (1) {
|
||||
if (!total_len || !*utf8str)
|
||||
return norm_len;
|
||||
utf8len = utf8_to_utf32(utf8str, MIN(total_len, 4), &utf32char);
|
||||
utf8len = utf8_to_utf32(utf8str, min(total_len, 4U), &utf32char);
|
||||
if (utf8len < 0) /* Invalid unicode; don't normalize anything */
|
||||
return 0;
|
||||
|
||||
@@ -306,7 +305,7 @@ new_starter:
|
||||
unicode_t utf32char;
|
||||
int utf8len, pos;
|
||||
|
||||
utf8len = utf8_to_utf32(utf8str, MIN(total_len, 4), &utf32char);
|
||||
utf8len = utf8_to_utf32(utf8str, min(total_len, 4U), &utf32char);
|
||||
for (pos = 0;; pos++, str_pos++) {
|
||||
unicode_t utf32norm;
|
||||
u8 ccc;
|
||||
|
||||
Reference in new issue
Block a user