xref: /linux/fs/hfsplus/inode.c (revision f4cdf7ca9a1fdcca413157df19753f388a5a224e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  linux/fs/hfsplus/inode.c
4  *
5  * Copyright (C) 2001
6  * Brad Boyer (flar@allandria.com)
7  * (C) 2003 Ardis Technologies <roman@ardistech.com>
8  *
9  * Inode handling routines
10  */
11 
12 #include <linux/blkdev.h>
13 #include <linux/mm.h>
14 #include <linux/fs.h>
15 #include <linux/pagemap.h>
16 #include <linux/mpage.h>
17 #include <linux/sched.h>
18 #include <linux/cred.h>
19 #include <linux/uio.h>
20 #include <linux/fileattr.h>
21 
22 #include "hfsplus_fs.h"
23 #include "hfsplus_raw.h"
24 #include "xattr.h"
25 
26 static int hfsplus_read_folio(struct file *file, struct folio *folio)
27 {
28 	return block_read_full_folio(folio, hfsplus_get_block);
29 }
30 
31 static void hfsplus_write_failed(struct address_space *mapping, loff_t to)
32 {
33 	struct inode *inode = mapping->host;
34 
35 	if (to > inode->i_size) {
36 		truncate_pagecache(inode, inode->i_size);
37 		hfsplus_file_truncate(inode);
38 	}
39 }
40 
41 int hfsplus_write_begin(const struct kiocb *iocb,
42 			struct address_space *mapping, loff_t pos,
43 			unsigned len, struct folio **foliop,
44 			void **fsdata)
45 {
46 	struct inode *inode = mapping->host;
47 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
48 	loff_t total_capacity;
49 	int ret;
50 
51 	total_capacity = (loff_t)sbi->total_blocks << sbi->alloc_blksz_shift;
52 
53 	if (pos >= total_capacity)
54 		return -EFBIG;
55 
56 	ret = cont_write_begin(iocb, mapping, pos, len, foliop, fsdata,
57 				hfsplus_get_block,
58 				&HFSPLUS_I(inode)->phys_size);
59 	if (unlikely(ret))
60 		hfsplus_write_failed(mapping, pos + len);
61 
62 	return ret;
63 }
64 
65 static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block)
66 {
67 	return generic_block_bmap(mapping, block, hfsplus_get_block);
68 }
69 
70 static bool hfsplus_release_folio(struct folio *folio, gfp_t mask)
71 {
72 	struct inode *inode = folio->mapping->host;
73 	struct super_block *sb = inode->i_sb;
74 	struct hfs_btree *tree;
75 	struct hfs_bnode *node;
76 	u32 nidx;
77 	int i;
78 	bool res = true;
79 
80 	switch (inode->i_ino) {
81 	case HFSPLUS_EXT_CNID:
82 		tree = HFSPLUS_SB(sb)->ext_tree;
83 		break;
84 	case HFSPLUS_CAT_CNID:
85 		tree = HFSPLUS_SB(sb)->cat_tree;
86 		break;
87 	case HFSPLUS_ATTR_CNID:
88 		tree = HFSPLUS_SB(sb)->attr_tree;
89 		break;
90 	default:
91 		BUG();
92 		return false;
93 	}
94 	if (!tree)
95 		return false;
96 	if (tree->node_size >= PAGE_SIZE) {
97 		nidx = folio->index >>
98 			(tree->node_size_shift - PAGE_SHIFT);
99 		spin_lock(&tree->hash_lock);
100 		node = hfs_bnode_findhash(tree, nidx);
101 		if (!node)
102 			;
103 		else if (atomic_read(&node->refcnt))
104 			res = false;
105 		if (res && node) {
106 			hfs_bnode_unhash(node);
107 			hfs_bnode_free(node);
108 		}
109 		spin_unlock(&tree->hash_lock);
110 	} else {
111 		nidx = folio->index <<
112 			(PAGE_SHIFT - tree->node_size_shift);
113 		i = 1 << (PAGE_SHIFT - tree->node_size_shift);
114 		spin_lock(&tree->hash_lock);
115 		do {
116 			node = hfs_bnode_findhash(tree, nidx++);
117 			if (!node)
118 				continue;
119 			if (atomic_read(&node->refcnt)) {
120 				res = false;
121 				break;
122 			}
123 			hfs_bnode_unhash(node);
124 			hfs_bnode_free(node);
125 		} while (--i && nidx < tree->node_count);
126 		spin_unlock(&tree->hash_lock);
127 	}
128 	return res ? try_to_free_buffers(folio) : false;
129 }
130 
131 static ssize_t hfsplus_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
132 {
133 	struct file *file = iocb->ki_filp;
134 	struct address_space *mapping = file->f_mapping;
135 	struct inode *inode = mapping->host;
136 	loff_t isize;
137 	size_t count = iov_iter_count(iter);
138 	loff_t end = iocb->ki_pos + count;
139 	ssize_t ret;
140 
141 	/*
142 	 * The hfsplus_get_block() only allows creating the next sequential block.
143 	 * For direct writes beyond EOF, expand the file first.
144 	 */
145 	if (iov_iter_rw(iter) == WRITE && iocb->ki_pos > i_size_read(inode)) {
146 		loff_t start_off, end_off;
147 		loff_t start_page, end_page;
148 
149 		isize = i_size_read(inode);
150 
151 		/*
152 		 * Wait for any in-flight DIO on this inode to finish before
153 		 * calling generic_cont_expand_simple().
154 		 */
155 		inode_dio_wait(inode);
156 
157 		ret = generic_cont_expand_simple(inode, iocb->ki_pos);
158 		if (ret)
159 			return ret;
160 
161 		start_off = isize;
162 		end_off = (end > 0) ? end - 1 : end;
163 
164 		ret = filemap_write_and_wait_range(mapping, start_off, end_off);
165 		if (ret)
166 			return ret;
167 
168 		start_page = start_off >> PAGE_SHIFT;
169 		end_page = end_off >> PAGE_SHIFT;
170 
171 		invalidate_inode_pages2_range(mapping, start_page, end_page);
172 	}
173 
174 	ret = blockdev_direct_IO(iocb, inode, iter, hfsplus_get_block);
175 
176 	/*
177 	 * In case of error extending write may have instantiated a few
178 	 * blocks outside i_size. Trim these off again.
179 	 */
180 	if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
181 		isize = i_size_read(inode);
182 
183 		if (end > isize)
184 			hfsplus_write_failed(mapping, end);
185 	}
186 
187 	return ret;
188 }
189 
190 static int hfsplus_writepages(struct address_space *mapping,
191 			      struct writeback_control *wbc)
192 {
193 	return mpage_writepages(mapping, wbc, hfsplus_get_block);
194 }
195 
196 const struct address_space_operations hfsplus_btree_aops = {
197 	.dirty_folio	= block_dirty_folio,
198 	.invalidate_folio = block_invalidate_folio,
199 	.read_folio	= hfsplus_read_folio,
200 	.writepages	= hfsplus_writepages,
201 	.write_begin	= hfsplus_write_begin,
202 	.write_end	= generic_write_end,
203 	.migrate_folio	= buffer_migrate_folio,
204 	.bmap		= hfsplus_bmap,
205 	.release_folio	= hfsplus_release_folio,
206 };
207 
208 const struct address_space_operations hfsplus_aops = {
209 	.dirty_folio	= block_dirty_folio,
210 	.invalidate_folio = block_invalidate_folio,
211 	.read_folio	= hfsplus_read_folio,
212 	.write_begin	= hfsplus_write_begin,
213 	.write_end	= generic_write_end,
214 	.bmap		= hfsplus_bmap,
215 	.direct_IO	= hfsplus_direct_IO,
216 	.writepages	= hfsplus_writepages,
217 	.migrate_folio	= buffer_migrate_folio,
218 };
219 
220 const struct dentry_operations hfsplus_dentry_operations = {
221 	.d_hash       = hfsplus_hash_dentry,
222 	.d_compare    = hfsplus_compare_dentry,
223 };
224 
225 static int hfsplus_get_perms(struct inode *inode,
226 			     struct hfsplus_perm *perms, int dir)
227 {
228 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
229 	u16 mode;
230 
231 	mode = be16_to_cpu(perms->mode);
232 	if (dir) {
233 		if (mode && !S_ISDIR(mode))
234 			goto bad_type;
235 	} else if (mode) {
236 		switch (mode & S_IFMT) {
237 		case S_IFREG:
238 		case S_IFLNK:
239 		case S_IFCHR:
240 		case S_IFBLK:
241 		case S_IFIFO:
242 		case S_IFSOCK:
243 			break;
244 		default:
245 			goto bad_type;
246 		}
247 	}
248 
249 	i_uid_write(inode, be32_to_cpu(perms->owner));
250 	if ((test_bit(HFSPLUS_SB_UID, &sbi->flags)) || (!i_uid_read(inode) && !mode))
251 		inode->i_uid = sbi->uid;
252 
253 	i_gid_write(inode, be32_to_cpu(perms->group));
254 	if ((test_bit(HFSPLUS_SB_GID, &sbi->flags)) || (!i_gid_read(inode) && !mode))
255 		inode->i_gid = sbi->gid;
256 
257 	if (dir) {
258 		mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask));
259 		mode |= S_IFDIR;
260 	} else if (!mode)
261 		mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask));
262 	inode->i_mode = mode;
263 
264 	HFSPLUS_I(inode)->userflags = perms->userflags;
265 	if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE)
266 		inode->i_flags |= S_IMMUTABLE;
267 	else
268 		inode->i_flags &= ~S_IMMUTABLE;
269 	if (perms->rootflags & HFSPLUS_FLG_APPEND)
270 		inode->i_flags |= S_APPEND;
271 	else
272 		inode->i_flags &= ~S_APPEND;
273 	return 0;
274 bad_type:
275 	pr_err("invalid file type 0%04o for inode %llu\n", mode, inode->i_ino);
276 	return -EIO;
277 }
278 
279 static int hfsplus_file_open(struct inode *inode, struct file *file)
280 {
281 	if (HFSPLUS_IS_RSRC(inode))
282 		inode = HFSPLUS_I(inode)->rsrc_inode;
283 	if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
284 		return -EOVERFLOW;
285 	atomic_inc(&HFSPLUS_I(inode)->opencnt);
286 	return 0;
287 }
288 
289 static int hfsplus_file_release(struct inode *inode, struct file *file)
290 {
291 	struct super_block *sb = inode->i_sb;
292 
293 	if (HFSPLUS_IS_RSRC(inode))
294 		inode = HFSPLUS_I(inode)->rsrc_inode;
295 	if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) {
296 		inode_lock(inode);
297 		hfsplus_file_truncate(inode);
298 		if (inode->i_flags & S_DEAD) {
299 			hfsplus_delete_cat(inode->i_ino,
300 					   HFSPLUS_SB(sb)->hidden_dir, NULL);
301 			hfsplus_delete_inode(inode);
302 		}
303 		inode_unlock(inode);
304 	}
305 	return 0;
306 }
307 
308 static int hfsplus_setattr(struct mnt_idmap *idmap,
309 			   struct dentry *dentry, struct iattr *attr)
310 {
311 	struct inode *inode = d_inode(dentry);
312 	int error;
313 
314 	error = setattr_prepare(&nop_mnt_idmap, dentry, attr);
315 	if (error)
316 		return error;
317 
318 	if ((attr->ia_valid & ATTR_SIZE) &&
319 	    attr->ia_size != i_size_read(inode)) {
320 		inode_dio_wait(inode);
321 		if (attr->ia_size > inode->i_size) {
322 			error = generic_cont_expand_simple(inode,
323 							   attr->ia_size);
324 			if (error)
325 				return error;
326 		}
327 		truncate_setsize(inode, attr->ia_size);
328 		hfsplus_file_truncate(inode);
329 		inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
330 	}
331 
332 	setattr_copy(&nop_mnt_idmap, inode, attr);
333 	mark_inode_dirty(inode);
334 
335 	return 0;
336 }
337 
338 int hfsplus_getattr(struct mnt_idmap *idmap, const struct path *path,
339 		    struct kstat *stat, u32 request_mask,
340 		    unsigned int query_flags)
341 {
342 	struct inode *inode = d_inode(path->dentry);
343 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
344 
345 	if (request_mask & STATX_BTIME) {
346 		stat->result_mask |= STATX_BTIME;
347 		stat->btime = hfsp_mt2ut(hip->create_date);
348 	}
349 
350 	if (inode->i_flags & S_APPEND)
351 		stat->attributes |= STATX_ATTR_APPEND;
352 	if (inode->i_flags & S_IMMUTABLE)
353 		stat->attributes |= STATX_ATTR_IMMUTABLE;
354 	if (hip->userflags & HFSPLUS_FLG_NODUMP)
355 		stat->attributes |= STATX_ATTR_NODUMP;
356 
357 	stat->attributes_mask |= STATX_ATTR_APPEND | STATX_ATTR_IMMUTABLE |
358 				 STATX_ATTR_NODUMP;
359 
360 	generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
361 	return 0;
362 }
363 
364 int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
365 		       int datasync)
366 {
367 	struct inode *inode = file->f_mapping->host;
368 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
369 	struct super_block *sb = inode->i_sb;
370 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
371 	struct hfsplus_vh *vhdr = sbi->s_vhdr;
372 	int error = 0, error2;
373 
374 	hfs_dbg("inode->i_ino %llu, start %llu, end %llu\n",
375 		inode->i_ino, start, end);
376 
377 	error = file_write_and_wait_range(file, start, end);
378 	if (error)
379 		return error;
380 	inode_lock(inode);
381 
382 	/*
383 	 * Sync inode metadata into the catalog and extent trees.
384 	 */
385 	sync_inode_metadata(inode, 1);
386 
387 	/*
388 	 * And explicitly write out the btrees.
389 	 */
390 	if (test_and_clear_bit(HFSPLUS_I_CAT_DIRTY,
391 				&HFSPLUS_I(HFSPLUS_CAT_TREE_I(sb))->flags)) {
392 		clear_bit(HFSPLUS_I_CAT_DIRTY, &hip->flags);
393 		error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping);
394 	}
395 
396 	if (test_and_clear_bit(HFSPLUS_I_EXT_DIRTY,
397 				&HFSPLUS_I(HFSPLUS_EXT_TREE_I(sb))->flags)) {
398 		clear_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags);
399 		error2 =
400 			filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
401 		if (!error)
402 			error = error2;
403 	}
404 
405 	if (sbi->attr_tree) {
406 		if (test_and_clear_bit(HFSPLUS_I_ATTR_DIRTY,
407 				&HFSPLUS_I(HFSPLUS_ATTR_TREE_I(sb))->flags)) {
408 			clear_bit(HFSPLUS_I_ATTR_DIRTY, &hip->flags);
409 			error2 =
410 				filemap_write_and_wait(
411 					    sbi->attr_tree->inode->i_mapping);
412 			if (!error)
413 				error = error2;
414 		}
415 	} else {
416 		if (test_and_clear_bit(HFSPLUS_I_ATTR_DIRTY, &hip->flags))
417 			pr_err("sync non-existent attributes tree\n");
418 	}
419 
420 	if (test_and_clear_bit(HFSPLUS_I_ALLOC_DIRTY,
421 				&HFSPLUS_I(sbi->alloc_file)->flags)) {
422 		clear_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags);
423 		error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
424 		if (!error)
425 			error = error2;
426 	}
427 
428 	mutex_lock(&sbi->vh_mutex);
429 	hfsplus_prepare_volume_header_for_commit(vhdr);
430 	mutex_unlock(&sbi->vh_mutex);
431 
432 	error2 = hfsplus_commit_superblock(inode->i_sb);
433 	if (!error)
434 		error = error2;
435 
436 	if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
437 		blkdev_issue_flush(inode->i_sb->s_bdev);
438 
439 	inode_unlock(inode);
440 
441 	return error;
442 }
443 
444 static const struct inode_operations hfsplus_file_inode_operations = {
445 	.setattr	= hfsplus_setattr,
446 	.getattr	= hfsplus_getattr,
447 	.listxattr	= hfsplus_listxattr,
448 	.fileattr_get	= hfsplus_fileattr_get,
449 	.fileattr_set	= hfsplus_fileattr_set,
450 };
451 
452 static const struct inode_operations hfsplus_symlink_inode_operations = {
453 	.get_link	= page_get_link,
454 	.setattr	= hfsplus_setattr,
455 	.getattr	= hfsplus_getattr,
456 	.listxattr	= hfsplus_listxattr,
457 };
458 
459 static const struct inode_operations hfsplus_special_inode_operations = {
460 	.setattr	= hfsplus_setattr,
461 	.getattr	= hfsplus_getattr,
462 	.listxattr	= hfsplus_listxattr,
463 };
464 
465 static const struct file_operations hfsplus_file_operations = {
466 	.llseek		= generic_file_llseek,
467 	.read_iter	= generic_file_read_iter,
468 	.write_iter	= generic_file_write_iter,
469 	.mmap_prepare	= generic_file_mmap_prepare,
470 	.splice_read	= filemap_splice_read,
471 	.splice_write	= iter_file_splice_write,
472 	.fsync		= hfsplus_file_fsync,
473 	.open		= hfsplus_file_open,
474 	.release	= hfsplus_file_release,
475 	.unlocked_ioctl = hfsplus_ioctl,
476 };
477 
478 struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
479 				umode_t mode)
480 {
481 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
482 	struct inode *inode = new_inode(sb);
483 	struct hfsplus_inode_info *hip;
484 
485 	if (!inode)
486 		return NULL;
487 
488 	inode->i_ino = sbi->next_cnid++;
489 	inode_init_owner(&nop_mnt_idmap, inode, dir, mode);
490 	set_nlink(inode, 1);
491 	simple_inode_init_ts(inode);
492 
493 	hip = HFSPLUS_I(inode);
494 	mutex_init(&hip->extents_lock);
495 	atomic_set(&hip->opencnt, 0);
496 	hip->extent_state = 0;
497 	hip->flags = 0;
498 	hip->userflags = 0;
499 	hip->subfolders = 0;
500 	memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
501 	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
502 	hip->alloc_blocks = 0;
503 	hip->first_blocks = 0;
504 	hip->cached_start = 0;
505 	hip->cached_blocks = 0;
506 	hip->phys_size = 0;
507 	hip->fs_blocks = 0;
508 	hip->rsrc_inode = NULL;
509 	if (S_ISDIR(inode->i_mode)) {
510 		inode->i_size = 2;
511 		sbi->folder_count++;
512 		inode->i_op = &hfsplus_dir_inode_operations;
513 		inode->i_fop = &hfsplus_dir_operations;
514 	} else if (S_ISREG(inode->i_mode)) {
515 		sbi->file_count++;
516 		inode->i_op = &hfsplus_file_inode_operations;
517 		inode->i_fop = &hfsplus_file_operations;
518 		inode->i_mapping->a_ops = &hfsplus_aops;
519 		hip->clump_blocks = sbi->data_clump_blocks;
520 	} else if (S_ISLNK(inode->i_mode)) {
521 		sbi->file_count++;
522 		inode->i_op = &hfsplus_symlink_inode_operations;
523 		inode_nohighmem(inode);
524 		inode->i_mapping->a_ops = &hfsplus_aops;
525 		hip->clump_blocks = 1;
526 	} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
527 		   S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
528 		sbi->file_count++;
529 		inode->i_op = &hfsplus_special_inode_operations;
530 	} else
531 		sbi->file_count++;
532 
533 	insert_inode_hash(inode);
534 	mark_inode_dirty(inode);
535 	hfsplus_mark_mdb_dirty(sb);
536 
537 	return inode;
538 }
539 
540 void hfsplus_delete_inode(struct inode *inode)
541 {
542 	struct super_block *sb = inode->i_sb;
543 
544 	if (S_ISDIR(inode->i_mode)) {
545 		HFSPLUS_SB(sb)->folder_count--;
546 		hfsplus_mark_mdb_dirty(sb);
547 		return;
548 	}
549 	HFSPLUS_SB(sb)->file_count--;
550 	if (S_ISREG(inode->i_mode)) {
551 		if (!inode->i_nlink) {
552 			inode->i_size = 0;
553 			hfsplus_file_truncate(inode);
554 		}
555 	} else if (S_ISLNK(inode->i_mode)) {
556 		inode->i_size = 0;
557 		hfsplus_file_truncate(inode);
558 	}
559 	hfsplus_mark_mdb_dirty(sb);
560 }
561 
562 void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
563 {
564 	struct super_block *sb = inode->i_sb;
565 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
566 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
567 	u32 count;
568 	int i;
569 
570 	memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec));
571 	for (count = 0, i = 0; i < 8; i++)
572 		count += be32_to_cpu(fork->extents[i].block_count);
573 	hip->first_blocks = count;
574 	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
575 	hip->cached_start = 0;
576 	hip->cached_blocks = 0;
577 
578 	hip->alloc_blocks = be32_to_cpu(fork->total_blocks);
579 	hip->phys_size = inode->i_size = be64_to_cpu(fork->total_size);
580 	hip->fs_blocks =
581 		(inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
582 	inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
583 	hip->clump_blocks =
584 		be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift;
585 	if (!hip->clump_blocks) {
586 		hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ?
587 			sbi->rsrc_clump_blocks :
588 			sbi->data_clump_blocks;
589 	}
590 }
591 
592 void hfsplus_inode_write_fork(struct inode *inode,
593 		struct hfsplus_fork_raw *fork)
594 {
595 	memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents,
596 	       sizeof(hfsplus_extent_rec));
597 	fork->total_size = cpu_to_be64(inode->i_size);
598 	fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks);
599 }
600 
601 int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
602 {
603 	hfsplus_cat_entry entry;
604 	int res = 0;
605 	u16 type;
606 
607 	type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
608 
609 	HFSPLUS_I(inode)->linkid = 0;
610 	if (type == HFSPLUS_FOLDER) {
611 		struct hfsplus_cat_folder *folder = &entry.folder;
612 
613 		if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) {
614 			pr_err("bad catalog folder entry\n");
615 			res = -EIO;
616 			goto out;
617 		}
618 		hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
619 					sizeof(struct hfsplus_cat_folder));
620 		res = hfsplus_get_perms(inode, &folder->permissions, 1);
621 		if (res)
622 			goto out;
623 		set_nlink(inode, 1);
624 		inode->i_size = 2 + be32_to_cpu(folder->valence);
625 		inode_set_atime_to_ts(inode, hfsp_mt2ut(folder->access_date));
626 		inode_set_mtime_to_ts(inode,
627 				      hfsp_mt2ut(folder->content_mod_date));
628 		inode_set_ctime_to_ts(inode,
629 				      hfsp_mt2ut(folder->attribute_mod_date));
630 		HFSPLUS_I(inode)->create_date = folder->create_date;
631 		HFSPLUS_I(inode)->fs_blocks = 0;
632 		if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
633 			HFSPLUS_I(inode)->subfolders =
634 				be32_to_cpu(folder->subfolders);
635 		}
636 		inode->i_op = &hfsplus_dir_inode_operations;
637 		inode->i_fop = &hfsplus_dir_operations;
638 	} else if (type == HFSPLUS_FILE) {
639 		struct hfsplus_cat_file *file = &entry.file;
640 
641 		if (fd->entrylength < sizeof(struct hfsplus_cat_file)) {
642 			pr_err("bad catalog file entry\n");
643 			res = -EIO;
644 			goto out;
645 		}
646 		hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
647 					sizeof(struct hfsplus_cat_file));
648 
649 		hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ?
650 					&file->rsrc_fork : &file->data_fork);
651 		res = hfsplus_get_perms(inode, &file->permissions, 0);
652 		if (res)
653 			goto out;
654 		set_nlink(inode, 1);
655 		if (S_ISREG(inode->i_mode)) {
656 			if (file->permissions.dev)
657 				set_nlink(inode,
658 					  be32_to_cpu(file->permissions.dev));
659 			inode->i_op = &hfsplus_file_inode_operations;
660 			inode->i_fop = &hfsplus_file_operations;
661 			inode->i_mapping->a_ops = &hfsplus_aops;
662 		} else if (S_ISLNK(inode->i_mode)) {
663 			inode->i_op = &hfsplus_symlink_inode_operations;
664 			inode_nohighmem(inode);
665 			inode->i_mapping->a_ops = &hfsplus_aops;
666 		} else {
667 			inode->i_op = &hfsplus_special_inode_operations;
668 			init_special_inode(inode, inode->i_mode,
669 					   be32_to_cpu(file->permissions.dev));
670 		}
671 		inode_set_atime_to_ts(inode, hfsp_mt2ut(file->access_date));
672 		inode_set_mtime_to_ts(inode,
673 				      hfsp_mt2ut(file->content_mod_date));
674 		inode_set_ctime_to_ts(inode,
675 				      hfsp_mt2ut(file->attribute_mod_date));
676 		HFSPLUS_I(inode)->create_date = file->create_date;
677 	} else {
678 		pr_err("bad catalog entry used to create inode\n");
679 		res = -EIO;
680 	}
681 out:
682 	return res;
683 }
684 
685 int hfsplus_cat_write_inode(struct inode *inode)
686 {
687 	struct inode *main_inode = inode;
688 	struct hfs_btree *tree = HFSPLUS_SB(inode->i_sb)->cat_tree;
689 	struct hfs_find_data fd;
690 	hfsplus_cat_entry entry;
691 	int res = 0;
692 
693 	hfs_dbg("inode->i_ino %llu\n", inode->i_ino);
694 
695 	if (HFSPLUS_IS_RSRC(inode))
696 		main_inode = HFSPLUS_I(inode)->rsrc_inode;
697 
698 	if (!main_inode->i_nlink)
699 		return 0;
700 
701 	if (hfs_find_init(tree, &fd))
702 		/* panic? */
703 		return -EIO;
704 
705 	if (hfsplus_find_cat(main_inode->i_sb, main_inode->i_ino, &fd))
706 		/* panic? */
707 		goto out;
708 
709 	if (S_ISDIR(main_inode->i_mode)) {
710 		struct hfsplus_cat_folder *folder = &entry.folder;
711 
712 		if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
713 			pr_err("bad catalog folder entry\n");
714 			res = -EIO;
715 			goto out;
716 		}
717 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
718 					sizeof(struct hfsplus_cat_folder));
719 		/* simple node checks? */
720 		hfsplus_cat_set_perms(inode, &folder->permissions);
721 		folder->access_date = hfsp_ut2mt(inode_get_atime(inode));
722 		folder->content_mod_date = hfsp_ut2mt(inode_get_mtime(inode));
723 		folder->attribute_mod_date = hfsp_ut2mt(inode_get_ctime(inode));
724 		folder->valence = cpu_to_be32(inode->i_size - 2);
725 		if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
726 			folder->subfolders =
727 				cpu_to_be32(HFSPLUS_I(inode)->subfolders);
728 		}
729 		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
730 					 sizeof(struct hfsplus_cat_folder));
731 	} else if (HFSPLUS_IS_RSRC(inode)) {
732 		struct hfsplus_cat_file *file = &entry.file;
733 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
734 			       sizeof(struct hfsplus_cat_file));
735 		hfsplus_inode_write_fork(inode, &file->rsrc_fork);
736 		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
737 				sizeof(struct hfsplus_cat_file));
738 	} else {
739 		struct hfsplus_cat_file *file = &entry.file;
740 
741 		if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
742 			pr_err("bad catalog file entry\n");
743 			res = -EIO;
744 			goto out;
745 		}
746 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
747 					sizeof(struct hfsplus_cat_file));
748 		hfsplus_inode_write_fork(inode, &file->data_fork);
749 		hfsplus_cat_set_perms(inode, &file->permissions);
750 		if (HFSPLUS_FLG_IMMUTABLE &
751 				(file->permissions.rootflags |
752 					file->permissions.userflags))
753 			file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
754 		else
755 			file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED);
756 		file->access_date = hfsp_ut2mt(inode_get_atime(inode));
757 		file->content_mod_date = hfsp_ut2mt(inode_get_mtime(inode));
758 		file->attribute_mod_date = hfsp_ut2mt(inode_get_ctime(inode));
759 		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
760 					 sizeof(struct hfsplus_cat_file));
761 	}
762 
763 	res = hfs_btree_write(tree);
764 	if (res) {
765 		pr_err("b-tree write err: %d, ino %llu\n",
766 		       res, inode->i_ino);
767 		goto out;
768 	}
769 
770 	set_bit(HFSPLUS_I_CAT_DIRTY,
771 		&HFSPLUS_I(HFSPLUS_CAT_TREE_I(inode->i_sb))->flags);
772 	set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
773 out:
774 	hfs_find_exit(&fd);
775 
776 	return res;
777 }
778 
779 int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
780 {
781 	struct inode *inode = d_inode(dentry);
782 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
783 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
784 	unsigned int flags = 0;
785 
786 	if (inode->i_flags & S_IMMUTABLE)
787 		flags |= FS_IMMUTABLE_FL;
788 	if (inode->i_flags & S_APPEND)
789 		flags |= FS_APPEND_FL;
790 	if (hip->userflags & HFSPLUS_FLG_NODUMP)
791 		flags |= FS_NODUMP_FL;
792 	if (test_bit(HFSPLUS_SB_CASEFOLD, &sbi->flags))
793 		flags |= FS_CASEFOLD_FL;
794 
795 	fileattr_fill_flags(fa, flags);
796 
797 	return 0;
798 }
799 
800 int hfsplus_fileattr_set(struct mnt_idmap *idmap,
801 			 struct dentry *dentry, struct file_kattr *fa)
802 {
803 	struct inode *inode = d_inode(dentry);
804 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
805 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
806 	unsigned int allowed = FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL;
807 	unsigned int new_fl = 0;
808 
809 	if (fileattr_has_fsx(fa))
810 		return -EOPNOTSUPP;
811 
812 	/*
813 	 * FS_CASEFOLD_FL reflects HFSPLUS_SB_CASEFOLD, a mount-time
814 	 * property. Accept it as a no-op so chattr's RMW round-trip
815 	 * succeeds; reject any attempt to enable it on a volume that
816 	 * was not formatted case-insensitive.
817 	 */
818 	if (test_bit(HFSPLUS_SB_CASEFOLD, &sbi->flags))
819 		allowed |= FS_CASEFOLD_FL;
820 
821 	/* don't silently ignore unsupported ext2 flags */
822 	if (fa->flags & ~allowed)
823 		return -EOPNOTSUPP;
824 
825 	if (fa->flags & FS_IMMUTABLE_FL)
826 		new_fl |= S_IMMUTABLE;
827 
828 	if (fa->flags & FS_APPEND_FL)
829 		new_fl |= S_APPEND;
830 
831 	inode_set_flags(inode, new_fl, S_IMMUTABLE | S_APPEND);
832 
833 	if (fa->flags & FS_NODUMP_FL)
834 		hip->userflags |= HFSPLUS_FLG_NODUMP;
835 	else
836 		hip->userflags &= ~HFSPLUS_FLG_NODUMP;
837 
838 	inode_set_ctime_current(inode);
839 	mark_inode_dirty(inode);
840 
841 	return 0;
842 }
843