mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
hfs/hfsplus updates for v7.2
- hfs: rework hfsplus_readdir() logic
- hfs: disable the updating of file access times (atime)
- hfs: fix incorrect inode ID assignment in hfs_new_inode()
- hfsplus: rework hfsplus_readdir() logic
- hfs/hfsplus: zero-initialize buffer in hfs_bnode_read
- hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length
- hfsplus: Add a sanity check for btree node size
- hfsplus: fix issue of direct writes beyond end-of-file
- hfs/hfxplus: use kzalloc_flex()
- hfsplus: Remove the duplicate attr inode dirty marking action
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQT4wVoLCG92poNnMFAhI4xTh21NnQUCai948AAKCRAhI4xTh21N
nRpsAP9w+yaRu3llG6VUMnKBtBOVkWkVO2SPVn4DGiNPIq+f3QEAzJguenZ6dn8N
/Yjznl4uwgZA1u86SM81mM8tLyICLwU=
=RwOP
-----END PGP SIGNATURE-----
Merge tag 'hfs-v7.2-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/vdubeyko/hfs
Pull hfs/hfsplus updates from Viacheslav Dubeyko:
"Several fixes in HFS/HFS+ of syzbot reported issues and HFS//HFS+
fixes of xfstests failures.
- fix a null-ptr-deref issue reported by syzbot (Edward Adam Davis)
If the attributes file is not loaded during system mount
hfsplus_create_attributes_file can dereference a NULL pointer.
Also, add a b-tree node size check in hfs_btree_open() with the
goal to prevent an uninit-value bug reported by syzbot for the case
of corrupted HFS+ image.
- fix __hfs_bnode_create() by using kzalloc_flex() instead of
kzalloc() (Rosen Penev)
- fix early return in hfs_bnode_read() (Tristan Madani)
hfs_bnode_read() can return early without writing to the output
buffer when is_bnode_offset_valid() fails or when
check_and_correct_requested_ length() corrects the length to zero.
Callers such as hfs_bnode_read_ u16() and hfs_bnode_read_u8() pass
stack-allocated buffers and use the result unconditionally, leading
to KMSAN uninit-value reports.
The rest fix (1) generic/637, generic/729 issue for the case of HFS+
file system, (2) generic/003, generic/637 for the case of HFS file
system"
* tag 'hfs-v7.2-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/vdubeyko/hfs:
hfs: rework hfsplus_readdir() logic
hfs: disable the updating of file access times (atime)
hfs: fix incorrect inode ID assignment in hfs_new_inode()
hfsplus: rework hfsplus_readdir() logic
hfs/hfsplus: zero-initialize buffer in hfs_bnode_read
hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length
hfsplus: Add a sanity check for btree node size
hfsplus: fix issue of direct writes beyond end-of-file
hfs/hfxplus: use kzalloc_flex()
hfsplus: Remove the duplicate attr inode dirty marking action
This commit is contained in:
commit
d29fd593e6
|
|
@ -41,7 +41,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len)
|
|||
|
||||
node_size = node->tree->node_size;
|
||||
|
||||
if ((off + len) > node_size) {
|
||||
if ((u64)off + len > node_size) {
|
||||
u32 new_len = node_size - off;
|
||||
|
||||
pr_err("requested length has been corrected: "
|
||||
|
|
@ -64,6 +64,8 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)
|
|||
u32 bytes_read;
|
||||
u32 bytes_to_read;
|
||||
|
||||
memset(buf, 0, len);
|
||||
|
||||
if (!is_bnode_offset_valid(node, off))
|
||||
return;
|
||||
|
||||
|
|
@ -344,7 +346,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
|
|||
struct hfs_bnode *node, *node2;
|
||||
struct address_space *mapping;
|
||||
struct page *page;
|
||||
int size, block, i, hash;
|
||||
int block, i, hash;
|
||||
loff_t off;
|
||||
|
||||
if (cnid >= tree->node_count) {
|
||||
|
|
@ -352,9 +354,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
|
||||
sizeof(struct page *);
|
||||
node = kzalloc(size, GFP_KERNEL);
|
||||
node = kzalloc_flex(*node, page, tree->pages_per_bnode, GFP_KERNEL);
|
||||
if (!node)
|
||||
return NULL;
|
||||
node->tree = tree;
|
||||
|
|
|
|||
|
|
@ -340,7 +340,6 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, const struct qstr *str)
|
|||
{
|
||||
struct super_block *sb;
|
||||
struct hfs_find_data fd;
|
||||
struct hfs_readdir_data *rd;
|
||||
int res, type;
|
||||
|
||||
hfs_dbg("name %s, cnid %u\n", str ? str->name : NULL, cnid);
|
||||
|
|
@ -366,14 +365,6 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, const struct qstr *str)
|
|||
}
|
||||
}
|
||||
|
||||
/* we only need to take spinlock for exclusion with ->release() */
|
||||
spin_lock(&HFS_I(dir)->open_dir_lock);
|
||||
list_for_each_entry(rd, &HFS_I(dir)->open_dir_list, list) {
|
||||
if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
|
||||
rd->file->f_pos--;
|
||||
}
|
||||
spin_unlock(&HFS_I(dir)->open_dir_lock);
|
||||
|
||||
res = hfs_brec_remove(&fd);
|
||||
if (res)
|
||||
goto out;
|
||||
|
|
|
|||
37
fs/hfs/dir.c
37
fs/hfs/dir.c
|
|
@ -97,7 +97,15 @@ static int hfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
}
|
||||
if (ctx->pos >= inode->i_size)
|
||||
goto out;
|
||||
err = hfs_brec_goto(&fd, ctx->pos - 1);
|
||||
rd = file->private_data;
|
||||
if (rd && rd->pos == ctx->pos) {
|
||||
memcpy(fd.search_key, &rd->key, sizeof(struct hfs_cat_key));
|
||||
err = hfs_brec_find(&fd);
|
||||
if (err == -ENOENT)
|
||||
err = hfs_brec_goto(&fd, 1);
|
||||
} else {
|
||||
err = hfs_brec_goto(&fd, ctx->pos - 1);
|
||||
}
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
@ -146,7 +154,6 @@ static int hfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
if (err)
|
||||
goto out;
|
||||
}
|
||||
rd = file->private_data;
|
||||
if (!rd) {
|
||||
rd = kmalloc_obj(struct hfs_readdir_data);
|
||||
if (!rd) {
|
||||
|
|
@ -154,15 +161,8 @@ static int hfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
goto out;
|
||||
}
|
||||
file->private_data = rd;
|
||||
rd->file = file;
|
||||
spin_lock(&HFS_I(inode)->open_dir_lock);
|
||||
list_add(&rd->list, &HFS_I(inode)->open_dir_list);
|
||||
spin_unlock(&HFS_I(inode)->open_dir_lock);
|
||||
}
|
||||
/*
|
||||
* Can be done after the list insertion; exclusion with
|
||||
* hfs_delete_cat() is provided by directory lock.
|
||||
*/
|
||||
rd->pos = ctx->pos;
|
||||
memcpy(&rd->key, &fd.key->cat, sizeof(struct hfs_cat_key));
|
||||
out:
|
||||
hfs_find_exit(&fd);
|
||||
|
|
@ -171,13 +171,7 @@ static int hfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
|
||||
static int hfs_dir_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct hfs_readdir_data *rd = file->private_data;
|
||||
if (rd) {
|
||||
spin_lock(&HFS_I(inode)->open_dir_lock);
|
||||
list_del(&rd->list);
|
||||
spin_unlock(&HFS_I(inode)->open_dir_lock);
|
||||
kfree(rd);
|
||||
}
|
||||
kfree(file->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -306,10 +300,15 @@ static int hfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
|||
res = hfs_cat_move(d_inode(old_dentry)->i_ino,
|
||||
old_dir, &old_dentry->d_name,
|
||||
new_dir, &new_dentry->d_name);
|
||||
if (!res)
|
||||
if (!res) {
|
||||
struct inode *inode = d_inode(old_dentry);
|
||||
|
||||
hfs_cat_build_key(old_dir->i_sb,
|
||||
(btree_key *)&HFS_I(d_inode(old_dentry))->cat_key,
|
||||
(btree_key *)&HFS_I(inode)->cat_key,
|
||||
new_dir->i_ino, &new_dentry->d_name);
|
||||
inode_set_ctime_current(inode);
|
||||
mark_inode_dirty(inode);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@
|
|||
/*======== Data structures kept in memory ========*/
|
||||
|
||||
struct hfs_readdir_data {
|
||||
struct list_head list;
|
||||
struct file *file;
|
||||
loff_t pos;
|
||||
struct hfs_cat_key key;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@ struct hfs_inode_info {
|
|||
|
||||
struct hfs_cat_key cat_key;
|
||||
|
||||
struct list_head open_dir_list;
|
||||
spinlock_t open_dir_lock;
|
||||
struct inode *rsrc_inode;
|
||||
|
||||
struct mutex extents_lock;
|
||||
|
|
|
|||
|
|
@ -196,8 +196,6 @@ struct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, umode_t
|
|||
err = -ERANGE;
|
||||
|
||||
mutex_init(&HFS_I(inode)->extents_lock);
|
||||
INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
|
||||
spin_lock_init(&HFS_I(inode)->open_dir_lock);
|
||||
hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
|
||||
next_id = atomic64_inc_return(&HFS_SB(sb)->next_id);
|
||||
if (next_id > U32_MAX) {
|
||||
|
|
@ -205,7 +203,7 @@ struct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, umode_t
|
|||
pr_err("cannot create new inode: next CNID exceeds limit\n");
|
||||
goto out_discard;
|
||||
}
|
||||
inode->i_ino = (u32)next_id;
|
||||
inode->i_ino = (u32)next_id - 1;
|
||||
inode->i_mode = mode;
|
||||
inode->i_uid = current_fsuid();
|
||||
inode->i_gid = current_fsgid();
|
||||
|
|
@ -349,12 +347,11 @@ static int hfs_read_inode(struct inode *inode, void *data)
|
|||
struct hfs_iget_data *idata = data;
|
||||
struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
|
||||
hfs_cat_rec *rec;
|
||||
struct timespec64 mtime;
|
||||
|
||||
HFS_I(inode)->flags = 0;
|
||||
HFS_I(inode)->rsrc_inode = NULL;
|
||||
mutex_init(&HFS_I(inode)->extents_lock);
|
||||
INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
|
||||
spin_lock_init(&HFS_I(inode)->open_dir_lock);
|
||||
|
||||
/* Initialize the inode */
|
||||
inode->i_uid = hsb->s_uid;
|
||||
|
|
@ -384,8 +381,10 @@ static int hfs_read_inode(struct inode *inode, void *data)
|
|||
inode->i_mode |= S_IWUGO;
|
||||
inode->i_mode &= ~hsb->s_file_umask;
|
||||
inode->i_mode |= S_IFREG;
|
||||
inode_set_mtime_to_ts(inode,
|
||||
inode_set_atime_to_ts(inode, inode_set_ctime_to_ts(inode, hfs_m_to_utime(rec->file.MdDat))));
|
||||
mtime = hfs_m_to_utime(rec->file.MdDat);
|
||||
inode_set_ctime_to_ts(inode, mtime);
|
||||
inode_set_atime_to_ts(inode, mtime);
|
||||
inode_set_mtime_to_ts(inode, mtime);
|
||||
inode->i_op = &hfs_file_inode_operations;
|
||||
inode->i_fop = &hfs_file_operations;
|
||||
inode->i_mapping->a_ops = &hfs_aops;
|
||||
|
|
@ -395,8 +394,10 @@ static int hfs_read_inode(struct inode *inode, void *data)
|
|||
inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
|
||||
HFS_I(inode)->fs_blocks = 0;
|
||||
inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
|
||||
inode_set_mtime_to_ts(inode,
|
||||
inode_set_atime_to_ts(inode, inode_set_ctime_to_ts(inode, hfs_m_to_utime(rec->dir.MdDat))));
|
||||
mtime = hfs_m_to_utime(rec->dir.MdDat);
|
||||
inode_set_ctime_to_ts(inode, mtime);
|
||||
inode_set_atime_to_ts(inode, mtime);
|
||||
inode_set_mtime_to_ts(inode, mtime);
|
||||
inode->i_op = &hfs_dir_inode_operations;
|
||||
inode->i_fop = &hfs_dir_operations;
|
||||
break;
|
||||
|
|
@ -666,7 +667,7 @@ int hfs_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
|||
|
||||
truncate_setsize(inode, attr->ia_size);
|
||||
hfs_file_truncate(inode);
|
||||
simple_inode_init_ts(inode);
|
||||
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
||||
}
|
||||
|
||||
setattr_copy(&nop_mnt_idmap, inode, attr);
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
|
|||
sbi->sb = sb;
|
||||
sb->s_op = &hfs_super_operations;
|
||||
sb->s_xattr = hfs_xattr_handlers;
|
||||
sb->s_flags |= SB_NODIRATIME;
|
||||
sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
|
||||
mutex_init(&sbi->bitmap_lock);
|
||||
|
||||
res = hfs_mdb_get(sb);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)
|
|||
struct page **pagep;
|
||||
u32 l;
|
||||
|
||||
memset(buf, 0, len);
|
||||
|
||||
if (!is_bnode_offset_valid(node, off))
|
||||
return;
|
||||
|
||||
|
|
@ -455,7 +457,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
|
|||
struct hfs_bnode *node, *node2;
|
||||
struct address_space *mapping;
|
||||
struct page *page;
|
||||
int size, block, i, hash;
|
||||
int block, i, hash;
|
||||
loff_t off;
|
||||
|
||||
if (cnid >= tree->node_count) {
|
||||
|
|
@ -464,9 +466,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
|
||||
sizeof(struct page *);
|
||||
node = kzalloc(size, GFP_KERNEL);
|
||||
node = kzalloc_flex(*node, page, tree->pages_per_bnode);
|
||||
if (!node)
|
||||
return NULL;
|
||||
node->tree = tree;
|
||||
|
|
|
|||
|
|
@ -365,6 +365,8 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
|
|||
}
|
||||
|
||||
size = tree->node_size;
|
||||
if (size < HFSPLUS_NODE_MINSZ || size > HFSPLUS_NODE_MXSZ)
|
||||
goto fail_page;
|
||||
if (!is_power_of_2(size))
|
||||
goto fail_page;
|
||||
if (!tree->node_count)
|
||||
|
|
|
|||
|
|
@ -333,7 +333,6 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, const struct qstr *str)
|
|||
struct super_block *sb = dir->i_sb;
|
||||
struct hfs_find_data fd;
|
||||
struct hfsplus_fork_raw fork;
|
||||
struct list_head *pos;
|
||||
int err, off;
|
||||
u16 type;
|
||||
|
||||
|
|
@ -392,16 +391,6 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, const struct qstr *str)
|
|||
hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC);
|
||||
}
|
||||
|
||||
/* we only need to take spinlock for exclusion with ->release() */
|
||||
spin_lock(&HFSPLUS_I(dir)->open_dir_lock);
|
||||
list_for_each(pos, &HFSPLUS_I(dir)->open_dir_list) {
|
||||
struct hfsplus_readdir_data *rd =
|
||||
list_entry(pos, struct hfsplus_readdir_data, list);
|
||||
if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
|
||||
rd->file->f_pos--;
|
||||
}
|
||||
spin_unlock(&HFSPLUS_I(dir)->open_dir_lock);
|
||||
|
||||
err = hfs_brec_remove(&fd);
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -185,7 +185,15 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
|
|||
}
|
||||
if (ctx->pos >= inode->i_size)
|
||||
goto out;
|
||||
err = hfs_brec_goto(&fd, ctx->pos - 1);
|
||||
rd = file->private_data;
|
||||
if (rd && rd->pos == ctx->pos) {
|
||||
memcpy(fd.search_key, &rd->key, sizeof(struct hfsplus_cat_key));
|
||||
err = hfs_brec_find(&fd, hfs_find_rec_by_key);
|
||||
if (err == -ENOENT)
|
||||
err = hfs_brec_goto(&fd, 1);
|
||||
} else {
|
||||
err = hfs_brec_goto(&fd, ctx->pos - 1);
|
||||
}
|
||||
if (err)
|
||||
goto out;
|
||||
for (;;) {
|
||||
|
|
@ -261,7 +269,6 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
|
|||
if (err)
|
||||
goto out;
|
||||
}
|
||||
rd = file->private_data;
|
||||
if (!rd) {
|
||||
rd = kmalloc_obj(struct hfsplus_readdir_data);
|
||||
if (!rd) {
|
||||
|
|
@ -269,15 +276,8 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
|
|||
goto out;
|
||||
}
|
||||
file->private_data = rd;
|
||||
rd->file = file;
|
||||
spin_lock(&HFSPLUS_I(inode)->open_dir_lock);
|
||||
list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list);
|
||||
spin_unlock(&HFSPLUS_I(inode)->open_dir_lock);
|
||||
}
|
||||
/*
|
||||
* Can be done after the list insertion; exclusion with
|
||||
* hfsplus_delete_cat() is provided by directory lock.
|
||||
*/
|
||||
rd->pos = ctx->pos;
|
||||
memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key));
|
||||
out:
|
||||
kfree(strbuf);
|
||||
|
|
@ -287,13 +287,7 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
|
|||
|
||||
static int hfsplus_dir_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct hfsplus_readdir_data *rd = file->private_data;
|
||||
if (rd) {
|
||||
spin_lock(&HFSPLUS_I(inode)->open_dir_lock);
|
||||
list_del(&rd->list);
|
||||
spin_unlock(&HFSPLUS_I(inode)->open_dir_lock);
|
||||
kfree(rd);
|
||||
}
|
||||
kfree(file->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,8 +214,6 @@ struct hfsplus_inode_info {
|
|||
sector_t fs_blocks;
|
||||
u8 userflags; /* BSD user file flags */
|
||||
u32 subfolders; /* Subfolder count (HFSX only) */
|
||||
struct list_head open_dir_list;
|
||||
spinlock_t open_dir_lock;
|
||||
loff_t phys_size;
|
||||
|
||||
struct inode vfs_inode;
|
||||
|
|
@ -272,8 +270,7 @@ struct hfs_find_data {
|
|||
};
|
||||
|
||||
struct hfsplus_readdir_data {
|
||||
struct list_head list;
|
||||
struct file *file;
|
||||
loff_t pos;
|
||||
struct hfsplus_cat_key key;
|
||||
};
|
||||
|
||||
|
|
@ -600,7 +597,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len)
|
|||
|
||||
node_size = node->tree->node_size;
|
||||
|
||||
if ((off + len) > node_size) {
|
||||
if ((u64)off + len > node_size) {
|
||||
u32 new_len = node_size - off;
|
||||
|
||||
pr_err("requested length has been corrected: "
|
||||
|
|
|
|||
|
|
@ -125,9 +125,44 @@ static ssize_t hfsplus_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|||
struct file *file = iocb->ki_filp;
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
loff_t isize;
|
||||
size_t count = iov_iter_count(iter);
|
||||
loff_t end = iocb->ki_pos + count;
|
||||
ssize_t ret;
|
||||
|
||||
/*
|
||||
* The hfsplus_get_block() only allows creating the next sequential block.
|
||||
* For direct writes beyond EOF, expand the file first.
|
||||
*/
|
||||
if (iov_iter_rw(iter) == WRITE && iocb->ki_pos > i_size_read(inode)) {
|
||||
loff_t start_off, end_off;
|
||||
loff_t start_page, end_page;
|
||||
|
||||
isize = i_size_read(inode);
|
||||
|
||||
/*
|
||||
* Wait for any in-flight DIO on this inode to finish before
|
||||
* calling generic_cont_expand_simple().
|
||||
*/
|
||||
inode_dio_wait(inode);
|
||||
|
||||
ret = generic_cont_expand_simple(inode, iocb->ki_pos);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
start_off = isize;
|
||||
end_off = (end > 0) ? end - 1 : end;
|
||||
|
||||
ret = filemap_write_and_wait_range(mapping, start_off, end_off);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
start_page = start_off >> PAGE_SHIFT;
|
||||
end_page = end_off >> PAGE_SHIFT;
|
||||
|
||||
invalidate_inode_pages2_range(mapping, start_page, end_page);
|
||||
}
|
||||
|
||||
ret = blockdev_direct_IO(iocb, inode, iter, hfsplus_get_block);
|
||||
|
||||
/*
|
||||
|
|
@ -135,8 +170,7 @@ static ssize_t hfsplus_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|||
* blocks outside i_size. Trim these off again.
|
||||
*/
|
||||
if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
|
||||
loff_t isize = i_size_read(inode);
|
||||
loff_t end = iocb->ki_pos + count;
|
||||
isize = i_size_read(inode);
|
||||
|
||||
if (end > isize)
|
||||
hfsplus_write_failed(mapping, end);
|
||||
|
|
@ -449,8 +483,6 @@ struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
|
|||
simple_inode_init_ts(inode);
|
||||
|
||||
hip = HFSPLUS_I(inode);
|
||||
INIT_LIST_HEAD(&hip->open_dir_list);
|
||||
spin_lock_init(&hip->open_dir_lock);
|
||||
mutex_init(&hip->extents_lock);
|
||||
atomic_set(&hip->opencnt, 0);
|
||||
hip->extent_state = 0;
|
||||
|
|
|
|||
|
|
@ -91,8 +91,6 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
|
|||
HFSPLUS_I(inode)->fs_blocks = 0;
|
||||
HFSPLUS_I(inode)->userflags = 0;
|
||||
HFSPLUS_I(inode)->subfolders = 0;
|
||||
INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list);
|
||||
spin_lock_init(&HFSPLUS_I(inode)->open_dir_lock);
|
||||
HFSPLUS_I(inode)->phys_size = 0;
|
||||
|
||||
if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
|
||||
|
|
|
|||
|
|
@ -317,7 +317,6 @@ static int hfsplus_create_attributes_file(struct super_block *sb)
|
|||
next_node++;
|
||||
}
|
||||
|
||||
hfsplus_mark_inode_dirty(HFSPLUS_ATTR_TREE_I(sb), HFSPLUS_I_ATTR_DIRTY);
|
||||
hfsplus_mark_inode_dirty(attr_file, HFSPLUS_I_ATTR_DIRTY);
|
||||
|
||||
sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID);
|
||||
|
|
|
|||
|
|
@ -513,6 +513,7 @@ struct hfs_btree_header_rec {
|
|||
/* HFS+ BTree misc info */
|
||||
#define HFSPLUS_TREE_HEAD 0
|
||||
#define HFSPLUS_NODE_MXSZ 32768
|
||||
#define HFSPLUS_NODE_MINSZ 512
|
||||
#define HFSPLUS_ATTR_TREE_NODE_SIZE 8192
|
||||
#define HFSPLUS_BTREE_HDR_NODE_RECS_COUNT 3
|
||||
#define HFSPLUS_BTREE_HDR_MAP_REC_INDEX 2 /* Map (bitmap) record in Header node */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user