xref: /linux/fs/ntfs3/fsntfs.c (revision 3f5ef510)
182cae269SKonstantin Komarov // SPDX-License-Identifier: GPL-2.0
282cae269SKonstantin Komarov /*
382cae269SKonstantin Komarov  *
482cae269SKonstantin Komarov  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
582cae269SKonstantin Komarov  *
682cae269SKonstantin Komarov  */
782cae269SKonstantin Komarov 
882cae269SKonstantin Komarov #include <linux/blkdev.h>
982cae269SKonstantin Komarov #include <linux/buffer_head.h>
1082cae269SKonstantin Komarov #include <linux/fs.h>
11b5322eb1SKari Argillander #include <linux/kernel.h>
127832e123SKonstantin Komarov #include <linux/nls.h>
1382cae269SKonstantin Komarov 
1482cae269SKonstantin Komarov #include "debug.h"
1582cae269SKonstantin Komarov #include "ntfs.h"
1682cae269SKonstantin Komarov #include "ntfs_fs.h"
1782cae269SKonstantin Komarov 
1882cae269SKonstantin Komarov // clang-format off
1982cae269SKonstantin Komarov const struct cpu_str NAME_MFT = {
2082cae269SKonstantin Komarov 	4, 0, { '$', 'M', 'F', 'T' },
2182cae269SKonstantin Komarov };
2282cae269SKonstantin Komarov const struct cpu_str NAME_MIRROR = {
2382cae269SKonstantin Komarov 	8, 0, { '$', 'M', 'F', 'T', 'M', 'i', 'r', 'r' },
2482cae269SKonstantin Komarov };
2582cae269SKonstantin Komarov const struct cpu_str NAME_LOGFILE = {
2682cae269SKonstantin Komarov 	8, 0, { '$', 'L', 'o', 'g', 'F', 'i', 'l', 'e' },
2782cae269SKonstantin Komarov };
2882cae269SKonstantin Komarov const struct cpu_str NAME_VOLUME = {
2982cae269SKonstantin Komarov 	7, 0, { '$', 'V', 'o', 'l', 'u', 'm', 'e' },
3082cae269SKonstantin Komarov };
3182cae269SKonstantin Komarov const struct cpu_str NAME_ATTRDEF = {
3282cae269SKonstantin Komarov 	8, 0, { '$', 'A', 't', 't', 'r', 'D', 'e', 'f' },
3382cae269SKonstantin Komarov };
3482cae269SKonstantin Komarov const struct cpu_str NAME_ROOT = {
3582cae269SKonstantin Komarov 	1, 0, { '.' },
3682cae269SKonstantin Komarov };
3782cae269SKonstantin Komarov const struct cpu_str NAME_BITMAP = {
3882cae269SKonstantin Komarov 	7, 0, { '$', 'B', 'i', 't', 'm', 'a', 'p' },
3982cae269SKonstantin Komarov };
4082cae269SKonstantin Komarov const struct cpu_str NAME_BOOT = {
4182cae269SKonstantin Komarov 	5, 0, { '$', 'B', 'o', 'o', 't' },
4282cae269SKonstantin Komarov };
4382cae269SKonstantin Komarov const struct cpu_str NAME_BADCLUS = {
4482cae269SKonstantin Komarov 	8, 0, { '$', 'B', 'a', 'd', 'C', 'l', 'u', 's' },
4582cae269SKonstantin Komarov };
4682cae269SKonstantin Komarov const struct cpu_str NAME_QUOTA = {
4782cae269SKonstantin Komarov 	6, 0, { '$', 'Q', 'u', 'o', 't', 'a' },
4882cae269SKonstantin Komarov };
4982cae269SKonstantin Komarov const struct cpu_str NAME_SECURE = {
5082cae269SKonstantin Komarov 	7, 0, { '$', 'S', 'e', 'c', 'u', 'r', 'e' },
5182cae269SKonstantin Komarov };
5282cae269SKonstantin Komarov const struct cpu_str NAME_UPCASE = {
5382cae269SKonstantin Komarov 	7, 0, { '$', 'U', 'p', 'C', 'a', 's', 'e' },
5482cae269SKonstantin Komarov };
5582cae269SKonstantin Komarov const struct cpu_str NAME_EXTEND = {
5682cae269SKonstantin Komarov 	7, 0, { '$', 'E', 'x', 't', 'e', 'n', 'd' },
5782cae269SKonstantin Komarov };
5882cae269SKonstantin Komarov const struct cpu_str NAME_OBJID = {
5982cae269SKonstantin Komarov 	6, 0, { '$', 'O', 'b', 'j', 'I', 'd' },
6082cae269SKonstantin Komarov };
6182cae269SKonstantin Komarov const struct cpu_str NAME_REPARSE = {
6282cae269SKonstantin Komarov 	8, 0, { '$', 'R', 'e', 'p', 'a', 'r', 's', 'e' },
6382cae269SKonstantin Komarov };
6482cae269SKonstantin Komarov const struct cpu_str NAME_USNJRNL = {
6582cae269SKonstantin Komarov 	8, 0, { '$', 'U', 's', 'n', 'J', 'r', 'n', 'l' },
6682cae269SKonstantin Komarov };
6782cae269SKonstantin Komarov const __le16 BAD_NAME[4] = {
6882cae269SKonstantin Komarov 	cpu_to_le16('$'), cpu_to_le16('B'), cpu_to_le16('a'), cpu_to_le16('d'),
6982cae269SKonstantin Komarov };
7082cae269SKonstantin Komarov const __le16 I30_NAME[4] = {
7182cae269SKonstantin Komarov 	cpu_to_le16('$'), cpu_to_le16('I'), cpu_to_le16('3'), cpu_to_le16('0'),
7282cae269SKonstantin Komarov };
7382cae269SKonstantin Komarov const __le16 SII_NAME[4] = {
7482cae269SKonstantin Komarov 	cpu_to_le16('$'), cpu_to_le16('S'), cpu_to_le16('I'), cpu_to_le16('I'),
7582cae269SKonstantin Komarov };
7682cae269SKonstantin Komarov const __le16 SDH_NAME[4] = {
7782cae269SKonstantin Komarov 	cpu_to_le16('$'), cpu_to_le16('S'), cpu_to_le16('D'), cpu_to_le16('H'),
7882cae269SKonstantin Komarov };
7982cae269SKonstantin Komarov const __le16 SDS_NAME[4] = {
8082cae269SKonstantin Komarov 	cpu_to_le16('$'), cpu_to_le16('S'), cpu_to_le16('D'), cpu_to_le16('S'),
8182cae269SKonstantin Komarov };
8282cae269SKonstantin Komarov const __le16 SO_NAME[2] = {
8382cae269SKonstantin Komarov 	cpu_to_le16('$'), cpu_to_le16('O'),
8482cae269SKonstantin Komarov };
8582cae269SKonstantin Komarov const __le16 SQ_NAME[2] = {
8682cae269SKonstantin Komarov 	cpu_to_le16('$'), cpu_to_le16('Q'),
8782cae269SKonstantin Komarov };
8882cae269SKonstantin Komarov const __le16 SR_NAME[2] = {
8982cae269SKonstantin Komarov 	cpu_to_le16('$'), cpu_to_le16('R'),
9082cae269SKonstantin Komarov };
9182cae269SKonstantin Komarov 
9282cae269SKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS
9382cae269SKonstantin Komarov const __le16 WOF_NAME[17] = {
9482cae269SKonstantin Komarov 	cpu_to_le16('W'), cpu_to_le16('o'), cpu_to_le16('f'), cpu_to_le16('C'),
9582cae269SKonstantin Komarov 	cpu_to_le16('o'), cpu_to_le16('m'), cpu_to_le16('p'), cpu_to_le16('r'),
9682cae269SKonstantin Komarov 	cpu_to_le16('e'), cpu_to_le16('s'), cpu_to_le16('s'), cpu_to_le16('e'),
9782cae269SKonstantin Komarov 	cpu_to_le16('d'), cpu_to_le16('D'), cpu_to_le16('a'), cpu_to_le16('t'),
9882cae269SKonstantin Komarov 	cpu_to_le16('a'),
9982cae269SKonstantin Komarov };
10082cae269SKonstantin Komarov #endif
10182cae269SKonstantin Komarov 
1021d07a9dfSDaniel Pinto static const __le16 CON_NAME[3] = {
1031d07a9dfSDaniel Pinto 	cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('N'),
1041d07a9dfSDaniel Pinto };
1051d07a9dfSDaniel Pinto 
1061d07a9dfSDaniel Pinto static const __le16 NUL_NAME[3] = {
1071d07a9dfSDaniel Pinto 	cpu_to_le16('N'), cpu_to_le16('U'), cpu_to_le16('L'),
1081d07a9dfSDaniel Pinto };
1091d07a9dfSDaniel Pinto 
1101d07a9dfSDaniel Pinto static const __le16 AUX_NAME[3] = {
1111d07a9dfSDaniel Pinto 	cpu_to_le16('A'), cpu_to_le16('U'), cpu_to_le16('X'),
1121d07a9dfSDaniel Pinto };
1131d07a9dfSDaniel Pinto 
1141d07a9dfSDaniel Pinto static const __le16 PRN_NAME[3] = {
1151d07a9dfSDaniel Pinto 	cpu_to_le16('P'), cpu_to_le16('R'), cpu_to_le16('N'),
1161d07a9dfSDaniel Pinto };
1171d07a9dfSDaniel Pinto 
1181d07a9dfSDaniel Pinto static const __le16 COM_NAME[3] = {
1191d07a9dfSDaniel Pinto 	cpu_to_le16('C'), cpu_to_le16('O'), cpu_to_le16('M'),
1201d07a9dfSDaniel Pinto };
1211d07a9dfSDaniel Pinto 
1221d07a9dfSDaniel Pinto static const __le16 LPT_NAME[3] = {
1231d07a9dfSDaniel Pinto 	cpu_to_le16('L'), cpu_to_le16('P'), cpu_to_le16('T'),
1241d07a9dfSDaniel Pinto };
1251d07a9dfSDaniel Pinto 
12682cae269SKonstantin Komarov // clang-format on
12782cae269SKonstantin Komarov 
12882cae269SKonstantin Komarov /*
129e8b8e97fSKari Argillander  * ntfs_fix_pre_write - Insert fixups into @rhdr before writing to disk.
13082cae269SKonstantin Komarov  */
ntfs_fix_pre_write(struct NTFS_RECORD_HEADER * rhdr,size_t bytes)13182cae269SKonstantin Komarov bool ntfs_fix_pre_write(struct NTFS_RECORD_HEADER *rhdr, size_t bytes)
13282cae269SKonstantin Komarov {
13382cae269SKonstantin Komarov 	u16 *fixup, *ptr;
13482cae269SKonstantin Komarov 	u16 sample;
13582cae269SKonstantin Komarov 	u16 fo = le16_to_cpu(rhdr->fix_off);
13682cae269SKonstantin Komarov 	u16 fn = le16_to_cpu(rhdr->fix_num);
13782cae269SKonstantin Komarov 
13882cae269SKonstantin Komarov 	if ((fo & 1) || fo + fn * sizeof(short) > SECTOR_SIZE || !fn-- ||
13982cae269SKonstantin Komarov 	    fn * SECTOR_SIZE > bytes) {
14082cae269SKonstantin Komarov 		return false;
14182cae269SKonstantin Komarov 	}
14282cae269SKonstantin Komarov 
143e8b8e97fSKari Argillander 	/* Get fixup pointer. */
14482cae269SKonstantin Komarov 	fixup = Add2Ptr(rhdr, fo);
14582cae269SKonstantin Komarov 
14682cae269SKonstantin Komarov 	if (*fixup >= 0x7FFF)
14782cae269SKonstantin Komarov 		*fixup = 1;
14882cae269SKonstantin Komarov 	else
14982cae269SKonstantin Komarov 		*fixup += 1;
15082cae269SKonstantin Komarov 
15182cae269SKonstantin Komarov 	sample = *fixup;
15282cae269SKonstantin Komarov 
15382cae269SKonstantin Komarov 	ptr = Add2Ptr(rhdr, SECTOR_SIZE - sizeof(short));
15482cae269SKonstantin Komarov 
15582cae269SKonstantin Komarov 	while (fn--) {
15682cae269SKonstantin Komarov 		*++fixup = *ptr;
15782cae269SKonstantin Komarov 		*ptr = sample;
15882cae269SKonstantin Komarov 		ptr += SECTOR_SIZE / sizeof(short);
15982cae269SKonstantin Komarov 	}
16082cae269SKonstantin Komarov 	return true;
16182cae269SKonstantin Komarov }
16282cae269SKonstantin Komarov 
16382cae269SKonstantin Komarov /*
164e8b8e97fSKari Argillander  * ntfs_fix_post_read - Remove fixups after reading from disk.
16582cae269SKonstantin Komarov  *
166e8b8e97fSKari Argillander  * Return: < 0 if error, 0 if ok, 1 if need to update fixups.
16782cae269SKonstantin Komarov  */
ntfs_fix_post_read(struct NTFS_RECORD_HEADER * rhdr,size_t bytes,bool simple)16882cae269SKonstantin Komarov int ntfs_fix_post_read(struct NTFS_RECORD_HEADER *rhdr, size_t bytes,
16982cae269SKonstantin Komarov 		       bool simple)
17082cae269SKonstantin Komarov {
17182cae269SKonstantin Komarov 	int ret;
17282cae269SKonstantin Komarov 	u16 *fixup, *ptr;
17382cae269SKonstantin Komarov 	u16 sample, fo, fn;
17482cae269SKonstantin Komarov 
17582cae269SKonstantin Komarov 	fo = le16_to_cpu(rhdr->fix_off);
17696de65a9SKonstantin Komarov 	fn = simple ? ((bytes >> SECTOR_SHIFT) + 1) :
17796de65a9SKonstantin Komarov 		      le16_to_cpu(rhdr->fix_num);
17882cae269SKonstantin Komarov 
179e8b8e97fSKari Argillander 	/* Check errors. */
18082cae269SKonstantin Komarov 	if ((fo & 1) || fo + fn * sizeof(short) > SECTOR_SIZE || !fn-- ||
18182cae269SKonstantin Komarov 	    fn * SECTOR_SIZE > bytes) {
182e0f363a9SKonstantin Komarov 		return -E_NTFS_CORRUPT;
18382cae269SKonstantin Komarov 	}
18482cae269SKonstantin Komarov 
185e8b8e97fSKari Argillander 	/* Get fixup pointer. */
18682cae269SKonstantin Komarov 	fixup = Add2Ptr(rhdr, fo);
18782cae269SKonstantin Komarov 	sample = *fixup;
18882cae269SKonstantin Komarov 	ptr = Add2Ptr(rhdr, SECTOR_SIZE - sizeof(short));
18982cae269SKonstantin Komarov 	ret = 0;
19082cae269SKonstantin Komarov 
19182cae269SKonstantin Komarov 	while (fn--) {
192e8b8e97fSKari Argillander 		/* Test current word. */
19382cae269SKonstantin Komarov 		if (*ptr != sample) {
19482cae269SKonstantin Komarov 			/* Fixup does not match! Is it serious error? */
19582cae269SKonstantin Komarov 			ret = -E_NTFS_FIXUP;
19682cae269SKonstantin Komarov 		}
19782cae269SKonstantin Komarov 
198e8b8e97fSKari Argillander 		/* Replace fixup. */
19982cae269SKonstantin Komarov 		*ptr = *++fixup;
20082cae269SKonstantin Komarov 		ptr += SECTOR_SIZE / sizeof(short);
20182cae269SKonstantin Komarov 	}
20282cae269SKonstantin Komarov 
20382cae269SKonstantin Komarov 	return ret;
20482cae269SKonstantin Komarov }
20582cae269SKonstantin Komarov 
20682cae269SKonstantin Komarov /*
207e8b8e97fSKari Argillander  * ntfs_extend_init - Load $Extend file.
20882cae269SKonstantin Komarov  */
ntfs_extend_init(struct ntfs_sb_info * sbi)20982cae269SKonstantin Komarov int ntfs_extend_init(struct ntfs_sb_info *sbi)
21082cae269SKonstantin Komarov {
21182cae269SKonstantin Komarov 	int err;
21282cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
21382cae269SKonstantin Komarov 	struct inode *inode, *inode2;
21482cae269SKonstantin Komarov 	struct MFT_REF ref;
21582cae269SKonstantin Komarov 
21682cae269SKonstantin Komarov 	if (sbi->volume.major_ver < 3) {
21782cae269SKonstantin Komarov 		ntfs_notice(sb, "Skip $Extend 'cause NTFS version");
21882cae269SKonstantin Komarov 		return 0;
21982cae269SKonstantin Komarov 	}
22082cae269SKonstantin Komarov 
22182cae269SKonstantin Komarov 	ref.low = cpu_to_le32(MFT_REC_EXTEND);
22282cae269SKonstantin Komarov 	ref.high = 0;
22382cae269SKonstantin Komarov 	ref.seq = cpu_to_le16(MFT_REC_EXTEND);
22482cae269SKonstantin Komarov 	inode = ntfs_iget5(sb, &ref, &NAME_EXTEND);
22582cae269SKonstantin Komarov 	if (IS_ERR(inode)) {
22682cae269SKonstantin Komarov 		err = PTR_ERR(inode);
227e43f6ec2SKonstantin Komarov 		ntfs_err(sb, "Failed to load $Extend (%d).", err);
22882cae269SKonstantin Komarov 		inode = NULL;
22982cae269SKonstantin Komarov 		goto out;
23082cae269SKonstantin Komarov 	}
23182cae269SKonstantin Komarov 
232e8b8e97fSKari Argillander 	/* If ntfs_iget5() reads from disk it never returns bad inode. */
23382cae269SKonstantin Komarov 	if (!S_ISDIR(inode->i_mode)) {
23482cae269SKonstantin Komarov 		err = -EINVAL;
23582cae269SKonstantin Komarov 		goto out;
23682cae269SKonstantin Komarov 	}
23782cae269SKonstantin Komarov 
23882cae269SKonstantin Komarov 	/* Try to find $ObjId */
23982cae269SKonstantin Komarov 	inode2 = dir_search_u(inode, &NAME_OBJID, NULL);
24082cae269SKonstantin Komarov 	if (inode2 && !IS_ERR(inode2)) {
24182cae269SKonstantin Komarov 		if (is_bad_inode(inode2)) {
24282cae269SKonstantin Komarov 			iput(inode2);
24382cae269SKonstantin Komarov 		} else {
24482cae269SKonstantin Komarov 			sbi->objid.ni = ntfs_i(inode2);
24582cae269SKonstantin Komarov 			sbi->objid_no = inode2->i_ino;
24682cae269SKonstantin Komarov 		}
24782cae269SKonstantin Komarov 	}
24882cae269SKonstantin Komarov 
24982cae269SKonstantin Komarov 	/* Try to find $Quota */
25082cae269SKonstantin Komarov 	inode2 = dir_search_u(inode, &NAME_QUOTA, NULL);
25182cae269SKonstantin Komarov 	if (inode2 && !IS_ERR(inode2)) {
25282cae269SKonstantin Komarov 		sbi->quota_no = inode2->i_ino;
25382cae269SKonstantin Komarov 		iput(inode2);
25482cae269SKonstantin Komarov 	}
25582cae269SKonstantin Komarov 
25682cae269SKonstantin Komarov 	/* Try to find $Reparse */
25782cae269SKonstantin Komarov 	inode2 = dir_search_u(inode, &NAME_REPARSE, NULL);
25882cae269SKonstantin Komarov 	if (inode2 && !IS_ERR(inode2)) {
25982cae269SKonstantin Komarov 		sbi->reparse.ni = ntfs_i(inode2);
26082cae269SKonstantin Komarov 		sbi->reparse_no = inode2->i_ino;
26182cae269SKonstantin Komarov 	}
26282cae269SKonstantin Komarov 
26382cae269SKonstantin Komarov 	/* Try to find $UsnJrnl */
26482cae269SKonstantin Komarov 	inode2 = dir_search_u(inode, &NAME_USNJRNL, NULL);
26582cae269SKonstantin Komarov 	if (inode2 && !IS_ERR(inode2)) {
26682cae269SKonstantin Komarov 		sbi->usn_jrnl_no = inode2->i_ino;
26782cae269SKonstantin Komarov 		iput(inode2);
26882cae269SKonstantin Komarov 	}
26982cae269SKonstantin Komarov 
27082cae269SKonstantin Komarov 	err = 0;
27182cae269SKonstantin Komarov out:
27282cae269SKonstantin Komarov 	iput(inode);
27382cae269SKonstantin Komarov 	return err;
27482cae269SKonstantin Komarov }
27582cae269SKonstantin Komarov 
ntfs_loadlog_and_replay(struct ntfs_inode * ni,struct ntfs_sb_info * sbi)27682cae269SKonstantin Komarov int ntfs_loadlog_and_replay(struct ntfs_inode *ni, struct ntfs_sb_info *sbi)
27782cae269SKonstantin Komarov {
27882cae269SKonstantin Komarov 	int err = 0;
27982cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
28082cae269SKonstantin Komarov 	bool initialized = false;
28182cae269SKonstantin Komarov 	struct MFT_REF ref;
28282cae269SKonstantin Komarov 	struct inode *inode;
28382cae269SKonstantin Komarov 
284e8b8e97fSKari Argillander 	/* Check for 4GB. */
28582cae269SKonstantin Komarov 	if (ni->vfs_inode.i_size >= 0x100000000ull) {
286e43f6ec2SKonstantin Komarov 		ntfs_err(sb, "\x24LogFile is large than 4G.");
28782cae269SKonstantin Komarov 		err = -EINVAL;
28882cae269SKonstantin Komarov 		goto out;
28982cae269SKonstantin Komarov 	}
29082cae269SKonstantin Komarov 
29182cae269SKonstantin Komarov 	sbi->flags |= NTFS_FLAGS_LOG_REPLAYING;
29282cae269SKonstantin Komarov 
29382cae269SKonstantin Komarov 	ref.low = cpu_to_le32(MFT_REC_MFT);
29482cae269SKonstantin Komarov 	ref.high = 0;
29582cae269SKonstantin Komarov 	ref.seq = cpu_to_le16(1);
29682cae269SKonstantin Komarov 
29782cae269SKonstantin Komarov 	inode = ntfs_iget5(sb, &ref, NULL);
29882cae269SKonstantin Komarov 
29982cae269SKonstantin Komarov 	if (IS_ERR(inode))
30082cae269SKonstantin Komarov 		inode = NULL;
30182cae269SKonstantin Komarov 
30282cae269SKonstantin Komarov 	if (!inode) {
303e8b8e97fSKari Argillander 		/* Try to use MFT copy. */
30482cae269SKonstantin Komarov 		u64 t64 = sbi->mft.lbo;
30582cae269SKonstantin Komarov 
30682cae269SKonstantin Komarov 		sbi->mft.lbo = sbi->mft.lbo2;
30782cae269SKonstantin Komarov 		inode = ntfs_iget5(sb, &ref, NULL);
30882cae269SKonstantin Komarov 		sbi->mft.lbo = t64;
30982cae269SKonstantin Komarov 		if (IS_ERR(inode))
31082cae269SKonstantin Komarov 			inode = NULL;
31182cae269SKonstantin Komarov 	}
31282cae269SKonstantin Komarov 
31382cae269SKonstantin Komarov 	if (!inode) {
31482cae269SKonstantin Komarov 		err = -EINVAL;
31582cae269SKonstantin Komarov 		ntfs_err(sb, "Failed to load $MFT.");
31682cae269SKonstantin Komarov 		goto out;
31782cae269SKonstantin Komarov 	}
31882cae269SKonstantin Komarov 
31982cae269SKonstantin Komarov 	sbi->mft.ni = ntfs_i(inode);
32082cae269SKonstantin Komarov 
321e8b8e97fSKari Argillander 	/* LogFile should not contains attribute list. */
32282cae269SKonstantin Komarov 	err = ni_load_all_mi(sbi->mft.ni);
32382cae269SKonstantin Komarov 	if (!err)
32482cae269SKonstantin Komarov 		err = log_replay(ni, &initialized);
32582cae269SKonstantin Komarov 
32682cae269SKonstantin Komarov 	iput(inode);
32782cae269SKonstantin Komarov 	sbi->mft.ni = NULL;
32882cae269SKonstantin Komarov 
32982cae269SKonstantin Komarov 	sync_blockdev(sb->s_bdev);
33082cae269SKonstantin Komarov 	invalidate_bdev(sb->s_bdev);
33182cae269SKonstantin Komarov 
33282cae269SKonstantin Komarov 	if (sbi->flags & NTFS_FLAGS_NEED_REPLAY) {
33382cae269SKonstantin Komarov 		err = 0;
33482cae269SKonstantin Komarov 		goto out;
33582cae269SKonstantin Komarov 	}
33682cae269SKonstantin Komarov 
33782cae269SKonstantin Komarov 	if (sb_rdonly(sb) || !initialized)
33882cae269SKonstantin Komarov 		goto out;
33982cae269SKonstantin Komarov 
340d3624466SKonstantin Komarov 	/* Fill LogFile by '-1' if it is initialized. */
34182cae269SKonstantin Komarov 	err = ntfs_bio_fill_1(sbi, &ni->file.run);
34282cae269SKonstantin Komarov 
34382cae269SKonstantin Komarov out:
34482cae269SKonstantin Komarov 	sbi->flags &= ~NTFS_FLAGS_LOG_REPLAYING;
34582cae269SKonstantin Komarov 
34682cae269SKonstantin Komarov 	return err;
34782cae269SKonstantin Komarov }
34882cae269SKonstantin Komarov 
34982cae269SKonstantin Komarov /*
350e8b8e97fSKari Argillander  * ntfs_look_for_free_space - Look for a free space in bitmap.
35182cae269SKonstantin Komarov  */
ntfs_look_for_free_space(struct ntfs_sb_info * sbi,CLST lcn,CLST len,CLST * new_lcn,CLST * new_len,enum ALLOCATE_OPT opt)35282cae269SKonstantin Komarov int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len,
35382cae269SKonstantin Komarov 			     CLST *new_lcn, CLST *new_len,
35482cae269SKonstantin Komarov 			     enum ALLOCATE_OPT opt)
35582cae269SKonstantin Komarov {
35682cae269SKonstantin Komarov 	int err;
357edb853ffSKari Argillander 	CLST alen;
35882cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
35978ab59feSKonstantin Komarov 	size_t alcn, zlen, zeroes, zlcn, zlen2, ztrim, new_zlen;
36082cae269SKonstantin Komarov 	struct wnd_bitmap *wnd = &sbi->used.bitmap;
36182cae269SKonstantin Komarov 
36282cae269SKonstantin Komarov 	down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
36382cae269SKonstantin Komarov 	if (opt & ALLOCATE_MFT) {
36482cae269SKonstantin Komarov 		zlen = wnd_zone_len(wnd);
36582cae269SKonstantin Komarov 
36682cae269SKonstantin Komarov 		if (!zlen) {
36782cae269SKonstantin Komarov 			err = ntfs_refresh_zone(sbi);
36882cae269SKonstantin Komarov 			if (err)
369edb853ffSKari Argillander 				goto up_write;
370edb853ffSKari Argillander 
37182cae269SKonstantin Komarov 			zlen = wnd_zone_len(wnd);
37278ab59feSKonstantin Komarov 		}
37382cae269SKonstantin Komarov 
37482cae269SKonstantin Komarov 		if (!zlen) {
37578ab59feSKonstantin Komarov 			ntfs_err(sbi->sb, "no free space to extend mft");
376edb853ffSKari Argillander 			err = -ENOSPC;
377edb853ffSKari Argillander 			goto up_write;
37882cae269SKonstantin Komarov 		}
37982cae269SKonstantin Komarov 
38082cae269SKonstantin Komarov 		lcn = wnd_zone_bit(wnd);
3816e3331eeSKari Argillander 		alen = min_t(CLST, len, zlen);
38282cae269SKonstantin Komarov 
38382cae269SKonstantin Komarov 		wnd_zone_set(wnd, lcn + alen, zlen - alen);
38482cae269SKonstantin Komarov 
38582cae269SKonstantin Komarov 		err = wnd_set_used(wnd, lcn, alen);
386edb853ffSKari Argillander 		if (err)
387edb853ffSKari Argillander 			goto up_write;
388edb853ffSKari Argillander 
38978ab59feSKonstantin Komarov 		alcn = lcn;
390edb853ffSKari Argillander 		goto space_found;
39178ab59feSKonstantin Komarov 	}
39282cae269SKonstantin Komarov 	/*
39382cae269SKonstantin Komarov 	 * 'Cause cluster 0 is always used this value means that we should use
394e8b8e97fSKari Argillander 	 * cached value of 'next_free_lcn' to improve performance.
39582cae269SKonstantin Komarov 	 */
39682cae269SKonstantin Komarov 	if (!lcn)
39782cae269SKonstantin Komarov 		lcn = sbi->used.next_free_lcn;
39882cae269SKonstantin Komarov 
39982cae269SKonstantin Komarov 	if (lcn >= wnd->nbits)
40082cae269SKonstantin Komarov 		lcn = 0;
40182cae269SKonstantin Komarov 
40278ab59feSKonstantin Komarov 	alen = wnd_find(wnd, len, lcn, BITMAP_FIND_MARK_AS_USED, &alcn);
40378ab59feSKonstantin Komarov 	if (alen)
404edb853ffSKari Argillander 		goto space_found;
40582cae269SKonstantin Komarov 
406e8b8e97fSKari Argillander 	/* Try to use clusters from MftZone. */
40782cae269SKonstantin Komarov 	zlen = wnd_zone_len(wnd);
40882cae269SKonstantin Komarov 	zeroes = wnd_zeroes(wnd);
40982cae269SKonstantin Komarov 
41078ab59feSKonstantin Komarov 	/* Check too big request */
411edb853ffSKari Argillander 	if (len > zeroes + zlen || zlen <= NTFS_MIN_MFT_ZONE) {
412edb853ffSKari Argillander 		err = -ENOSPC;
413edb853ffSKari Argillander 		goto up_write;
414edb853ffSKari Argillander 	}
41582cae269SKonstantin Komarov 
416e8b8e97fSKari Argillander 	/* How many clusters to cat from zone. */
41782cae269SKonstantin Komarov 	zlcn = wnd_zone_bit(wnd);
41882cae269SKonstantin Komarov 	zlen2 = zlen >> 1;
419b5322eb1SKari Argillander 	ztrim = clamp_val(len, zlen2, zlen);
420b5322eb1SKari Argillander 	new_zlen = max_t(size_t, zlen - ztrim, NTFS_MIN_MFT_ZONE);
42182cae269SKonstantin Komarov 
42282cae269SKonstantin Komarov 	wnd_zone_set(wnd, zlcn, new_zlen);
42382cae269SKonstantin Komarov 
424e8b8e97fSKari Argillander 	/* Allocate continues clusters. */
42578ab59feSKonstantin Komarov 	alen = wnd_find(wnd, len, 0,
42678ab59feSKonstantin Komarov 			BITMAP_FIND_MARK_AS_USED | BITMAP_FIND_FULL, &alcn);
427edb853ffSKari Argillander 	if (!alen) {
428edb853ffSKari Argillander 		err = -ENOSPC;
429edb853ffSKari Argillander 		goto up_write;
430edb853ffSKari Argillander 	}
43182cae269SKonstantin Komarov 
432edb853ffSKari Argillander space_found:
43378ab59feSKonstantin Komarov 	err = 0;
43478ab59feSKonstantin Komarov 	*new_len = alen;
43578ab59feSKonstantin Komarov 	*new_lcn = alcn;
43678ab59feSKonstantin Komarov 
43778ab59feSKonstantin Komarov 	ntfs_unmap_meta(sb, alcn, alen);
43878ab59feSKonstantin Komarov 
43978ab59feSKonstantin Komarov 	/* Set hint for next requests. */
44078ab59feSKonstantin Komarov 	if (!(opt & ALLOCATE_MFT))
44178ab59feSKonstantin Komarov 		sbi->used.next_free_lcn = alcn + alen;
442edb853ffSKari Argillander up_write:
44382cae269SKonstantin Komarov 	up_write(&wnd->rw_lock);
44482cae269SKonstantin Komarov 	return err;
44582cae269SKonstantin Komarov }
44682cae269SKonstantin Komarov 
44782cae269SKonstantin Komarov /*
448910013f7SKonstantin Komarov  * ntfs_check_for_free_space
449910013f7SKonstantin Komarov  *
450910013f7SKonstantin Komarov  * Check if it is possible to allocate 'clen' clusters and 'mlen' Mft records
451910013f7SKonstantin Komarov  */
ntfs_check_for_free_space(struct ntfs_sb_info * sbi,CLST clen,CLST mlen)452910013f7SKonstantin Komarov bool ntfs_check_for_free_space(struct ntfs_sb_info *sbi, CLST clen, CLST mlen)
453910013f7SKonstantin Komarov {
454910013f7SKonstantin Komarov 	size_t free, zlen, avail;
455910013f7SKonstantin Komarov 	struct wnd_bitmap *wnd;
456910013f7SKonstantin Komarov 
457910013f7SKonstantin Komarov 	wnd = &sbi->used.bitmap;
458910013f7SKonstantin Komarov 	down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
459910013f7SKonstantin Komarov 	free = wnd_zeroes(wnd);
4606f80ed14SKonstantin Komarov 	zlen = min_t(size_t, NTFS_MIN_MFT_ZONE, wnd_zone_len(wnd));
461910013f7SKonstantin Komarov 	up_read(&wnd->rw_lock);
462910013f7SKonstantin Komarov 
463910013f7SKonstantin Komarov 	if (free < zlen + clen)
464910013f7SKonstantin Komarov 		return false;
465910013f7SKonstantin Komarov 
466910013f7SKonstantin Komarov 	avail = free - (zlen + clen);
467910013f7SKonstantin Komarov 
468910013f7SKonstantin Komarov 	wnd = &sbi->mft.bitmap;
469910013f7SKonstantin Komarov 	down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_MFT);
470910013f7SKonstantin Komarov 	free = wnd_zeroes(wnd);
471910013f7SKonstantin Komarov 	zlen = wnd_zone_len(wnd);
472910013f7SKonstantin Komarov 	up_read(&wnd->rw_lock);
473910013f7SKonstantin Komarov 
474910013f7SKonstantin Komarov 	if (free >= zlen + mlen)
475910013f7SKonstantin Komarov 		return true;
476910013f7SKonstantin Komarov 
477910013f7SKonstantin Komarov 	return avail >= bytes_to_cluster(sbi, mlen << sbi->record_bits);
478910013f7SKonstantin Komarov }
479910013f7SKonstantin Komarov 
480910013f7SKonstantin Komarov /*
481e8b8e97fSKari Argillander  * ntfs_extend_mft - Allocate additional MFT records.
48282cae269SKonstantin Komarov  *
483e8b8e97fSKari Argillander  * sbi->mft.bitmap is locked for write.
48482cae269SKonstantin Komarov  *
48582cae269SKonstantin Komarov  * NOTE: recursive:
48682cae269SKonstantin Komarov  *	ntfs_look_free_mft ->
48782cae269SKonstantin Komarov  *	ntfs_extend_mft ->
48882cae269SKonstantin Komarov  *	attr_set_size ->
48982cae269SKonstantin Komarov  *	ni_insert_nonresident ->
49082cae269SKonstantin Komarov  *	ni_insert_attr ->
49182cae269SKonstantin Komarov  *	ni_ins_attr_ext ->
49282cae269SKonstantin Komarov  *	ntfs_look_free_mft ->
49382cae269SKonstantin Komarov  *	ntfs_extend_mft
494e8b8e97fSKari Argillander  *
495e8b8e97fSKari Argillander  * To avoid recursive always allocate space for two new MFT records
496e8b8e97fSKari Argillander  * see attrib.c: "at least two MFT to avoid recursive loop".
49782cae269SKonstantin Komarov  */
ntfs_extend_mft(struct ntfs_sb_info * sbi)49882cae269SKonstantin Komarov static int ntfs_extend_mft(struct ntfs_sb_info *sbi)
49982cae269SKonstantin Komarov {
50082cae269SKonstantin Komarov 	int err;
50182cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->mft.ni;
50282cae269SKonstantin Komarov 	size_t new_mft_total;
50382cae269SKonstantin Komarov 	u64 new_mft_bytes, new_bitmap_bytes;
50482cae269SKonstantin Komarov 	struct ATTRIB *attr;
50582cae269SKonstantin Komarov 	struct wnd_bitmap *wnd = &sbi->mft.bitmap;
50682cae269SKonstantin Komarov 
50797a6815eSKonstantin Komarov 	new_mft_total = ALIGN(wnd->nbits + NTFS_MFT_INCREASE_STEP, 128);
50882cae269SKonstantin Komarov 	new_mft_bytes = (u64)new_mft_total << sbi->record_bits;
50982cae269SKonstantin Komarov 
510e8b8e97fSKari Argillander 	/* Step 1: Resize $MFT::DATA. */
51182cae269SKonstantin Komarov 	down_write(&ni->file.run_lock);
51282cae269SKonstantin Komarov 	err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run,
51382cae269SKonstantin Komarov 			    new_mft_bytes, NULL, false, &attr);
51482cae269SKonstantin Komarov 
51582cae269SKonstantin Komarov 	if (err) {
51682cae269SKonstantin Komarov 		up_write(&ni->file.run_lock);
51782cae269SKonstantin Komarov 		goto out;
51882cae269SKonstantin Komarov 	}
51982cae269SKonstantin Komarov 
52082cae269SKonstantin Komarov 	attr->nres.valid_size = attr->nres.data_size;
52182cae269SKonstantin Komarov 	new_mft_total = le64_to_cpu(attr->nres.alloc_size) >> sbi->record_bits;
52282cae269SKonstantin Komarov 	ni->mi.dirty = true;
52382cae269SKonstantin Komarov 
524e8b8e97fSKari Argillander 	/* Step 2: Resize $MFT::BITMAP. */
525*3f5ef510SAlexander Lobakin 	new_bitmap_bytes = ntfs3_bitmap_size(new_mft_total);
52682cae269SKonstantin Komarov 
52782cae269SKonstantin Komarov 	err = attr_set_size(ni, ATTR_BITMAP, NULL, 0, &sbi->mft.bitmap.run,
52882cae269SKonstantin Komarov 			    new_bitmap_bytes, &new_bitmap_bytes, true, NULL);
52982cae269SKonstantin Komarov 
530e8b8e97fSKari Argillander 	/* Refresh MFT Zone if necessary. */
53182cae269SKonstantin Komarov 	down_write_nested(&sbi->used.bitmap.rw_lock, BITMAP_MUTEX_CLUSTERS);
53282cae269SKonstantin Komarov 
53382cae269SKonstantin Komarov 	ntfs_refresh_zone(sbi);
53482cae269SKonstantin Komarov 
53582cae269SKonstantin Komarov 	up_write(&sbi->used.bitmap.rw_lock);
53682cae269SKonstantin Komarov 	up_write(&ni->file.run_lock);
53782cae269SKonstantin Komarov 
53882cae269SKonstantin Komarov 	if (err)
53982cae269SKonstantin Komarov 		goto out;
54082cae269SKonstantin Komarov 
54182cae269SKonstantin Komarov 	err = wnd_extend(wnd, new_mft_total);
54282cae269SKonstantin Komarov 
54382cae269SKonstantin Komarov 	if (err)
54482cae269SKonstantin Komarov 		goto out;
54582cae269SKonstantin Komarov 
54682cae269SKonstantin Komarov 	ntfs_clear_mft_tail(sbi, sbi->mft.used, new_mft_total);
54782cae269SKonstantin Komarov 
54882cae269SKonstantin Komarov 	err = _ni_write_inode(&ni->vfs_inode, 0);
54982cae269SKonstantin Komarov out:
55082cae269SKonstantin Komarov 	return err;
55182cae269SKonstantin Komarov }
55282cae269SKonstantin Komarov 
55382cae269SKonstantin Komarov /*
554e8b8e97fSKari Argillander  * ntfs_look_free_mft - Look for a free MFT record.
55582cae269SKonstantin Komarov  */
ntfs_look_free_mft(struct ntfs_sb_info * sbi,CLST * rno,bool mft,struct ntfs_inode * ni,struct mft_inode ** mi)55682cae269SKonstantin Komarov int ntfs_look_free_mft(struct ntfs_sb_info *sbi, CLST *rno, bool mft,
55782cae269SKonstantin Komarov 		       struct ntfs_inode *ni, struct mft_inode **mi)
55882cae269SKonstantin Komarov {
55982cae269SKonstantin Komarov 	int err = 0;
56082cae269SKonstantin Komarov 	size_t zbit, zlen, from, to, fr;
56182cae269SKonstantin Komarov 	size_t mft_total;
56282cae269SKonstantin Komarov 	struct MFT_REF ref;
56382cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
56482cae269SKonstantin Komarov 	struct wnd_bitmap *wnd = &sbi->mft.bitmap;
56582cae269SKonstantin Komarov 	u32 ir;
56682cae269SKonstantin Komarov 
56782cae269SKonstantin Komarov 	static_assert(sizeof(sbi->mft.reserved_bitmap) * 8 >=
56882cae269SKonstantin Komarov 		      MFT_REC_FREE - MFT_REC_RESERVED);
56982cae269SKonstantin Komarov 
57082cae269SKonstantin Komarov 	if (!mft)
57182cae269SKonstantin Komarov 		down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_MFT);
57282cae269SKonstantin Komarov 
57382cae269SKonstantin Komarov 	zlen = wnd_zone_len(wnd);
57482cae269SKonstantin Komarov 
575e8b8e97fSKari Argillander 	/* Always reserve space for MFT. */
57682cae269SKonstantin Komarov 	if (zlen) {
57782cae269SKonstantin Komarov 		if (mft) {
57882cae269SKonstantin Komarov 			zbit = wnd_zone_bit(wnd);
57982cae269SKonstantin Komarov 			*rno = zbit;
58082cae269SKonstantin Komarov 			wnd_zone_set(wnd, zbit + 1, zlen - 1);
58182cae269SKonstantin Komarov 		}
58282cae269SKonstantin Komarov 		goto found;
58382cae269SKonstantin Komarov 	}
58482cae269SKonstantin Komarov 
585e8b8e97fSKari Argillander 	/* No MFT zone. Find the nearest to '0' free MFT. */
58682cae269SKonstantin Komarov 	if (!wnd_find(wnd, 1, MFT_REC_FREE, 0, &zbit)) {
58782cae269SKonstantin Komarov 		/* Resize MFT */
58882cae269SKonstantin Komarov 		mft_total = wnd->nbits;
58982cae269SKonstantin Komarov 
59082cae269SKonstantin Komarov 		err = ntfs_extend_mft(sbi);
59182cae269SKonstantin Komarov 		if (!err) {
59282cae269SKonstantin Komarov 			zbit = mft_total;
59382cae269SKonstantin Komarov 			goto reserve_mft;
59482cae269SKonstantin Komarov 		}
59582cae269SKonstantin Komarov 
59682cae269SKonstantin Komarov 		if (!mft || MFT_REC_FREE == sbi->mft.next_reserved)
59782cae269SKonstantin Komarov 			goto out;
59882cae269SKonstantin Komarov 
59982cae269SKonstantin Komarov 		err = 0;
60082cae269SKonstantin Komarov 
60182cae269SKonstantin Komarov 		/*
60282cae269SKonstantin Komarov 		 * Look for free record reserved area [11-16) ==
60382cae269SKonstantin Komarov 		 * [MFT_REC_RESERVED, MFT_REC_FREE ) MFT bitmap always
604e8b8e97fSKari Argillander 		 * marks it as used.
60582cae269SKonstantin Komarov 		 */
60682cae269SKonstantin Komarov 		if (!sbi->mft.reserved_bitmap) {
607e8b8e97fSKari Argillander 			/* Once per session create internal bitmap for 5 bits. */
60882cae269SKonstantin Komarov 			sbi->mft.reserved_bitmap = 0xFF;
60982cae269SKonstantin Komarov 
61082cae269SKonstantin Komarov 			ref.high = 0;
61182cae269SKonstantin Komarov 			for (ir = MFT_REC_RESERVED; ir < MFT_REC_FREE; ir++) {
61282cae269SKonstantin Komarov 				struct inode *i;
61382cae269SKonstantin Komarov 				struct ntfs_inode *ni;
61482cae269SKonstantin Komarov 				struct MFT_REC *mrec;
61582cae269SKonstantin Komarov 
61682cae269SKonstantin Komarov 				ref.low = cpu_to_le32(ir);
61782cae269SKonstantin Komarov 				ref.seq = cpu_to_le16(ir);
61882cae269SKonstantin Komarov 
61982cae269SKonstantin Komarov 				i = ntfs_iget5(sb, &ref, NULL);
62082cae269SKonstantin Komarov 				if (IS_ERR(i)) {
62182cae269SKonstantin Komarov next:
62282cae269SKonstantin Komarov 					ntfs_notice(
62382cae269SKonstantin Komarov 						sb,
62482cae269SKonstantin Komarov 						"Invalid reserved record %x",
62582cae269SKonstantin Komarov 						ref.low);
62682cae269SKonstantin Komarov 					continue;
62782cae269SKonstantin Komarov 				}
62882cae269SKonstantin Komarov 				if (is_bad_inode(i)) {
62982cae269SKonstantin Komarov 					iput(i);
63082cae269SKonstantin Komarov 					goto next;
63182cae269SKonstantin Komarov 				}
63282cae269SKonstantin Komarov 
63382cae269SKonstantin Komarov 				ni = ntfs_i(i);
63482cae269SKonstantin Komarov 
63582cae269SKonstantin Komarov 				mrec = ni->mi.mrec;
63682cae269SKonstantin Komarov 
63782cae269SKonstantin Komarov 				if (!is_rec_base(mrec))
63882cae269SKonstantin Komarov 					goto next;
63982cae269SKonstantin Komarov 
64082cae269SKonstantin Komarov 				if (mrec->hard_links)
64182cae269SKonstantin Komarov 					goto next;
64282cae269SKonstantin Komarov 
64382cae269SKonstantin Komarov 				if (!ni_std(ni))
64482cae269SKonstantin Komarov 					goto next;
64582cae269SKonstantin Komarov 
64682cae269SKonstantin Komarov 				if (ni_find_attr(ni, NULL, NULL, ATTR_NAME,
64782cae269SKonstantin Komarov 						 NULL, 0, NULL, NULL))
64882cae269SKonstantin Komarov 					goto next;
64982cae269SKonstantin Komarov 
650e483783cSKonstantin Komarov 				__clear_bit(ir - MFT_REC_RESERVED,
65182cae269SKonstantin Komarov 					    &sbi->mft.reserved_bitmap);
65282cae269SKonstantin Komarov 			}
65382cae269SKonstantin Komarov 		}
65482cae269SKonstantin Komarov 
65582cae269SKonstantin Komarov 		/* Scan 5 bits for zero. Bit 0 == MFT_REC_RESERVED */
656e483783cSKonstantin Komarov 		zbit = find_next_zero_bit(&sbi->mft.reserved_bitmap,
65782cae269SKonstantin Komarov 					  MFT_REC_FREE, MFT_REC_RESERVED);
65882cae269SKonstantin Komarov 		if (zbit >= MFT_REC_FREE) {
65982cae269SKonstantin Komarov 			sbi->mft.next_reserved = MFT_REC_FREE;
66082cae269SKonstantin Komarov 			goto out;
66182cae269SKonstantin Komarov 		}
66282cae269SKonstantin Komarov 
66382cae269SKonstantin Komarov 		zlen = 1;
66482cae269SKonstantin Komarov 		sbi->mft.next_reserved = zbit;
66582cae269SKonstantin Komarov 	} else {
66682cae269SKonstantin Komarov reserve_mft:
66782cae269SKonstantin Komarov 		zlen = zbit == MFT_REC_FREE ? (MFT_REC_USER - MFT_REC_FREE) : 4;
66882cae269SKonstantin Komarov 		if (zbit + zlen > wnd->nbits)
66982cae269SKonstantin Komarov 			zlen = wnd->nbits - zbit;
67082cae269SKonstantin Komarov 
67182cae269SKonstantin Komarov 		while (zlen > 1 && !wnd_is_free(wnd, zbit, zlen))
67282cae269SKonstantin Komarov 			zlen -= 1;
67382cae269SKonstantin Komarov 
674e8b8e97fSKari Argillander 		/* [zbit, zbit + zlen) will be used for MFT itself. */
67582cae269SKonstantin Komarov 		from = sbi->mft.used;
67682cae269SKonstantin Komarov 		if (from < zbit)
67782cae269SKonstantin Komarov 			from = zbit;
67882cae269SKonstantin Komarov 		to = zbit + zlen;
67982cae269SKonstantin Komarov 		if (from < to) {
68082cae269SKonstantin Komarov 			ntfs_clear_mft_tail(sbi, from, to);
68182cae269SKonstantin Komarov 			sbi->mft.used = to;
68282cae269SKonstantin Komarov 		}
68382cae269SKonstantin Komarov 	}
68482cae269SKonstantin Komarov 
68582cae269SKonstantin Komarov 	if (mft) {
68682cae269SKonstantin Komarov 		*rno = zbit;
68782cae269SKonstantin Komarov 		zbit += 1;
68882cae269SKonstantin Komarov 		zlen -= 1;
68982cae269SKonstantin Komarov 	}
69082cae269SKonstantin Komarov 
69182cae269SKonstantin Komarov 	wnd_zone_set(wnd, zbit, zlen);
69282cae269SKonstantin Komarov 
69382cae269SKonstantin Komarov found:
69482cae269SKonstantin Komarov 	if (!mft) {
695e8b8e97fSKari Argillander 		/* The request to get record for general purpose. */
69682cae269SKonstantin Komarov 		if (sbi->mft.next_free < MFT_REC_USER)
69782cae269SKonstantin Komarov 			sbi->mft.next_free = MFT_REC_USER;
69882cae269SKonstantin Komarov 
69982cae269SKonstantin Komarov 		for (;;) {
70082cae269SKonstantin Komarov 			if (sbi->mft.next_free >= sbi->mft.bitmap.nbits) {
70182cae269SKonstantin Komarov 			} else if (!wnd_find(wnd, 1, MFT_REC_USER, 0, &fr)) {
70282cae269SKonstantin Komarov 				sbi->mft.next_free = sbi->mft.bitmap.nbits;
70382cae269SKonstantin Komarov 			} else {
70482cae269SKonstantin Komarov 				*rno = fr;
70582cae269SKonstantin Komarov 				sbi->mft.next_free = *rno + 1;
70682cae269SKonstantin Komarov 				break;
70782cae269SKonstantin Komarov 			}
70882cae269SKonstantin Komarov 
70982cae269SKonstantin Komarov 			err = ntfs_extend_mft(sbi);
71082cae269SKonstantin Komarov 			if (err)
71182cae269SKonstantin Komarov 				goto out;
71282cae269SKonstantin Komarov 		}
71382cae269SKonstantin Komarov 	}
71482cae269SKonstantin Komarov 
71582cae269SKonstantin Komarov 	if (ni && !ni_add_subrecord(ni, *rno, mi)) {
71682cae269SKonstantin Komarov 		err = -ENOMEM;
71782cae269SKonstantin Komarov 		goto out;
71882cae269SKonstantin Komarov 	}
71982cae269SKonstantin Komarov 
720e8b8e97fSKari Argillander 	/* We have found a record that are not reserved for next MFT. */
72182cae269SKonstantin Komarov 	if (*rno >= MFT_REC_FREE)
72282cae269SKonstantin Komarov 		wnd_set_used(wnd, *rno, 1);
72382cae269SKonstantin Komarov 	else if (*rno >= MFT_REC_RESERVED && sbi->mft.reserved_bitmap_inited)
724e483783cSKonstantin Komarov 		__set_bit(*rno - MFT_REC_RESERVED, &sbi->mft.reserved_bitmap);
72582cae269SKonstantin Komarov 
72682cae269SKonstantin Komarov out:
72782cae269SKonstantin Komarov 	if (!mft)
72882cae269SKonstantin Komarov 		up_write(&wnd->rw_lock);
72982cae269SKonstantin Komarov 
73082cae269SKonstantin Komarov 	return err;
73182cae269SKonstantin Komarov }
73282cae269SKonstantin Komarov 
73382cae269SKonstantin Komarov /*
734e8b8e97fSKari Argillander  * ntfs_mark_rec_free - Mark record as free.
735071100eaSKonstantin Komarov  * is_mft - true if we are changing MFT
73682cae269SKonstantin Komarov  */
ntfs_mark_rec_free(struct ntfs_sb_info * sbi,CLST rno,bool is_mft)737071100eaSKonstantin Komarov void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno, bool is_mft)
73882cae269SKonstantin Komarov {
73982cae269SKonstantin Komarov 	struct wnd_bitmap *wnd = &sbi->mft.bitmap;
74082cae269SKonstantin Komarov 
741071100eaSKonstantin Komarov 	if (!is_mft)
74282cae269SKonstantin Komarov 		down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_MFT);
74382cae269SKonstantin Komarov 	if (rno >= wnd->nbits)
74482cae269SKonstantin Komarov 		goto out;
74582cae269SKonstantin Komarov 
74682cae269SKonstantin Komarov 	if (rno >= MFT_REC_FREE) {
74782cae269SKonstantin Komarov 		if (!wnd_is_used(wnd, rno, 1))
74882cae269SKonstantin Komarov 			ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
74982cae269SKonstantin Komarov 		else
75082cae269SKonstantin Komarov 			wnd_set_free(wnd, rno, 1);
75182cae269SKonstantin Komarov 	} else if (rno >= MFT_REC_RESERVED && sbi->mft.reserved_bitmap_inited) {
752e483783cSKonstantin Komarov 		__clear_bit(rno - MFT_REC_RESERVED, &sbi->mft.reserved_bitmap);
75382cae269SKonstantin Komarov 	}
75482cae269SKonstantin Komarov 
75582cae269SKonstantin Komarov 	if (rno < wnd_zone_bit(wnd))
75682cae269SKonstantin Komarov 		wnd_zone_set(wnd, rno, 1);
75782cae269SKonstantin Komarov 	else if (rno < sbi->mft.next_free && rno >= MFT_REC_USER)
75882cae269SKonstantin Komarov 		sbi->mft.next_free = rno;
75982cae269SKonstantin Komarov 
76082cae269SKonstantin Komarov out:
761071100eaSKonstantin Komarov 	if (!is_mft)
76282cae269SKonstantin Komarov 		up_write(&wnd->rw_lock);
76382cae269SKonstantin Komarov }
76482cae269SKonstantin Komarov 
76582cae269SKonstantin Komarov /*
766e8b8e97fSKari Argillander  * ntfs_clear_mft_tail - Format empty records [from, to).
76782cae269SKonstantin Komarov  *
768e8b8e97fSKari Argillander  * sbi->mft.bitmap is locked for write.
76982cae269SKonstantin Komarov  */
ntfs_clear_mft_tail(struct ntfs_sb_info * sbi,size_t from,size_t to)77082cae269SKonstantin Komarov int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to)
77182cae269SKonstantin Komarov {
77282cae269SKonstantin Komarov 	int err;
77382cae269SKonstantin Komarov 	u32 rs;
77482cae269SKonstantin Komarov 	u64 vbo;
77582cae269SKonstantin Komarov 	struct runs_tree *run;
77682cae269SKonstantin Komarov 	struct ntfs_inode *ni;
77782cae269SKonstantin Komarov 
77882cae269SKonstantin Komarov 	if (from >= to)
77982cae269SKonstantin Komarov 		return 0;
78082cae269SKonstantin Komarov 
78182cae269SKonstantin Komarov 	rs = sbi->record_size;
78282cae269SKonstantin Komarov 	ni = sbi->mft.ni;
78382cae269SKonstantin Komarov 	run = &ni->file.run;
78482cae269SKonstantin Komarov 
78582cae269SKonstantin Komarov 	down_read(&ni->file.run_lock);
78682cae269SKonstantin Komarov 	vbo = (u64)from * rs;
78782cae269SKonstantin Komarov 	for (; from < to; from++, vbo += rs) {
78882cae269SKonstantin Komarov 		struct ntfs_buffers nb;
78982cae269SKonstantin Komarov 
79082cae269SKonstantin Komarov 		err = ntfs_get_bh(sbi, run, vbo, rs, &nb);
79182cae269SKonstantin Komarov 		if (err)
79282cae269SKonstantin Komarov 			goto out;
79382cae269SKonstantin Komarov 
79482cae269SKonstantin Komarov 		err = ntfs_write_bh(sbi, &sbi->new_rec->rhdr, &nb, 0);
79582cae269SKonstantin Komarov 		nb_put(&nb);
79682cae269SKonstantin Komarov 		if (err)
79782cae269SKonstantin Komarov 			goto out;
79882cae269SKonstantin Komarov 	}
79982cae269SKonstantin Komarov 
80082cae269SKonstantin Komarov out:
80182cae269SKonstantin Komarov 	sbi->mft.used = from;
80282cae269SKonstantin Komarov 	up_read(&ni->file.run_lock);
80382cae269SKonstantin Komarov 	return err;
80482cae269SKonstantin Komarov }
80582cae269SKonstantin Komarov 
80682cae269SKonstantin Komarov /*
807e8b8e97fSKari Argillander  * ntfs_refresh_zone - Refresh MFT zone.
80882cae269SKonstantin Komarov  *
809e8b8e97fSKari Argillander  * sbi->used.bitmap is locked for rw.
810e8b8e97fSKari Argillander  * sbi->mft.bitmap is locked for write.
811e8b8e97fSKari Argillander  * sbi->mft.ni->file.run_lock for write.
81282cae269SKonstantin Komarov  */
ntfs_refresh_zone(struct ntfs_sb_info * sbi)81382cae269SKonstantin Komarov int ntfs_refresh_zone(struct ntfs_sb_info *sbi)
81482cae269SKonstantin Komarov {
8158335ebe1SKonstantin Komarov 	CLST lcn, vcn, len;
81682cae269SKonstantin Komarov 	size_t lcn_s, zlen;
81782cae269SKonstantin Komarov 	struct wnd_bitmap *wnd = &sbi->used.bitmap;
81882cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->mft.ni;
81982cae269SKonstantin Komarov 
820e8b8e97fSKari Argillander 	/* Do not change anything unless we have non empty MFT zone. */
82182cae269SKonstantin Komarov 	if (wnd_zone_len(wnd))
82282cae269SKonstantin Komarov 		return 0;
82382cae269SKonstantin Komarov 
82482cae269SKonstantin Komarov 	vcn = bytes_to_cluster(sbi,
82582cae269SKonstantin Komarov 			       (u64)sbi->mft.bitmap.nbits << sbi->record_bits);
82682cae269SKonstantin Komarov 
82782cae269SKonstantin Komarov 	if (!run_lookup_entry(&ni->file.run, vcn - 1, &lcn, &len, NULL))
82882cae269SKonstantin Komarov 		lcn = SPARSE_LCN;
82982cae269SKonstantin Komarov 
830e8b8e97fSKari Argillander 	/* We should always find Last Lcn for MFT. */
83182cae269SKonstantin Komarov 	if (lcn == SPARSE_LCN)
83282cae269SKonstantin Komarov 		return -EINVAL;
83382cae269SKonstantin Komarov 
83482cae269SKonstantin Komarov 	lcn_s = lcn + 1;
83582cae269SKonstantin Komarov 
836e8b8e97fSKari Argillander 	/* Try to allocate clusters after last MFT run. */
8378335ebe1SKonstantin Komarov 	zlen = wnd_find(wnd, sbi->zone_max, lcn_s, 0, &lcn_s);
83882cae269SKonstantin Komarov 	wnd_zone_set(wnd, lcn_s, zlen);
83982cae269SKonstantin Komarov 
84082cae269SKonstantin Komarov 	return 0;
84182cae269SKonstantin Komarov }
84282cae269SKonstantin Komarov 
84382cae269SKonstantin Komarov /*
844e8b8e97fSKari Argillander  * ntfs_update_mftmirr - Update $MFTMirr data.
84582cae269SKonstantin Komarov  */
ntfs_update_mftmirr(struct ntfs_sb_info * sbi,int wait)846e66af07cSPavel Skripkin void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait)
84782cae269SKonstantin Komarov {
84882cae269SKonstantin Komarov 	int err;
84982cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
850e483783cSKonstantin Komarov 	u32 blocksize, bytes;
85182cae269SKonstantin Komarov 	sector_t block1, block2;
85282cae269SKonstantin Komarov 
85396de65a9SKonstantin Komarov 	/*
85496de65a9SKonstantin Komarov 	 * sb can be NULL here. In this case sbi->flags should be 0 too.
85596de65a9SKonstantin Komarov 	 */
85697ec56d3SKonstantin Komarov 	if (!sb || !(sbi->flags & NTFS_FLAGS_MFTMIRR) ||
85797ec56d3SKonstantin Komarov 	    unlikely(ntfs3_forced_shutdown(sb)))
858e66af07cSPavel Skripkin 		return;
859321460caSPavel Skripkin 
860321460caSPavel Skripkin 	blocksize = sb->s_blocksize;
86182cae269SKonstantin Komarov 	bytes = sbi->mft.recs_mirr << sbi->record_bits;
86282cae269SKonstantin Komarov 	block1 = sbi->mft.lbo >> sb->s_blocksize_bits;
86382cae269SKonstantin Komarov 	block2 = sbi->mft.lbo2 >> sb->s_blocksize_bits;
86482cae269SKonstantin Komarov 
86582cae269SKonstantin Komarov 	for (; bytes >= blocksize; bytes -= blocksize) {
86682cae269SKonstantin Komarov 		struct buffer_head *bh1, *bh2;
86782cae269SKonstantin Komarov 
86882cae269SKonstantin Komarov 		bh1 = sb_bread(sb, block1++);
869e66af07cSPavel Skripkin 		if (!bh1)
870e66af07cSPavel Skripkin 			return;
87182cae269SKonstantin Komarov 
87282cae269SKonstantin Komarov 		bh2 = sb_getblk(sb, block2++);
87382cae269SKonstantin Komarov 		if (!bh2) {
87482cae269SKonstantin Komarov 			put_bh(bh1);
875e66af07cSPavel Skripkin 			return;
87682cae269SKonstantin Komarov 		}
87782cae269SKonstantin Komarov 
87882cae269SKonstantin Komarov 		if (buffer_locked(bh2))
87982cae269SKonstantin Komarov 			__wait_on_buffer(bh2);
88082cae269SKonstantin Komarov 
88182cae269SKonstantin Komarov 		lock_buffer(bh2);
88282cae269SKonstantin Komarov 		memcpy(bh2->b_data, bh1->b_data, blocksize);
88382cae269SKonstantin Komarov 		set_buffer_uptodate(bh2);
88482cae269SKonstantin Komarov 		mark_buffer_dirty(bh2);
88582cae269SKonstantin Komarov 		unlock_buffer(bh2);
88682cae269SKonstantin Komarov 
88782cae269SKonstantin Komarov 		put_bh(bh1);
88882cae269SKonstantin Komarov 		bh1 = NULL;
88982cae269SKonstantin Komarov 
890ba118928SKonstantin Komarov 		err = wait ? sync_dirty_buffer(bh2) : 0;
89182cae269SKonstantin Komarov 
89282cae269SKonstantin Komarov 		put_bh(bh2);
89382cae269SKonstantin Komarov 		if (err)
894e66af07cSPavel Skripkin 			return;
89582cae269SKonstantin Komarov 	}
89682cae269SKonstantin Komarov 
89782cae269SKonstantin Komarov 	sbi->flags &= ~NTFS_FLAGS_MFTMIRR;
89882cae269SKonstantin Komarov }
89982cae269SKonstantin Komarov 
90082cae269SKonstantin Komarov /*
901c12df45eSKonstantin Komarov  * ntfs_bad_inode
902c12df45eSKonstantin Komarov  *
903c12df45eSKonstantin Komarov  * Marks inode as bad and marks fs as 'dirty'
904c12df45eSKonstantin Komarov  */
ntfs_bad_inode(struct inode * inode,const char * hint)905c12df45eSKonstantin Komarov void ntfs_bad_inode(struct inode *inode, const char *hint)
906c12df45eSKonstantin Komarov {
907c12df45eSKonstantin Komarov 	struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
908c12df45eSKonstantin Komarov 
909c12df45eSKonstantin Komarov 	ntfs_inode_err(inode, "%s", hint);
910c12df45eSKonstantin Komarov 	make_bad_inode(inode);
911c12df45eSKonstantin Komarov 	ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
91282cae269SKonstantin Komarov }
91382cae269SKonstantin Komarov 
91482cae269SKonstantin Komarov /*
91582cae269SKonstantin Komarov  * ntfs_set_state
91682cae269SKonstantin Komarov  *
917e8b8e97fSKari Argillander  * Mount: ntfs_set_state(NTFS_DIRTY_DIRTY)
918e8b8e97fSKari Argillander  * Umount: ntfs_set_state(NTFS_DIRTY_CLEAR)
919e8b8e97fSKari Argillander  * NTFS error: ntfs_set_state(NTFS_DIRTY_ERROR)
92082cae269SKonstantin Komarov  */
ntfs_set_state(struct ntfs_sb_info * sbi,enum NTFS_DIRTY_FLAGS dirty)92182cae269SKonstantin Komarov int ntfs_set_state(struct ntfs_sb_info *sbi, enum NTFS_DIRTY_FLAGS dirty)
92282cae269SKonstantin Komarov {
92382cae269SKonstantin Komarov 	int err;
92482cae269SKonstantin Komarov 	struct ATTRIB *attr;
92582cae269SKonstantin Komarov 	struct VOLUME_INFO *info;
92682cae269SKonstantin Komarov 	struct mft_inode *mi;
92782cae269SKonstantin Komarov 	struct ntfs_inode *ni;
92862560248SKonstantin Komarov 	__le16 info_flags;
92982cae269SKonstantin Komarov 
93082cae269SKonstantin Komarov 	/*
931e8b8e97fSKari Argillander 	 * Do not change state if fs was real_dirty.
932e8b8e97fSKari Argillander 	 * Do not change state if fs already dirty(clear).
933e8b8e97fSKari Argillander 	 * Do not change any thing if mounted read only.
93482cae269SKonstantin Komarov 	 */
93582cae269SKonstantin Komarov 	if (sbi->volume.real_dirty || sb_rdonly(sbi->sb))
93682cae269SKonstantin Komarov 		return 0;
93782cae269SKonstantin Komarov 
938e8b8e97fSKari Argillander 	/* Check cached value. */
93982cae269SKonstantin Komarov 	if ((dirty == NTFS_DIRTY_CLEAR ? 0 : VOLUME_FLAG_DIRTY) ==
94082cae269SKonstantin Komarov 	    (sbi->volume.flags & VOLUME_FLAG_DIRTY))
94182cae269SKonstantin Komarov 		return 0;
94282cae269SKonstantin Komarov 
94382cae269SKonstantin Komarov 	ni = sbi->volume.ni;
94482cae269SKonstantin Komarov 	if (!ni)
94582cae269SKonstantin Komarov 		return -EINVAL;
94682cae269SKonstantin Komarov 
94782cae269SKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_DIRTY);
94882cae269SKonstantin Komarov 
94982cae269SKonstantin Komarov 	attr = ni_find_attr(ni, NULL, NULL, ATTR_VOL_INFO, NULL, 0, NULL, &mi);
95082cae269SKonstantin Komarov 	if (!attr) {
95182cae269SKonstantin Komarov 		err = -EINVAL;
95282cae269SKonstantin Komarov 		goto out;
95382cae269SKonstantin Komarov 	}
95482cae269SKonstantin Komarov 
95582cae269SKonstantin Komarov 	info = resident_data_ex(attr, SIZEOF_ATTRIBUTE_VOLUME_INFO);
95682cae269SKonstantin Komarov 	if (!info) {
95782cae269SKonstantin Komarov 		err = -EINVAL;
95882cae269SKonstantin Komarov 		goto out;
95982cae269SKonstantin Komarov 	}
96082cae269SKonstantin Komarov 
96162560248SKonstantin Komarov 	info_flags = info->flags;
96262560248SKonstantin Komarov 
96382cae269SKonstantin Komarov 	switch (dirty) {
96482cae269SKonstantin Komarov 	case NTFS_DIRTY_ERROR:
96582cae269SKonstantin Komarov 		ntfs_notice(sbi->sb, "Mark volume as dirty due to NTFS errors");
96682cae269SKonstantin Komarov 		sbi->volume.real_dirty = true;
96782cae269SKonstantin Komarov 		fallthrough;
96882cae269SKonstantin Komarov 	case NTFS_DIRTY_DIRTY:
96982cae269SKonstantin Komarov 		info->flags |= VOLUME_FLAG_DIRTY;
97082cae269SKonstantin Komarov 		break;
97182cae269SKonstantin Komarov 	case NTFS_DIRTY_CLEAR:
97282cae269SKonstantin Komarov 		info->flags &= ~VOLUME_FLAG_DIRTY;
97382cae269SKonstantin Komarov 		break;
97482cae269SKonstantin Komarov 	}
975e8b8e97fSKari Argillander 	/* Cache current volume flags. */
97662560248SKonstantin Komarov 	if (info_flags != info->flags) {
97782cae269SKonstantin Komarov 		sbi->volume.flags = info->flags;
97882cae269SKonstantin Komarov 		mi->dirty = true;
97962560248SKonstantin Komarov 	}
98082cae269SKonstantin Komarov 	err = 0;
98182cae269SKonstantin Komarov 
98282cae269SKonstantin Komarov out:
98382cae269SKonstantin Komarov 	ni_unlock(ni);
98482cae269SKonstantin Komarov 	if (err)
98582cae269SKonstantin Komarov 		return err;
98682cae269SKonstantin Komarov 
98706ccfb00SKonstantin Komarov 	mark_inode_dirty_sync(&ni->vfs_inode);
98882cae269SKonstantin Komarov 	/* verify(!ntfs_update_mftmirr()); */
98982cae269SKonstantin Komarov 
99006ccfb00SKonstantin Komarov 	/* write mft record on disk. */
99106ccfb00SKonstantin Komarov 	err = _ni_write_inode(&ni->vfs_inode, 1);
99282cae269SKonstantin Komarov 
99382cae269SKonstantin Komarov 	return err;
99482cae269SKonstantin Komarov }
99582cae269SKonstantin Komarov 
99682cae269SKonstantin Komarov /*
997e8b8e97fSKari Argillander  * security_hash - Calculates a hash of security descriptor.
99882cae269SKonstantin Komarov  */
security_hash(const void * sd,size_t bytes)99982cae269SKonstantin Komarov static inline __le32 security_hash(const void *sd, size_t bytes)
100082cae269SKonstantin Komarov {
100182cae269SKonstantin Komarov 	u32 hash = 0;
100282cae269SKonstantin Komarov 	const __le32 *ptr = sd;
100382cae269SKonstantin Komarov 
100482cae269SKonstantin Komarov 	bytes >>= 2;
100582cae269SKonstantin Komarov 	while (bytes--)
100682cae269SKonstantin Komarov 		hash = ((hash >> 0x1D) | (hash << 3)) + le32_to_cpu(*ptr++);
100782cae269SKonstantin Komarov 	return cpu_to_le32(hash);
100882cae269SKonstantin Komarov }
100982cae269SKonstantin Komarov 
10105ca87d01SKonstantin Komarov /*
10115ca87d01SKonstantin Komarov  * simple wrapper for sb_bread_unmovable.
10125ca87d01SKonstantin Komarov  */
ntfs_bread(struct super_block * sb,sector_t block)10135ca87d01SKonstantin Komarov struct buffer_head *ntfs_bread(struct super_block *sb, sector_t block)
10145ca87d01SKonstantin Komarov {
10155ca87d01SKonstantin Komarov 	struct ntfs_sb_info *sbi = sb->s_fs_info;
10165ca87d01SKonstantin Komarov 	struct buffer_head *bh;
10175ca87d01SKonstantin Komarov 
10185ca87d01SKonstantin Komarov 	if (unlikely(block >= sbi->volume.blocks)) {
10195ca87d01SKonstantin Komarov 		/* prevent generic message "attempt to access beyond end of device" */
10205ca87d01SKonstantin Komarov 		ntfs_err(sb, "try to read out of volume at offset 0x%llx",
10215ca87d01SKonstantin Komarov 			 (u64)block << sb->s_blocksize_bits);
10225ca87d01SKonstantin Komarov 		return NULL;
10235ca87d01SKonstantin Komarov 	}
10245ca87d01SKonstantin Komarov 
10255ca87d01SKonstantin Komarov 	bh = sb_bread_unmovable(sb, block);
10265ca87d01SKonstantin Komarov 	if (bh)
10275ca87d01SKonstantin Komarov 		return bh;
10285ca87d01SKonstantin Komarov 
10295ca87d01SKonstantin Komarov 	ntfs_err(sb, "failed to read volume at offset 0x%llx",
10305ca87d01SKonstantin Komarov 		 (u64)block << sb->s_blocksize_bits);
10315ca87d01SKonstantin Komarov 	return NULL;
10325ca87d01SKonstantin Komarov }
10335ca87d01SKonstantin Komarov 
ntfs_sb_read(struct super_block * sb,u64 lbo,size_t bytes,void * buffer)103482cae269SKonstantin Komarov int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer)
103582cae269SKonstantin Komarov {
103682cae269SKonstantin Komarov 	struct block_device *bdev = sb->s_bdev;
103782cae269SKonstantin Komarov 	u32 blocksize = sb->s_blocksize;
103882cae269SKonstantin Komarov 	u64 block = lbo >> sb->s_blocksize_bits;
103982cae269SKonstantin Komarov 	u32 off = lbo & (blocksize - 1);
104082cae269SKonstantin Komarov 	u32 op = blocksize - off;
104182cae269SKonstantin Komarov 
104282cae269SKonstantin Komarov 	for (; bytes; block += 1, off = 0, op = blocksize) {
104382cae269SKonstantin Komarov 		struct buffer_head *bh = __bread(bdev, block, blocksize);
104482cae269SKonstantin Komarov 
104582cae269SKonstantin Komarov 		if (!bh)
104682cae269SKonstantin Komarov 			return -EIO;
104782cae269SKonstantin Komarov 
104882cae269SKonstantin Komarov 		if (op > bytes)
104982cae269SKonstantin Komarov 			op = bytes;
105082cae269SKonstantin Komarov 
105182cae269SKonstantin Komarov 		memcpy(buffer, bh->b_data + off, op);
105282cae269SKonstantin Komarov 
105382cae269SKonstantin Komarov 		put_bh(bh);
105482cae269SKonstantin Komarov 
105582cae269SKonstantin Komarov 		bytes -= op;
105682cae269SKonstantin Komarov 		buffer = Add2Ptr(buffer, op);
105782cae269SKonstantin Komarov 	}
105882cae269SKonstantin Komarov 
105982cae269SKonstantin Komarov 	return 0;
106082cae269SKonstantin Komarov }
106182cae269SKonstantin Komarov 
ntfs_sb_write(struct super_block * sb,u64 lbo,size_t bytes,const void * buf,int wait)106282cae269SKonstantin Komarov int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes,
106382cae269SKonstantin Komarov 		  const void *buf, int wait)
106482cae269SKonstantin Komarov {
106582cae269SKonstantin Komarov 	u32 blocksize = sb->s_blocksize;
106682cae269SKonstantin Komarov 	struct block_device *bdev = sb->s_bdev;
106782cae269SKonstantin Komarov 	sector_t block = lbo >> sb->s_blocksize_bits;
106882cae269SKonstantin Komarov 	u32 off = lbo & (blocksize - 1);
106982cae269SKonstantin Komarov 	u32 op = blocksize - off;
107082cae269SKonstantin Komarov 	struct buffer_head *bh;
107182cae269SKonstantin Komarov 
107282cae269SKonstantin Komarov 	if (!wait && (sb->s_flags & SB_SYNCHRONOUS))
107382cae269SKonstantin Komarov 		wait = 1;
107482cae269SKonstantin Komarov 
107582cae269SKonstantin Komarov 	for (; bytes; block += 1, off = 0, op = blocksize) {
107682cae269SKonstantin Komarov 		if (op > bytes)
107782cae269SKonstantin Komarov 			op = bytes;
107882cae269SKonstantin Komarov 
107982cae269SKonstantin Komarov 		if (op < blocksize) {
108082cae269SKonstantin Komarov 			bh = __bread(bdev, block, blocksize);
108182cae269SKonstantin Komarov 			if (!bh) {
108282cae269SKonstantin Komarov 				ntfs_err(sb, "failed to read block %llx",
108382cae269SKonstantin Komarov 					 (u64)block);
108482cae269SKonstantin Komarov 				return -EIO;
108582cae269SKonstantin Komarov 			}
108682cae269SKonstantin Komarov 		} else {
108782cae269SKonstantin Komarov 			bh = __getblk(bdev, block, blocksize);
108882cae269SKonstantin Komarov 			if (!bh)
108982cae269SKonstantin Komarov 				return -ENOMEM;
109082cae269SKonstantin Komarov 		}
109182cae269SKonstantin Komarov 
109282cae269SKonstantin Komarov 		if (buffer_locked(bh))
109382cae269SKonstantin Komarov 			__wait_on_buffer(bh);
109482cae269SKonstantin Komarov 
109582cae269SKonstantin Komarov 		lock_buffer(bh);
109682cae269SKonstantin Komarov 		if (buf) {
109782cae269SKonstantin Komarov 			memcpy(bh->b_data + off, buf, op);
109882cae269SKonstantin Komarov 			buf = Add2Ptr(buf, op);
109982cae269SKonstantin Komarov 		} else {
110082cae269SKonstantin Komarov 			memset(bh->b_data + off, -1, op);
110182cae269SKonstantin Komarov 		}
110282cae269SKonstantin Komarov 
110382cae269SKonstantin Komarov 		set_buffer_uptodate(bh);
110482cae269SKonstantin Komarov 		mark_buffer_dirty(bh);
110582cae269SKonstantin Komarov 		unlock_buffer(bh);
110682cae269SKonstantin Komarov 
110782cae269SKonstantin Komarov 		if (wait) {
110882cae269SKonstantin Komarov 			int err = sync_dirty_buffer(bh);
110982cae269SKonstantin Komarov 
111082cae269SKonstantin Komarov 			if (err) {
111182cae269SKonstantin Komarov 				ntfs_err(
111282cae269SKonstantin Komarov 					sb,
111382cae269SKonstantin Komarov 					"failed to sync buffer at block %llx, error %d",
111482cae269SKonstantin Komarov 					(u64)block, err);
111582cae269SKonstantin Komarov 				put_bh(bh);
111682cae269SKonstantin Komarov 				return err;
111782cae269SKonstantin Komarov 			}
111882cae269SKonstantin Komarov 		}
111982cae269SKonstantin Komarov 
112082cae269SKonstantin Komarov 		put_bh(bh);
112182cae269SKonstantin Komarov 
112282cae269SKonstantin Komarov 		bytes -= op;
112382cae269SKonstantin Komarov 	}
112482cae269SKonstantin Komarov 	return 0;
112582cae269SKonstantin Komarov }
112682cae269SKonstantin Komarov 
ntfs_sb_write_run(struct ntfs_sb_info * sbi,const struct runs_tree * run,u64 vbo,const void * buf,size_t bytes,int sync)112782cae269SKonstantin Komarov int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run,
112863544672SKonstantin Komarov 		      u64 vbo, const void *buf, size_t bytes, int sync)
112982cae269SKonstantin Komarov {
113082cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
113182cae269SKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
113282cae269SKonstantin Komarov 	u32 off = vbo & sbi->cluster_mask;
113382cae269SKonstantin Komarov 	CLST lcn, clen, vcn = vbo >> cluster_bits, vcn_next;
113482cae269SKonstantin Komarov 	u64 lbo, len;
113582cae269SKonstantin Komarov 	size_t idx;
113682cae269SKonstantin Komarov 
113782cae269SKonstantin Komarov 	if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx))
113882cae269SKonstantin Komarov 		return -ENOENT;
113982cae269SKonstantin Komarov 
114082cae269SKonstantin Komarov 	if (lcn == SPARSE_LCN)
114182cae269SKonstantin Komarov 		return -EINVAL;
114282cae269SKonstantin Komarov 
114382cae269SKonstantin Komarov 	lbo = ((u64)lcn << cluster_bits) + off;
114482cae269SKonstantin Komarov 	len = ((u64)clen << cluster_bits) - off;
114582cae269SKonstantin Komarov 
114682cae269SKonstantin Komarov 	for (;;) {
11476e3331eeSKari Argillander 		u32 op = min_t(u64, len, bytes);
114863544672SKonstantin Komarov 		int err = ntfs_sb_write(sb, lbo, op, buf, sync);
114982cae269SKonstantin Komarov 
115082cae269SKonstantin Komarov 		if (err)
115182cae269SKonstantin Komarov 			return err;
115282cae269SKonstantin Komarov 
115382cae269SKonstantin Komarov 		bytes -= op;
115482cae269SKonstantin Komarov 		if (!bytes)
115582cae269SKonstantin Komarov 			break;
115682cae269SKonstantin Komarov 
115782cae269SKonstantin Komarov 		vcn_next = vcn + clen;
115882cae269SKonstantin Komarov 		if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
115982cae269SKonstantin Komarov 		    vcn != vcn_next)
116082cae269SKonstantin Komarov 			return -ENOENT;
116182cae269SKonstantin Komarov 
116282cae269SKonstantin Komarov 		if (lcn == SPARSE_LCN)
116382cae269SKonstantin Komarov 			return -EINVAL;
116482cae269SKonstantin Komarov 
116582cae269SKonstantin Komarov 		if (buf)
116682cae269SKonstantin Komarov 			buf = Add2Ptr(buf, op);
116782cae269SKonstantin Komarov 
116882cae269SKonstantin Komarov 		lbo = ((u64)lcn << cluster_bits);
116982cae269SKonstantin Komarov 		len = ((u64)clen << cluster_bits);
117082cae269SKonstantin Komarov 	}
117182cae269SKonstantin Komarov 
117282cae269SKonstantin Komarov 	return 0;
117382cae269SKonstantin Komarov }
117482cae269SKonstantin Komarov 
ntfs_bread_run(struct ntfs_sb_info * sbi,const struct runs_tree * run,u64 vbo)117582cae269SKonstantin Komarov struct buffer_head *ntfs_bread_run(struct ntfs_sb_info *sbi,
117682cae269SKonstantin Komarov 				   const struct runs_tree *run, u64 vbo)
117782cae269SKonstantin Komarov {
117882cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
117982cae269SKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
118082cae269SKonstantin Komarov 	CLST lcn;
118182cae269SKonstantin Komarov 	u64 lbo;
118282cae269SKonstantin Komarov 
118382cae269SKonstantin Komarov 	if (!run_lookup_entry(run, vbo >> cluster_bits, &lcn, NULL, NULL))
118482cae269SKonstantin Komarov 		return ERR_PTR(-ENOENT);
118582cae269SKonstantin Komarov 
118682cae269SKonstantin Komarov 	lbo = ((u64)lcn << cluster_bits) + (vbo & sbi->cluster_mask);
118782cae269SKonstantin Komarov 
118882cae269SKonstantin Komarov 	return ntfs_bread(sb, lbo >> sb->s_blocksize_bits);
118982cae269SKonstantin Komarov }
119082cae269SKonstantin Komarov 
ntfs_read_run_nb(struct ntfs_sb_info * sbi,const struct runs_tree * run,u64 vbo,void * buf,u32 bytes,struct ntfs_buffers * nb)119182cae269SKonstantin Komarov int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run,
119282cae269SKonstantin Komarov 		     u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb)
119382cae269SKonstantin Komarov {
119482cae269SKonstantin Komarov 	int err;
119582cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
119682cae269SKonstantin Komarov 	u32 blocksize = sb->s_blocksize;
119782cae269SKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
119882cae269SKonstantin Komarov 	u32 off = vbo & sbi->cluster_mask;
119982cae269SKonstantin Komarov 	u32 nbh = 0;
120082cae269SKonstantin Komarov 	CLST vcn_next, vcn = vbo >> cluster_bits;
120182cae269SKonstantin Komarov 	CLST lcn, clen;
120282cae269SKonstantin Komarov 	u64 lbo, len;
120382cae269SKonstantin Komarov 	size_t idx;
120482cae269SKonstantin Komarov 	struct buffer_head *bh;
120582cae269SKonstantin Komarov 
120682cae269SKonstantin Komarov 	if (!run) {
1207e8b8e97fSKari Argillander 		/* First reading of $Volume + $MFTMirr + $LogFile goes here. */
120882cae269SKonstantin Komarov 		if (vbo > MFT_REC_VOL * sbi->record_size) {
120982cae269SKonstantin Komarov 			err = -ENOENT;
121082cae269SKonstantin Komarov 			goto out;
121182cae269SKonstantin Komarov 		}
121282cae269SKonstantin Komarov 
1213e8b8e97fSKari Argillander 		/* Use absolute boot's 'MFTCluster' to read record. */
121482cae269SKonstantin Komarov 		lbo = vbo + sbi->mft.lbo;
121582cae269SKonstantin Komarov 		len = sbi->record_size;
121682cae269SKonstantin Komarov 	} else if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
121782cae269SKonstantin Komarov 		err = -ENOENT;
121882cae269SKonstantin Komarov 		goto out;
121982cae269SKonstantin Komarov 	} else {
122082cae269SKonstantin Komarov 		if (lcn == SPARSE_LCN) {
122182cae269SKonstantin Komarov 			err = -EINVAL;
122282cae269SKonstantin Komarov 			goto out;
122382cae269SKonstantin Komarov 		}
122482cae269SKonstantin Komarov 
122582cae269SKonstantin Komarov 		lbo = ((u64)lcn << cluster_bits) + off;
122682cae269SKonstantin Komarov 		len = ((u64)clen << cluster_bits) - off;
122782cae269SKonstantin Komarov 	}
122882cae269SKonstantin Komarov 
122982cae269SKonstantin Komarov 	off = lbo & (blocksize - 1);
123082cae269SKonstantin Komarov 	if (nb) {
123182cae269SKonstantin Komarov 		nb->off = off;
123282cae269SKonstantin Komarov 		nb->bytes = bytes;
123382cae269SKonstantin Komarov 	}
123482cae269SKonstantin Komarov 
123582cae269SKonstantin Komarov 	for (;;) {
123682cae269SKonstantin Komarov 		u32 len32 = len >= bytes ? bytes : len;
123782cae269SKonstantin Komarov 		sector_t block = lbo >> sb->s_blocksize_bits;
123882cae269SKonstantin Komarov 
123982cae269SKonstantin Komarov 		do {
124082cae269SKonstantin Komarov 			u32 op = blocksize - off;
124182cae269SKonstantin Komarov 
124282cae269SKonstantin Komarov 			if (op > len32)
124382cae269SKonstantin Komarov 				op = len32;
124482cae269SKonstantin Komarov 
124582cae269SKonstantin Komarov 			bh = ntfs_bread(sb, block);
124682cae269SKonstantin Komarov 			if (!bh) {
124782cae269SKonstantin Komarov 				err = -EIO;
124882cae269SKonstantin Komarov 				goto out;
124982cae269SKonstantin Komarov 			}
125082cae269SKonstantin Komarov 
125182cae269SKonstantin Komarov 			if (buf) {
125282cae269SKonstantin Komarov 				memcpy(buf, bh->b_data + off, op);
125382cae269SKonstantin Komarov 				buf = Add2Ptr(buf, op);
125482cae269SKonstantin Komarov 			}
125582cae269SKonstantin Komarov 
125682cae269SKonstantin Komarov 			if (!nb) {
125782cae269SKonstantin Komarov 				put_bh(bh);
125882cae269SKonstantin Komarov 			} else if (nbh >= ARRAY_SIZE(nb->bh)) {
125982cae269SKonstantin Komarov 				err = -EINVAL;
126082cae269SKonstantin Komarov 				goto out;
126182cae269SKonstantin Komarov 			} else {
126282cae269SKonstantin Komarov 				nb->bh[nbh++] = bh;
126382cae269SKonstantin Komarov 				nb->nbufs = nbh;
126482cae269SKonstantin Komarov 			}
126582cae269SKonstantin Komarov 
126682cae269SKonstantin Komarov 			bytes -= op;
126782cae269SKonstantin Komarov 			if (!bytes)
126882cae269SKonstantin Komarov 				return 0;
126982cae269SKonstantin Komarov 			len32 -= op;
127082cae269SKonstantin Komarov 			block += 1;
127182cae269SKonstantin Komarov 			off = 0;
127282cae269SKonstantin Komarov 
127382cae269SKonstantin Komarov 		} while (len32);
127482cae269SKonstantin Komarov 
127582cae269SKonstantin Komarov 		vcn_next = vcn + clen;
127682cae269SKonstantin Komarov 		if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
127782cae269SKonstantin Komarov 		    vcn != vcn_next) {
127882cae269SKonstantin Komarov 			err = -ENOENT;
127982cae269SKonstantin Komarov 			goto out;
128082cae269SKonstantin Komarov 		}
128182cae269SKonstantin Komarov 
128282cae269SKonstantin Komarov 		if (lcn == SPARSE_LCN) {
128382cae269SKonstantin Komarov 			err = -EINVAL;
128482cae269SKonstantin Komarov 			goto out;
128582cae269SKonstantin Komarov 		}
128682cae269SKonstantin Komarov 
128782cae269SKonstantin Komarov 		lbo = ((u64)lcn << cluster_bits);
128882cae269SKonstantin Komarov 		len = ((u64)clen << cluster_bits);
128982cae269SKonstantin Komarov 	}
129082cae269SKonstantin Komarov 
129182cae269SKonstantin Komarov out:
129282cae269SKonstantin Komarov 	if (!nbh)
129382cae269SKonstantin Komarov 		return err;
129482cae269SKonstantin Komarov 
129582cae269SKonstantin Komarov 	while (nbh) {
129682cae269SKonstantin Komarov 		put_bh(nb->bh[--nbh]);
129782cae269SKonstantin Komarov 		nb->bh[nbh] = NULL;
129882cae269SKonstantin Komarov 	}
129982cae269SKonstantin Komarov 
130082cae269SKonstantin Komarov 	nb->nbufs = 0;
130182cae269SKonstantin Komarov 	return err;
130282cae269SKonstantin Komarov }
130382cae269SKonstantin Komarov 
1304e8b8e97fSKari Argillander /*
1305e8b8e97fSKari Argillander  * ntfs_read_bh
1306e8b8e97fSKari Argillander  *
1307e8b8e97fSKari Argillander  * Return: < 0 if error, 0 if ok, -E_NTFS_FIXUP if need to update fixups.
1308e8b8e97fSKari Argillander  */
ntfs_read_bh(struct ntfs_sb_info * sbi,const struct runs_tree * run,u64 vbo,struct NTFS_RECORD_HEADER * rhdr,u32 bytes,struct ntfs_buffers * nb)130982cae269SKonstantin Komarov int ntfs_read_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
131082cae269SKonstantin Komarov 		 struct NTFS_RECORD_HEADER *rhdr, u32 bytes,
131182cae269SKonstantin Komarov 		 struct ntfs_buffers *nb)
131282cae269SKonstantin Komarov {
131382cae269SKonstantin Komarov 	int err = ntfs_read_run_nb(sbi, run, vbo, rhdr, bytes, nb);
131482cae269SKonstantin Komarov 
131582cae269SKonstantin Komarov 	if (err)
131682cae269SKonstantin Komarov 		return err;
131782cae269SKonstantin Komarov 	return ntfs_fix_post_read(rhdr, nb->bytes, true);
131882cae269SKonstantin Komarov }
131982cae269SKonstantin Komarov 
ntfs_get_bh(struct ntfs_sb_info * sbi,const struct runs_tree * run,u64 vbo,u32 bytes,struct ntfs_buffers * nb)132082cae269SKonstantin Komarov int ntfs_get_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
132182cae269SKonstantin Komarov 		u32 bytes, struct ntfs_buffers *nb)
132282cae269SKonstantin Komarov {
132382cae269SKonstantin Komarov 	int err = 0;
132482cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
132582cae269SKonstantin Komarov 	u32 blocksize = sb->s_blocksize;
132682cae269SKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
132782cae269SKonstantin Komarov 	CLST vcn_next, vcn = vbo >> cluster_bits;
132882cae269SKonstantin Komarov 	u32 off;
132982cae269SKonstantin Komarov 	u32 nbh = 0;
133082cae269SKonstantin Komarov 	CLST lcn, clen;
133182cae269SKonstantin Komarov 	u64 lbo, len;
133282cae269SKonstantin Komarov 	size_t idx;
133382cae269SKonstantin Komarov 
133482cae269SKonstantin Komarov 	nb->bytes = bytes;
133582cae269SKonstantin Komarov 
133682cae269SKonstantin Komarov 	if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
133782cae269SKonstantin Komarov 		err = -ENOENT;
133882cae269SKonstantin Komarov 		goto out;
133982cae269SKonstantin Komarov 	}
134082cae269SKonstantin Komarov 
134182cae269SKonstantin Komarov 	off = vbo & sbi->cluster_mask;
134282cae269SKonstantin Komarov 	lbo = ((u64)lcn << cluster_bits) + off;
134382cae269SKonstantin Komarov 	len = ((u64)clen << cluster_bits) - off;
134482cae269SKonstantin Komarov 
134582cae269SKonstantin Komarov 	nb->off = off = lbo & (blocksize - 1);
134682cae269SKonstantin Komarov 
134782cae269SKonstantin Komarov 	for (;;) {
13486e3331eeSKari Argillander 		u32 len32 = min_t(u64, len, bytes);
134982cae269SKonstantin Komarov 		sector_t block = lbo >> sb->s_blocksize_bits;
135082cae269SKonstantin Komarov 
135182cae269SKonstantin Komarov 		do {
135282cae269SKonstantin Komarov 			u32 op;
135382cae269SKonstantin Komarov 			struct buffer_head *bh;
135482cae269SKonstantin Komarov 
135582cae269SKonstantin Komarov 			if (nbh >= ARRAY_SIZE(nb->bh)) {
135682cae269SKonstantin Komarov 				err = -EINVAL;
135782cae269SKonstantin Komarov 				goto out;
135882cae269SKonstantin Komarov 			}
135982cae269SKonstantin Komarov 
136082cae269SKonstantin Komarov 			op = blocksize - off;
136182cae269SKonstantin Komarov 			if (op > len32)
136282cae269SKonstantin Komarov 				op = len32;
136382cae269SKonstantin Komarov 
136482cae269SKonstantin Komarov 			if (op == blocksize) {
136582cae269SKonstantin Komarov 				bh = sb_getblk(sb, block);
136682cae269SKonstantin Komarov 				if (!bh) {
136782cae269SKonstantin Komarov 					err = -ENOMEM;
136882cae269SKonstantin Komarov 					goto out;
136982cae269SKonstantin Komarov 				}
137082cae269SKonstantin Komarov 				if (buffer_locked(bh))
137182cae269SKonstantin Komarov 					__wait_on_buffer(bh);
137282cae269SKonstantin Komarov 				set_buffer_uptodate(bh);
137382cae269SKonstantin Komarov 			} else {
137482cae269SKonstantin Komarov 				bh = ntfs_bread(sb, block);
137582cae269SKonstantin Komarov 				if (!bh) {
137682cae269SKonstantin Komarov 					err = -EIO;
137782cae269SKonstantin Komarov 					goto out;
137882cae269SKonstantin Komarov 				}
137982cae269SKonstantin Komarov 			}
138082cae269SKonstantin Komarov 
138182cae269SKonstantin Komarov 			nb->bh[nbh++] = bh;
138282cae269SKonstantin Komarov 			bytes -= op;
138382cae269SKonstantin Komarov 			if (!bytes) {
138482cae269SKonstantin Komarov 				nb->nbufs = nbh;
138582cae269SKonstantin Komarov 				return 0;
138682cae269SKonstantin Komarov 			}
138782cae269SKonstantin Komarov 
138882cae269SKonstantin Komarov 			block += 1;
138982cae269SKonstantin Komarov 			len32 -= op;
139082cae269SKonstantin Komarov 			off = 0;
139182cae269SKonstantin Komarov 		} while (len32);
139282cae269SKonstantin Komarov 
139382cae269SKonstantin Komarov 		vcn_next = vcn + clen;
139482cae269SKonstantin Komarov 		if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
139582cae269SKonstantin Komarov 		    vcn != vcn_next) {
139682cae269SKonstantin Komarov 			err = -ENOENT;
139782cae269SKonstantin Komarov 			goto out;
139882cae269SKonstantin Komarov 		}
139982cae269SKonstantin Komarov 
140082cae269SKonstantin Komarov 		lbo = ((u64)lcn << cluster_bits);
140182cae269SKonstantin Komarov 		len = ((u64)clen << cluster_bits);
140282cae269SKonstantin Komarov 	}
140382cae269SKonstantin Komarov 
140482cae269SKonstantin Komarov out:
140582cae269SKonstantin Komarov 	while (nbh) {
140682cae269SKonstantin Komarov 		put_bh(nb->bh[--nbh]);
140782cae269SKonstantin Komarov 		nb->bh[nbh] = NULL;
140882cae269SKonstantin Komarov 	}
140982cae269SKonstantin Komarov 
141082cae269SKonstantin Komarov 	nb->nbufs = 0;
141182cae269SKonstantin Komarov 
141282cae269SKonstantin Komarov 	return err;
141382cae269SKonstantin Komarov }
141482cae269SKonstantin Komarov 
ntfs_write_bh(struct ntfs_sb_info * sbi,struct NTFS_RECORD_HEADER * rhdr,struct ntfs_buffers * nb,int sync)141582cae269SKonstantin Komarov int ntfs_write_bh(struct ntfs_sb_info *sbi, struct NTFS_RECORD_HEADER *rhdr,
141682cae269SKonstantin Komarov 		  struct ntfs_buffers *nb, int sync)
141782cae269SKonstantin Komarov {
141882cae269SKonstantin Komarov 	int err = 0;
141982cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
142082cae269SKonstantin Komarov 	u32 block_size = sb->s_blocksize;
142182cae269SKonstantin Komarov 	u32 bytes = nb->bytes;
142282cae269SKonstantin Komarov 	u32 off = nb->off;
142382cae269SKonstantin Komarov 	u16 fo = le16_to_cpu(rhdr->fix_off);
142482cae269SKonstantin Komarov 	u16 fn = le16_to_cpu(rhdr->fix_num);
142582cae269SKonstantin Komarov 	u32 idx;
142682cae269SKonstantin Komarov 	__le16 *fixup;
142782cae269SKonstantin Komarov 	__le16 sample;
142882cae269SKonstantin Komarov 
142982cae269SKonstantin Komarov 	if ((fo & 1) || fo + fn * sizeof(short) > SECTOR_SIZE || !fn-- ||
143082cae269SKonstantin Komarov 	    fn * SECTOR_SIZE > bytes) {
143182cae269SKonstantin Komarov 		return -EINVAL;
143282cae269SKonstantin Komarov 	}
143382cae269SKonstantin Komarov 
143482cae269SKonstantin Komarov 	for (idx = 0; bytes && idx < nb->nbufs; idx += 1, off = 0) {
143582cae269SKonstantin Komarov 		u32 op = block_size - off;
143682cae269SKonstantin Komarov 		char *bh_data;
143782cae269SKonstantin Komarov 		struct buffer_head *bh = nb->bh[idx];
143882cae269SKonstantin Komarov 		__le16 *ptr, *end_data;
143982cae269SKonstantin Komarov 
144082cae269SKonstantin Komarov 		if (op > bytes)
144182cae269SKonstantin Komarov 			op = bytes;
144282cae269SKonstantin Komarov 
144382cae269SKonstantin Komarov 		if (buffer_locked(bh))
144482cae269SKonstantin Komarov 			__wait_on_buffer(bh);
144582cae269SKonstantin Komarov 
14468335ebe1SKonstantin Komarov 		lock_buffer(bh);
144782cae269SKonstantin Komarov 
144882cae269SKonstantin Komarov 		bh_data = bh->b_data + off;
144982cae269SKonstantin Komarov 		end_data = Add2Ptr(bh_data, op);
145082cae269SKonstantin Komarov 		memcpy(bh_data, rhdr, op);
145182cae269SKonstantin Komarov 
145282cae269SKonstantin Komarov 		if (!idx) {
145382cae269SKonstantin Komarov 			u16 t16;
145482cae269SKonstantin Komarov 
145582cae269SKonstantin Komarov 			fixup = Add2Ptr(bh_data, fo);
145682cae269SKonstantin Komarov 			sample = *fixup;
145782cae269SKonstantin Komarov 			t16 = le16_to_cpu(sample);
145882cae269SKonstantin Komarov 			if (t16 >= 0x7FFF) {
145982cae269SKonstantin Komarov 				sample = *fixup = cpu_to_le16(1);
146082cae269SKonstantin Komarov 			} else {
146182cae269SKonstantin Komarov 				sample = cpu_to_le16(t16 + 1);
146282cae269SKonstantin Komarov 				*fixup = sample;
146382cae269SKonstantin Komarov 			}
146482cae269SKonstantin Komarov 
146582cae269SKonstantin Komarov 			*(__le16 *)Add2Ptr(rhdr, fo) = sample;
146682cae269SKonstantin Komarov 		}
146782cae269SKonstantin Komarov 
146882cae269SKonstantin Komarov 		ptr = Add2Ptr(bh_data, SECTOR_SIZE - sizeof(short));
146982cae269SKonstantin Komarov 
147082cae269SKonstantin Komarov 		do {
147182cae269SKonstantin Komarov 			*++fixup = *ptr;
147282cae269SKonstantin Komarov 			*ptr = sample;
147382cae269SKonstantin Komarov 			ptr += SECTOR_SIZE / sizeof(short);
147482cae269SKonstantin Komarov 		} while (ptr < end_data);
147582cae269SKonstantin Komarov 
147682cae269SKonstantin Komarov 		set_buffer_uptodate(bh);
147782cae269SKonstantin Komarov 		mark_buffer_dirty(bh);
147882cae269SKonstantin Komarov 		unlock_buffer(bh);
147982cae269SKonstantin Komarov 
148082cae269SKonstantin Komarov 		if (sync) {
148182cae269SKonstantin Komarov 			int err2 = sync_dirty_buffer(bh);
148282cae269SKonstantin Komarov 
148382cae269SKonstantin Komarov 			if (!err && err2)
148482cae269SKonstantin Komarov 				err = err2;
148582cae269SKonstantin Komarov 		}
148682cae269SKonstantin Komarov 
148782cae269SKonstantin Komarov 		bytes -= op;
148882cae269SKonstantin Komarov 		rhdr = Add2Ptr(rhdr, op);
148982cae269SKonstantin Komarov 	}
149082cae269SKonstantin Komarov 
149182cae269SKonstantin Komarov 	return err;
149282cae269SKonstantin Komarov }
149382cae269SKonstantin Komarov 
1494e8b8e97fSKari Argillander /*
1495e8b8e97fSKari Argillander  * ntfs_bio_pages - Read/write pages from/to disk.
1496e8b8e97fSKari Argillander  */
ntfs_bio_pages(struct ntfs_sb_info * sbi,const struct runs_tree * run,struct page ** pages,u32 nr_pages,u64 vbo,u32 bytes,enum req_op op)149782cae269SKonstantin Komarov int ntfs_bio_pages(struct ntfs_sb_info *sbi, const struct runs_tree *run,
149882cae269SKonstantin Komarov 		   struct page **pages, u32 nr_pages, u64 vbo, u32 bytes,
1499ce6b5315SBart Van Assche 		   enum req_op op)
150082cae269SKonstantin Komarov {
150182cae269SKonstantin Komarov 	int err = 0;
150282cae269SKonstantin Komarov 	struct bio *new, *bio = NULL;
150382cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
150482cae269SKonstantin Komarov 	struct block_device *bdev = sb->s_bdev;
150582cae269SKonstantin Komarov 	struct page *page;
150682cae269SKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
150782cae269SKonstantin Komarov 	CLST lcn, clen, vcn, vcn_next;
150882cae269SKonstantin Komarov 	u32 add, off, page_idx;
150982cae269SKonstantin Komarov 	u64 lbo, len;
151082cae269SKonstantin Komarov 	size_t run_idx;
151182cae269SKonstantin Komarov 	struct blk_plug plug;
151282cae269SKonstantin Komarov 
151382cae269SKonstantin Komarov 	if (!bytes)
151482cae269SKonstantin Komarov 		return 0;
151582cae269SKonstantin Komarov 
151682cae269SKonstantin Komarov 	blk_start_plug(&plug);
151782cae269SKonstantin Komarov 
1518e8b8e97fSKari Argillander 	/* Align vbo and bytes to be 512 bytes aligned. */
151982cae269SKonstantin Komarov 	lbo = (vbo + bytes + 511) & ~511ull;
152082cae269SKonstantin Komarov 	vbo = vbo & ~511ull;
152182cae269SKonstantin Komarov 	bytes = lbo - vbo;
152282cae269SKonstantin Komarov 
152382cae269SKonstantin Komarov 	vcn = vbo >> cluster_bits;
152482cae269SKonstantin Komarov 	if (!run_lookup_entry(run, vcn, &lcn, &clen, &run_idx)) {
152582cae269SKonstantin Komarov 		err = -ENOENT;
152682cae269SKonstantin Komarov 		goto out;
152782cae269SKonstantin Komarov 	}
152882cae269SKonstantin Komarov 	off = vbo & sbi->cluster_mask;
152982cae269SKonstantin Komarov 	page_idx = 0;
153082cae269SKonstantin Komarov 	page = pages[0];
153182cae269SKonstantin Komarov 
153282cae269SKonstantin Komarov 	for (;;) {
153382cae269SKonstantin Komarov 		lbo = ((u64)lcn << cluster_bits) + off;
153482cae269SKonstantin Komarov 		len = ((u64)clen << cluster_bits) - off;
153582cae269SKonstantin Komarov new_bio:
153607888c66SChristoph Hellwig 		new = bio_alloc(bdev, nr_pages - page_idx, op, GFP_NOFS);
153782cae269SKonstantin Komarov 		if (bio) {
153882cae269SKonstantin Komarov 			bio_chain(bio, new);
153982cae269SKonstantin Komarov 			submit_bio(bio);
154082cae269SKonstantin Komarov 		}
154182cae269SKonstantin Komarov 		bio = new;
154282cae269SKonstantin Komarov 		bio->bi_iter.bi_sector = lbo >> 9;
154382cae269SKonstantin Komarov 
154482cae269SKonstantin Komarov 		while (len) {
154582cae269SKonstantin Komarov 			off = vbo & (PAGE_SIZE - 1);
154682cae269SKonstantin Komarov 			add = off + len > PAGE_SIZE ? (PAGE_SIZE - off) : len;
154782cae269SKonstantin Komarov 
154882cae269SKonstantin Komarov 			if (bio_add_page(bio, page, add, off) < add)
154982cae269SKonstantin Komarov 				goto new_bio;
155082cae269SKonstantin Komarov 
155182cae269SKonstantin Komarov 			if (bytes <= add)
155282cae269SKonstantin Komarov 				goto out;
155382cae269SKonstantin Komarov 			bytes -= add;
155482cae269SKonstantin Komarov 			vbo += add;
155582cae269SKonstantin Komarov 
155682cae269SKonstantin Komarov 			if (add + off == PAGE_SIZE) {
155782cae269SKonstantin Komarov 				page_idx += 1;
155882cae269SKonstantin Komarov 				if (WARN_ON(page_idx >= nr_pages)) {
155982cae269SKonstantin Komarov 					err = -EINVAL;
156082cae269SKonstantin Komarov 					goto out;
156182cae269SKonstantin Komarov 				}
156282cae269SKonstantin Komarov 				page = pages[page_idx];
156382cae269SKonstantin Komarov 			}
156482cae269SKonstantin Komarov 
156582cae269SKonstantin Komarov 			if (len <= add)
156682cae269SKonstantin Komarov 				break;
156782cae269SKonstantin Komarov 			len -= add;
156882cae269SKonstantin Komarov 			lbo += add;
156982cae269SKonstantin Komarov 		}
157082cae269SKonstantin Komarov 
157182cae269SKonstantin Komarov 		vcn_next = vcn + clen;
157282cae269SKonstantin Komarov 		if (!run_get_entry(run, ++run_idx, &vcn, &lcn, &clen) ||
157382cae269SKonstantin Komarov 		    vcn != vcn_next) {
157482cae269SKonstantin Komarov 			err = -ENOENT;
157582cae269SKonstantin Komarov 			goto out;
157682cae269SKonstantin Komarov 		}
157782cae269SKonstantin Komarov 		off = 0;
157882cae269SKonstantin Komarov 	}
157982cae269SKonstantin Komarov out:
158082cae269SKonstantin Komarov 	if (bio) {
158182cae269SKonstantin Komarov 		if (!err)
158282cae269SKonstantin Komarov 			err = submit_bio_wait(bio);
158382cae269SKonstantin Komarov 		bio_put(bio);
158482cae269SKonstantin Komarov 	}
158582cae269SKonstantin Komarov 	blk_finish_plug(&plug);
158682cae269SKonstantin Komarov 
158782cae269SKonstantin Komarov 	return err;
158882cae269SKonstantin Komarov }
158982cae269SKonstantin Komarov 
159082cae269SKonstantin Komarov /*
1591e8b8e97fSKari Argillander  * ntfs_bio_fill_1 - Helper for ntfs_loadlog_and_replay().
1592e8b8e97fSKari Argillander  *
1593e8b8e97fSKari Argillander  * Fill on-disk logfile range by (-1)
1594e8b8e97fSKari Argillander  * this means empty logfile.
159582cae269SKonstantin Komarov  */
ntfs_bio_fill_1(struct ntfs_sb_info * sbi,const struct runs_tree * run)159682cae269SKonstantin Komarov int ntfs_bio_fill_1(struct ntfs_sb_info *sbi, const struct runs_tree *run)
159782cae269SKonstantin Komarov {
159882cae269SKonstantin Komarov 	int err = 0;
159982cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
160082cae269SKonstantin Komarov 	struct block_device *bdev = sb->s_bdev;
160182cae269SKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
160282cae269SKonstantin Komarov 	struct bio *new, *bio = NULL;
160382cae269SKonstantin Komarov 	CLST lcn, clen;
160482cae269SKonstantin Komarov 	u64 lbo, len;
160582cae269SKonstantin Komarov 	size_t run_idx;
160682cae269SKonstantin Komarov 	struct page *fill;
160782cae269SKonstantin Komarov 	void *kaddr;
160882cae269SKonstantin Komarov 	struct blk_plug plug;
160982cae269SKonstantin Komarov 
161082cae269SKonstantin Komarov 	fill = alloc_page(GFP_KERNEL);
161182cae269SKonstantin Komarov 	if (!fill)
161282cae269SKonstantin Komarov 		return -ENOMEM;
161382cae269SKonstantin Komarov 
161482cae269SKonstantin Komarov 	kaddr = kmap_atomic(fill);
161582cae269SKonstantin Komarov 	memset(kaddr, -1, PAGE_SIZE);
161682cae269SKonstantin Komarov 	kunmap_atomic(kaddr);
161782cae269SKonstantin Komarov 	flush_dcache_page(fill);
161882cae269SKonstantin Komarov 	lock_page(fill);
161982cae269SKonstantin Komarov 
162082cae269SKonstantin Komarov 	if (!run_lookup_entry(run, 0, &lcn, &clen, &run_idx)) {
162182cae269SKonstantin Komarov 		err = -ENOENT;
162282cae269SKonstantin Komarov 		goto out;
162382cae269SKonstantin Komarov 	}
162482cae269SKonstantin Komarov 
162582cae269SKonstantin Komarov 	/*
1626e8b8e97fSKari Argillander 	 * TODO: Try blkdev_issue_write_same.
162782cae269SKonstantin Komarov 	 */
162882cae269SKonstantin Komarov 	blk_start_plug(&plug);
162982cae269SKonstantin Komarov 	do {
163082cae269SKonstantin Komarov 		lbo = (u64)lcn << cluster_bits;
163182cae269SKonstantin Komarov 		len = (u64)clen << cluster_bits;
163282cae269SKonstantin Komarov new_bio:
163307888c66SChristoph Hellwig 		new = bio_alloc(bdev, BIO_MAX_VECS, REQ_OP_WRITE, GFP_NOFS);
163482cae269SKonstantin Komarov 		if (bio) {
163582cae269SKonstantin Komarov 			bio_chain(bio, new);
163682cae269SKonstantin Komarov 			submit_bio(bio);
163782cae269SKonstantin Komarov 		}
163882cae269SKonstantin Komarov 		bio = new;
163982cae269SKonstantin Komarov 		bio->bi_iter.bi_sector = lbo >> 9;
164082cae269SKonstantin Komarov 
164182cae269SKonstantin Komarov 		for (;;) {
164282cae269SKonstantin Komarov 			u32 add = len > PAGE_SIZE ? PAGE_SIZE : len;
164382cae269SKonstantin Komarov 
164482cae269SKonstantin Komarov 			if (bio_add_page(bio, fill, add, 0) < add)
164582cae269SKonstantin Komarov 				goto new_bio;
164682cae269SKonstantin Komarov 
164782cae269SKonstantin Komarov 			lbo += add;
164882cae269SKonstantin Komarov 			if (len <= add)
164982cae269SKonstantin Komarov 				break;
165082cae269SKonstantin Komarov 			len -= add;
165182cae269SKonstantin Komarov 		}
165282cae269SKonstantin Komarov 	} while (run_get_entry(run, ++run_idx, NULL, &lcn, &clen));
165382cae269SKonstantin Komarov 
165482cae269SKonstantin Komarov 	if (!err)
165582cae269SKonstantin Komarov 		err = submit_bio_wait(bio);
165682cae269SKonstantin Komarov 	bio_put(bio);
1657365ab499SDan Carpenter 
165882cae269SKonstantin Komarov 	blk_finish_plug(&plug);
165982cae269SKonstantin Komarov out:
166082cae269SKonstantin Komarov 	unlock_page(fill);
166182cae269SKonstantin Komarov 	put_page(fill);
166282cae269SKonstantin Komarov 
166382cae269SKonstantin Komarov 	return err;
166482cae269SKonstantin Komarov }
166582cae269SKonstantin Komarov 
ntfs_vbo_to_lbo(struct ntfs_sb_info * sbi,const struct runs_tree * run,u64 vbo,u64 * lbo,u64 * bytes)166682cae269SKonstantin Komarov int ntfs_vbo_to_lbo(struct ntfs_sb_info *sbi, const struct runs_tree *run,
166782cae269SKonstantin Komarov 		    u64 vbo, u64 *lbo, u64 *bytes)
166882cae269SKonstantin Komarov {
166982cae269SKonstantin Komarov 	u32 off;
167082cae269SKonstantin Komarov 	CLST lcn, len;
167182cae269SKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
167282cae269SKonstantin Komarov 
167382cae269SKonstantin Komarov 	if (!run_lookup_entry(run, vbo >> cluster_bits, &lcn, &len, NULL))
167482cae269SKonstantin Komarov 		return -ENOENT;
167582cae269SKonstantin Komarov 
167682cae269SKonstantin Komarov 	off = vbo & sbi->cluster_mask;
167782cae269SKonstantin Komarov 	*lbo = lcn == SPARSE_LCN ? -1 : (((u64)lcn << cluster_bits) + off);
167882cae269SKonstantin Komarov 	*bytes = ((u64)len << cluster_bits) - off;
167982cae269SKonstantin Komarov 
168082cae269SKonstantin Komarov 	return 0;
168182cae269SKonstantin Komarov }
168282cae269SKonstantin Komarov 
ntfs_new_inode(struct ntfs_sb_info * sbi,CLST rno,enum RECORD_FLAG flag)1683a81f47c4SKonstantin Komarov struct ntfs_inode *ntfs_new_inode(struct ntfs_sb_info *sbi, CLST rno,
1684a81f47c4SKonstantin Komarov 				  enum RECORD_FLAG flag)
168582cae269SKonstantin Komarov {
168682cae269SKonstantin Komarov 	int err = 0;
168782cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
168882cae269SKonstantin Komarov 	struct inode *inode = new_inode(sb);
168982cae269SKonstantin Komarov 	struct ntfs_inode *ni;
169082cae269SKonstantin Komarov 
169182cae269SKonstantin Komarov 	if (!inode)
169282cae269SKonstantin Komarov 		return ERR_PTR(-ENOMEM);
169382cae269SKonstantin Komarov 
169482cae269SKonstantin Komarov 	ni = ntfs_i(inode);
169582cae269SKonstantin Komarov 
1696a81f47c4SKonstantin Komarov 	err = mi_format_new(&ni->mi, sbi, rno, flag, false);
169782cae269SKonstantin Komarov 	if (err)
169882cae269SKonstantin Komarov 		goto out;
169982cae269SKonstantin Komarov 
170082cae269SKonstantin Komarov 	inode->i_ino = rno;
170182cae269SKonstantin Komarov 	if (insert_inode_locked(inode) < 0) {
170282cae269SKonstantin Komarov 		err = -EIO;
170382cae269SKonstantin Komarov 		goto out;
170482cae269SKonstantin Komarov 	}
170582cae269SKonstantin Komarov 
170682cae269SKonstantin Komarov out:
170782cae269SKonstantin Komarov 	if (err) {
1708db2a3cc6SYe Bin 		make_bad_inode(inode);
170982cae269SKonstantin Komarov 		iput(inode);
171082cae269SKonstantin Komarov 		ni = ERR_PTR(err);
171182cae269SKonstantin Komarov 	}
171282cae269SKonstantin Komarov 	return ni;
171382cae269SKonstantin Komarov }
171482cae269SKonstantin Komarov 
171582cae269SKonstantin Komarov /*
171682cae269SKonstantin Komarov  * O:BAG:BAD:(A;OICI;FA;;;WD)
1717e8b8e97fSKari Argillander  * Owner S-1-5-32-544 (Administrators)
1718e8b8e97fSKari Argillander  * Group S-1-5-32-544 (Administrators)
171982cae269SKonstantin Komarov  * ACE: allow S-1-1-0 (Everyone) with FILE_ALL_ACCESS
172082cae269SKonstantin Komarov  */
172182cae269SKonstantin Komarov const u8 s_default_security[] __aligned(8) = {
172282cae269SKonstantin Komarov 	0x01, 0x00, 0x04, 0x80, 0x30, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
172382cae269SKonstantin Komarov 	0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1C, 0x00,
172482cae269SKonstantin Komarov 	0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x14, 0x00, 0xFF, 0x01, 0x1F, 0x00,
172582cae269SKonstantin Komarov 	0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
172682cae269SKonstantin Komarov 	0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00,
172782cae269SKonstantin Komarov 	0x20, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
172882cae269SKonstantin Komarov 	0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00,
172982cae269SKonstantin Komarov };
173082cae269SKonstantin Komarov 
173182cae269SKonstantin Komarov static_assert(sizeof(s_default_security) == 0x50);
173282cae269SKonstantin Komarov 
sid_length(const struct SID * sid)173382cae269SKonstantin Komarov static inline u32 sid_length(const struct SID *sid)
173482cae269SKonstantin Komarov {
173582cae269SKonstantin Komarov 	return struct_size(sid, SubAuthority, sid->SubAuthorityCount);
173682cae269SKonstantin Komarov }
173782cae269SKonstantin Komarov 
173882cae269SKonstantin Komarov /*
1739e8b8e97fSKari Argillander  * is_acl_valid
1740e8b8e97fSKari Argillander  *
1741e8b8e97fSKari Argillander  * Thanks Mark Harmstone for idea.
174282cae269SKonstantin Komarov  */
is_acl_valid(const struct ACL * acl,u32 len)174382cae269SKonstantin Komarov static bool is_acl_valid(const struct ACL *acl, u32 len)
174482cae269SKonstantin Komarov {
174582cae269SKonstantin Komarov 	const struct ACE_HEADER *ace;
174682cae269SKonstantin Komarov 	u32 i;
174782cae269SKonstantin Komarov 	u16 ace_count, ace_size;
174882cae269SKonstantin Komarov 
174982cae269SKonstantin Komarov 	if (acl->AclRevision != ACL_REVISION &&
175082cae269SKonstantin Komarov 	    acl->AclRevision != ACL_REVISION_DS) {
175182cae269SKonstantin Komarov 		/*
175282cae269SKonstantin Komarov 		 * This value should be ACL_REVISION, unless the ACL contains an
175382cae269SKonstantin Komarov 		 * object-specific ACE, in which case this value must be ACL_REVISION_DS.
175482cae269SKonstantin Komarov 		 * All ACEs in an ACL must be at the same revision level.
175582cae269SKonstantin Komarov 		 */
175682cae269SKonstantin Komarov 		return false;
175782cae269SKonstantin Komarov 	}
175882cae269SKonstantin Komarov 
175982cae269SKonstantin Komarov 	if (acl->Sbz1)
176082cae269SKonstantin Komarov 		return false;
176182cae269SKonstantin Komarov 
176282cae269SKonstantin Komarov 	if (le16_to_cpu(acl->AclSize) > len)
176382cae269SKonstantin Komarov 		return false;
176482cae269SKonstantin Komarov 
176582cae269SKonstantin Komarov 	if (acl->Sbz2)
176682cae269SKonstantin Komarov 		return false;
176782cae269SKonstantin Komarov 
176882cae269SKonstantin Komarov 	len -= sizeof(struct ACL);
176982cae269SKonstantin Komarov 	ace = (struct ACE_HEADER *)&acl[1];
177082cae269SKonstantin Komarov 	ace_count = le16_to_cpu(acl->AceCount);
177182cae269SKonstantin Komarov 
177282cae269SKonstantin Komarov 	for (i = 0; i < ace_count; i++) {
177382cae269SKonstantin Komarov 		if (len < sizeof(struct ACE_HEADER))
177482cae269SKonstantin Komarov 			return false;
177582cae269SKonstantin Komarov 
177682cae269SKonstantin Komarov 		ace_size = le16_to_cpu(ace->AceSize);
177782cae269SKonstantin Komarov 		if (len < ace_size)
177882cae269SKonstantin Komarov 			return false;
177982cae269SKonstantin Komarov 
178082cae269SKonstantin Komarov 		len -= ace_size;
178182cae269SKonstantin Komarov 		ace = Add2Ptr(ace, ace_size);
178282cae269SKonstantin Komarov 	}
178382cae269SKonstantin Komarov 
178482cae269SKonstantin Komarov 	return true;
178582cae269SKonstantin Komarov }
178682cae269SKonstantin Komarov 
is_sd_valid(const struct SECURITY_DESCRIPTOR_RELATIVE * sd,u32 len)178782cae269SKonstantin Komarov bool is_sd_valid(const struct SECURITY_DESCRIPTOR_RELATIVE *sd, u32 len)
178882cae269SKonstantin Komarov {
178982cae269SKonstantin Komarov 	u32 sd_owner, sd_group, sd_sacl, sd_dacl;
179082cae269SKonstantin Komarov 
179182cae269SKonstantin Komarov 	if (len < sizeof(struct SECURITY_DESCRIPTOR_RELATIVE))
179282cae269SKonstantin Komarov 		return false;
179382cae269SKonstantin Komarov 
179482cae269SKonstantin Komarov 	if (sd->Revision != 1)
179582cae269SKonstantin Komarov 		return false;
179682cae269SKonstantin Komarov 
179782cae269SKonstantin Komarov 	if (sd->Sbz1)
179882cae269SKonstantin Komarov 		return false;
179982cae269SKonstantin Komarov 
180082cae269SKonstantin Komarov 	if (!(sd->Control & SE_SELF_RELATIVE))
180182cae269SKonstantin Komarov 		return false;
180282cae269SKonstantin Komarov 
180382cae269SKonstantin Komarov 	sd_owner = le32_to_cpu(sd->Owner);
180482cae269SKonstantin Komarov 	if (sd_owner) {
180582cae269SKonstantin Komarov 		const struct SID *owner = Add2Ptr(sd, sd_owner);
180682cae269SKonstantin Komarov 
180782cae269SKonstantin Komarov 		if (sd_owner + offsetof(struct SID, SubAuthority) > len)
180882cae269SKonstantin Komarov 			return false;
180982cae269SKonstantin Komarov 
181082cae269SKonstantin Komarov 		if (owner->Revision != 1)
181182cae269SKonstantin Komarov 			return false;
181282cae269SKonstantin Komarov 
181382cae269SKonstantin Komarov 		if (sd_owner + sid_length(owner) > len)
181482cae269SKonstantin Komarov 			return false;
181582cae269SKonstantin Komarov 	}
181682cae269SKonstantin Komarov 
181782cae269SKonstantin Komarov 	sd_group = le32_to_cpu(sd->Group);
181882cae269SKonstantin Komarov 	if (sd_group) {
181982cae269SKonstantin Komarov 		const struct SID *group = Add2Ptr(sd, sd_group);
182082cae269SKonstantin Komarov 
182182cae269SKonstantin Komarov 		if (sd_group + offsetof(struct SID, SubAuthority) > len)
182282cae269SKonstantin Komarov 			return false;
182382cae269SKonstantin Komarov 
182482cae269SKonstantin Komarov 		if (group->Revision != 1)
182582cae269SKonstantin Komarov 			return false;
182682cae269SKonstantin Komarov 
182782cae269SKonstantin Komarov 		if (sd_group + sid_length(group) > len)
182882cae269SKonstantin Komarov 			return false;
182982cae269SKonstantin Komarov 	}
183082cae269SKonstantin Komarov 
183182cae269SKonstantin Komarov 	sd_sacl = le32_to_cpu(sd->Sacl);
183282cae269SKonstantin Komarov 	if (sd_sacl) {
183382cae269SKonstantin Komarov 		const struct ACL *sacl = Add2Ptr(sd, sd_sacl);
183482cae269SKonstantin Komarov 
183582cae269SKonstantin Komarov 		if (sd_sacl + sizeof(struct ACL) > len)
183682cae269SKonstantin Komarov 			return false;
183782cae269SKonstantin Komarov 
183882cae269SKonstantin Komarov 		if (!is_acl_valid(sacl, len - sd_sacl))
183982cae269SKonstantin Komarov 			return false;
184082cae269SKonstantin Komarov 	}
184182cae269SKonstantin Komarov 
184282cae269SKonstantin Komarov 	sd_dacl = le32_to_cpu(sd->Dacl);
184382cae269SKonstantin Komarov 	if (sd_dacl) {
184482cae269SKonstantin Komarov 		const struct ACL *dacl = Add2Ptr(sd, sd_dacl);
184582cae269SKonstantin Komarov 
184682cae269SKonstantin Komarov 		if (sd_dacl + sizeof(struct ACL) > len)
184782cae269SKonstantin Komarov 			return false;
184882cae269SKonstantin Komarov 
184982cae269SKonstantin Komarov 		if (!is_acl_valid(dacl, len - sd_dacl))
185082cae269SKonstantin Komarov 			return false;
185182cae269SKonstantin Komarov 	}
185282cae269SKonstantin Komarov 
185382cae269SKonstantin Komarov 	return true;
185482cae269SKonstantin Komarov }
185582cae269SKonstantin Komarov 
185682cae269SKonstantin Komarov /*
1857e8b8e97fSKari Argillander  * ntfs_security_init - Load and parse $Secure.
185882cae269SKonstantin Komarov  */
ntfs_security_init(struct ntfs_sb_info * sbi)185982cae269SKonstantin Komarov int ntfs_security_init(struct ntfs_sb_info *sbi)
186082cae269SKonstantin Komarov {
186182cae269SKonstantin Komarov 	int err;
186282cae269SKonstantin Komarov 	struct super_block *sb = sbi->sb;
186382cae269SKonstantin Komarov 	struct inode *inode;
186482cae269SKonstantin Komarov 	struct ntfs_inode *ni;
186582cae269SKonstantin Komarov 	struct MFT_REF ref;
186682cae269SKonstantin Komarov 	struct ATTRIB *attr;
186782cae269SKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
186882cae269SKonstantin Komarov 	u64 sds_size;
18698c01308bSNathan Chancellor 	size_t off;
187082cae269SKonstantin Komarov 	struct NTFS_DE *ne;
187182cae269SKonstantin Komarov 	struct NTFS_DE_SII *sii_e;
187282cae269SKonstantin Komarov 	struct ntfs_fnd *fnd_sii = NULL;
187382cae269SKonstantin Komarov 	const struct INDEX_ROOT *root_sii;
187482cae269SKonstantin Komarov 	const struct INDEX_ROOT *root_sdh;
187582cae269SKonstantin Komarov 	struct ntfs_index *indx_sdh = &sbi->security.index_sdh;
187682cae269SKonstantin Komarov 	struct ntfs_index *indx_sii = &sbi->security.index_sii;
187782cae269SKonstantin Komarov 
187882cae269SKonstantin Komarov 	ref.low = cpu_to_le32(MFT_REC_SECURE);
187982cae269SKonstantin Komarov 	ref.high = 0;
188082cae269SKonstantin Komarov 	ref.seq = cpu_to_le16(MFT_REC_SECURE);
188182cae269SKonstantin Komarov 
188282cae269SKonstantin Komarov 	inode = ntfs_iget5(sb, &ref, &NAME_SECURE);
188382cae269SKonstantin Komarov 	if (IS_ERR(inode)) {
188482cae269SKonstantin Komarov 		err = PTR_ERR(inode);
1885e43f6ec2SKonstantin Komarov 		ntfs_err(sb, "Failed to load $Secure (%d).", err);
188682cae269SKonstantin Komarov 		inode = NULL;
188782cae269SKonstantin Komarov 		goto out;
188882cae269SKonstantin Komarov 	}
188982cae269SKonstantin Komarov 
189082cae269SKonstantin Komarov 	ni = ntfs_i(inode);
189182cae269SKonstantin Komarov 
189282cae269SKonstantin Komarov 	le = NULL;
189382cae269SKonstantin Komarov 
189482cae269SKonstantin Komarov 	attr = ni_find_attr(ni, NULL, &le, ATTR_ROOT, SDH_NAME,
189582cae269SKonstantin Komarov 			    ARRAY_SIZE(SDH_NAME), NULL, NULL);
1896e43f6ec2SKonstantin Komarov 	if (!attr ||
1897e43f6ec2SKonstantin Komarov 	    !(root_sdh = resident_data_ex(attr, sizeof(struct INDEX_ROOT))) ||
1898fc499245SKonstantin Komarov 	    root_sdh->type != ATTR_ZERO ||
1899bfcdbae0SEdward Lo 	    root_sdh->rule != NTFS_COLLATION_TYPE_SECURITY_HASH ||
1900fc499245SKonstantin Komarov 	    offsetof(struct INDEX_ROOT, ihdr) +
1901fc499245SKonstantin Komarov 			    le32_to_cpu(root_sdh->ihdr.used) >
1902fc499245SKonstantin Komarov 		    le32_to_cpu(attr->res.data_size)) {
1903e43f6ec2SKonstantin Komarov 		ntfs_err(sb, "$Secure::$SDH is corrupted.");
190482cae269SKonstantin Komarov 		err = -EINVAL;
190582cae269SKonstantin Komarov 		goto out;
190682cae269SKonstantin Komarov 	}
190782cae269SKonstantin Komarov 
190882cae269SKonstantin Komarov 	err = indx_init(indx_sdh, sbi, attr, INDEX_MUTEX_SDH);
1909e43f6ec2SKonstantin Komarov 	if (err) {
1910e43f6ec2SKonstantin Komarov 		ntfs_err(sb, "Failed to initialize $Secure::$SDH (%d).", err);
191182cae269SKonstantin Komarov 		goto out;
191282cae269SKonstantin Komarov 	}
191382cae269SKonstantin Komarov 
1914e43f6ec2SKonstantin Komarov 	attr = ni_find_attr(ni, attr, &le, ATTR_ROOT, SII_NAME,
1915e43f6ec2SKonstantin Komarov 			    ARRAY_SIZE(SII_NAME), NULL, NULL);
1916e43f6ec2SKonstantin Komarov 	if (!attr ||
1917e43f6ec2SKonstantin Komarov 	    !(root_sii = resident_data_ex(attr, sizeof(struct INDEX_ROOT))) ||
1918fc499245SKonstantin Komarov 	    root_sii->type != ATTR_ZERO ||
1919bfcdbae0SEdward Lo 	    root_sii->rule != NTFS_COLLATION_TYPE_UINT ||
1920fc499245SKonstantin Komarov 	    offsetof(struct INDEX_ROOT, ihdr) +
1921fc499245SKonstantin Komarov 			    le32_to_cpu(root_sii->ihdr.used) >
1922fc499245SKonstantin Komarov 		    le32_to_cpu(attr->res.data_size)) {
1923e43f6ec2SKonstantin Komarov 		ntfs_err(sb, "$Secure::$SII is corrupted.");
192482cae269SKonstantin Komarov 		err = -EINVAL;
192582cae269SKonstantin Komarov 		goto out;
192682cae269SKonstantin Komarov 	}
192782cae269SKonstantin Komarov 
192882cae269SKonstantin Komarov 	err = indx_init(indx_sii, sbi, attr, INDEX_MUTEX_SII);
1929e43f6ec2SKonstantin Komarov 	if (err) {
1930e43f6ec2SKonstantin Komarov 		ntfs_err(sb, "Failed to initialize $Secure::$SII (%d).", err);
193182cae269SKonstantin Komarov 		goto out;
1932e43f6ec2SKonstantin Komarov 	}
193382cae269SKonstantin Komarov 
193482cae269SKonstantin Komarov 	fnd_sii = fnd_get();
193582cae269SKonstantin Komarov 	if (!fnd_sii) {
193682cae269SKonstantin Komarov 		err = -ENOMEM;
193782cae269SKonstantin Komarov 		goto out;
193882cae269SKonstantin Komarov 	}
193982cae269SKonstantin Komarov 
194082cae269SKonstantin Komarov 	sds_size = inode->i_size;
194182cae269SKonstantin Komarov 
1942e8b8e97fSKari Argillander 	/* Find the last valid Id. */
194382cae269SKonstantin Komarov 	sbi->security.next_id = SECURITY_ID_FIRST;
1944e8b8e97fSKari Argillander 	/* Always write new security at the end of bucket. */
194582cae269SKonstantin Komarov 	sbi->security.next_off =
1946fa3cacf5SKari Argillander 		ALIGN(sds_size - SecurityDescriptorsBlockSize, 16);
194782cae269SKonstantin Komarov 
194882cae269SKonstantin Komarov 	off = 0;
194982cae269SKonstantin Komarov 	ne = NULL;
195082cae269SKonstantin Komarov 
195182cae269SKonstantin Komarov 	for (;;) {
195282cae269SKonstantin Komarov 		u32 next_id;
195382cae269SKonstantin Komarov 
195482cae269SKonstantin Komarov 		err = indx_find_raw(indx_sii, ni, root_sii, &ne, &off, fnd_sii);
195582cae269SKonstantin Komarov 		if (err || !ne)
195682cae269SKonstantin Komarov 			break;
195782cae269SKonstantin Komarov 
195882cae269SKonstantin Komarov 		sii_e = (struct NTFS_DE_SII *)ne;
1959a81f47c4SKonstantin Komarov 		if (le16_to_cpu(ne->view.data_size) < sizeof(sii_e->sec_hdr))
196082cae269SKonstantin Komarov 			continue;
196182cae269SKonstantin Komarov 
196282cae269SKonstantin Komarov 		next_id = le32_to_cpu(sii_e->sec_id) + 1;
196382cae269SKonstantin Komarov 		if (next_id >= sbi->security.next_id)
196482cae269SKonstantin Komarov 			sbi->security.next_id = next_id;
196582cae269SKonstantin Komarov 	}
196682cae269SKonstantin Komarov 
196782cae269SKonstantin Komarov 	sbi->security.ni = ni;
196882cae269SKonstantin Komarov 	inode = NULL;
196982cae269SKonstantin Komarov out:
197082cae269SKonstantin Komarov 	iput(inode);
197182cae269SKonstantin Komarov 	fnd_put(fnd_sii);
197282cae269SKonstantin Komarov 
197382cae269SKonstantin Komarov 	return err;
197482cae269SKonstantin Komarov }
197582cae269SKonstantin Komarov 
197682cae269SKonstantin Komarov /*
1977e8b8e97fSKari Argillander  * ntfs_get_security_by_id - Read security descriptor by id.
197882cae269SKonstantin Komarov  */
ntfs_get_security_by_id(struct ntfs_sb_info * sbi,__le32 security_id,struct SECURITY_DESCRIPTOR_RELATIVE ** sd,size_t * size)197982cae269SKonstantin Komarov int ntfs_get_security_by_id(struct ntfs_sb_info *sbi, __le32 security_id,
198082cae269SKonstantin Komarov 			    struct SECURITY_DESCRIPTOR_RELATIVE **sd,
198182cae269SKonstantin Komarov 			    size_t *size)
198282cae269SKonstantin Komarov {
198382cae269SKonstantin Komarov 	int err;
198482cae269SKonstantin Komarov 	int diff;
198582cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->security.ni;
198682cae269SKonstantin Komarov 	struct ntfs_index *indx = &sbi->security.index_sii;
198782cae269SKonstantin Komarov 	void *p = NULL;
198882cae269SKonstantin Komarov 	struct NTFS_DE_SII *sii_e;
198982cae269SKonstantin Komarov 	struct ntfs_fnd *fnd_sii;
199082cae269SKonstantin Komarov 	struct SECURITY_HDR d_security;
199182cae269SKonstantin Komarov 	const struct INDEX_ROOT *root_sii;
199282cae269SKonstantin Komarov 	u32 t32;
199382cae269SKonstantin Komarov 
199482cae269SKonstantin Komarov 	*sd = NULL;
199582cae269SKonstantin Komarov 
199682cae269SKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_SECURITY);
199782cae269SKonstantin Komarov 
199882cae269SKonstantin Komarov 	fnd_sii = fnd_get();
199982cae269SKonstantin Komarov 	if (!fnd_sii) {
200082cae269SKonstantin Komarov 		err = -ENOMEM;
200182cae269SKonstantin Komarov 		goto out;
200282cae269SKonstantin Komarov 	}
200382cae269SKonstantin Komarov 
200482cae269SKonstantin Komarov 	root_sii = indx_get_root(indx, ni, NULL, NULL);
200582cae269SKonstantin Komarov 	if (!root_sii) {
200682cae269SKonstantin Komarov 		err = -EINVAL;
200782cae269SKonstantin Komarov 		goto out;
200882cae269SKonstantin Komarov 	}
200982cae269SKonstantin Komarov 
2010e8b8e97fSKari Argillander 	/* Try to find this SECURITY descriptor in SII indexes. */
201182cae269SKonstantin Komarov 	err = indx_find(indx, ni, root_sii, &security_id, sizeof(security_id),
201282cae269SKonstantin Komarov 			NULL, &diff, (struct NTFS_DE **)&sii_e, fnd_sii);
201382cae269SKonstantin Komarov 	if (err)
201482cae269SKonstantin Komarov 		goto out;
201582cae269SKonstantin Komarov 
201682cae269SKonstantin Komarov 	if (diff)
201782cae269SKonstantin Komarov 		goto out;
201882cae269SKonstantin Komarov 
201982cae269SKonstantin Komarov 	t32 = le32_to_cpu(sii_e->sec_hdr.size);
2020a81f47c4SKonstantin Komarov 	if (t32 < sizeof(struct SECURITY_HDR)) {
202182cae269SKonstantin Komarov 		err = -EINVAL;
202282cae269SKonstantin Komarov 		goto out;
202382cae269SKonstantin Komarov 	}
202482cae269SKonstantin Komarov 
2025a81f47c4SKonstantin Komarov 	if (t32 > sizeof(struct SECURITY_HDR) + 0x10000) {
2026e8b8e97fSKari Argillander 		/* Looks like too big security. 0x10000 - is arbitrary big number. */
202782cae269SKonstantin Komarov 		err = -EFBIG;
202882cae269SKonstantin Komarov 		goto out;
202982cae269SKonstantin Komarov 	}
203082cae269SKonstantin Komarov 
2031a81f47c4SKonstantin Komarov 	*size = t32 - sizeof(struct SECURITY_HDR);
203282cae269SKonstantin Komarov 
2033195c52bdSKari Argillander 	p = kmalloc(*size, GFP_NOFS);
203482cae269SKonstantin Komarov 	if (!p) {
203582cae269SKonstantin Komarov 		err = -ENOMEM;
203682cae269SKonstantin Komarov 		goto out;
203782cae269SKonstantin Komarov 	}
203882cae269SKonstantin Komarov 
203982cae269SKonstantin Komarov 	err = ntfs_read_run_nb(sbi, &ni->file.run,
204082cae269SKonstantin Komarov 			       le64_to_cpu(sii_e->sec_hdr.off), &d_security,
204182cae269SKonstantin Komarov 			       sizeof(d_security), NULL);
204282cae269SKonstantin Komarov 	if (err)
204382cae269SKonstantin Komarov 		goto out;
204482cae269SKonstantin Komarov 
2045a81f47c4SKonstantin Komarov 	if (memcmp(&d_security, &sii_e->sec_hdr, sizeof(d_security))) {
204682cae269SKonstantin Komarov 		err = -EINVAL;
204782cae269SKonstantin Komarov 		goto out;
204882cae269SKonstantin Komarov 	}
204982cae269SKonstantin Komarov 
205082cae269SKonstantin Komarov 	err = ntfs_read_run_nb(sbi, &ni->file.run,
205182cae269SKonstantin Komarov 			       le64_to_cpu(sii_e->sec_hdr.off) +
2052a81f47c4SKonstantin Komarov 				       sizeof(struct SECURITY_HDR),
205382cae269SKonstantin Komarov 			       p, *size, NULL);
205482cae269SKonstantin Komarov 	if (err)
205582cae269SKonstantin Komarov 		goto out;
205682cae269SKonstantin Komarov 
205782cae269SKonstantin Komarov 	*sd = p;
205882cae269SKonstantin Komarov 	p = NULL;
205982cae269SKonstantin Komarov 
206082cae269SKonstantin Komarov out:
2061195c52bdSKari Argillander 	kfree(p);
206282cae269SKonstantin Komarov 	fnd_put(fnd_sii);
206382cae269SKonstantin Komarov 	ni_unlock(ni);
206482cae269SKonstantin Komarov 
206582cae269SKonstantin Komarov 	return err;
206682cae269SKonstantin Komarov }
206782cae269SKonstantin Komarov 
206882cae269SKonstantin Komarov /*
2069e8b8e97fSKari Argillander  * ntfs_insert_security - Insert security descriptor into $Secure::SDS.
207082cae269SKonstantin Komarov  *
207182cae269SKonstantin Komarov  * SECURITY Descriptor Stream data is organized into chunks of 256K bytes
207282cae269SKonstantin Komarov  * and it contains a mirror copy of each security descriptor.  When writing
207382cae269SKonstantin Komarov  * to a security descriptor at location X, another copy will be written at
207482cae269SKonstantin Komarov  * location (X+256K).
207582cae269SKonstantin Komarov  * When writing a security descriptor that will cross the 256K boundary,
207682cae269SKonstantin Komarov  * the pointer will be advanced by 256K to skip
207782cae269SKonstantin Komarov  * over the mirror portion.
207882cae269SKonstantin Komarov  */
ntfs_insert_security(struct ntfs_sb_info * sbi,const struct SECURITY_DESCRIPTOR_RELATIVE * sd,u32 size_sd,__le32 * security_id,bool * inserted)207982cae269SKonstantin Komarov int ntfs_insert_security(struct ntfs_sb_info *sbi,
208082cae269SKonstantin Komarov 			 const struct SECURITY_DESCRIPTOR_RELATIVE *sd,
208182cae269SKonstantin Komarov 			 u32 size_sd, __le32 *security_id, bool *inserted)
208282cae269SKonstantin Komarov {
208382cae269SKonstantin Komarov 	int err, diff;
208482cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->security.ni;
208582cae269SKonstantin Komarov 	struct ntfs_index *indx_sdh = &sbi->security.index_sdh;
208682cae269SKonstantin Komarov 	struct ntfs_index *indx_sii = &sbi->security.index_sii;
208782cae269SKonstantin Komarov 	struct NTFS_DE_SDH *e;
208882cae269SKonstantin Komarov 	struct NTFS_DE_SDH sdh_e;
208982cae269SKonstantin Komarov 	struct NTFS_DE_SII sii_e;
209082cae269SKonstantin Komarov 	struct SECURITY_HDR *d_security;
2091a81f47c4SKonstantin Komarov 	u32 new_sec_size = size_sd + sizeof(struct SECURITY_HDR);
2092fa3cacf5SKari Argillander 	u32 aligned_sec_size = ALIGN(new_sec_size, 16);
209382cae269SKonstantin Komarov 	struct SECURITY_KEY hash_key;
209482cae269SKonstantin Komarov 	struct ntfs_fnd *fnd_sdh = NULL;
209582cae269SKonstantin Komarov 	const struct INDEX_ROOT *root_sdh;
209682cae269SKonstantin Komarov 	const struct INDEX_ROOT *root_sii;
209782cae269SKonstantin Komarov 	u64 mirr_off, new_sds_size;
209882cae269SKonstantin Komarov 	u32 next, left;
209982cae269SKonstantin Komarov 
210082cae269SKonstantin Komarov 	static_assert((1 << Log2OfSecurityDescriptorsBlockSize) ==
210182cae269SKonstantin Komarov 		      SecurityDescriptorsBlockSize);
210282cae269SKonstantin Komarov 
210382cae269SKonstantin Komarov 	hash_key.hash = security_hash(sd, size_sd);
210482cae269SKonstantin Komarov 	hash_key.sec_id = SECURITY_ID_INVALID;
210582cae269SKonstantin Komarov 
210682cae269SKonstantin Komarov 	if (inserted)
210782cae269SKonstantin Komarov 		*inserted = false;
210882cae269SKonstantin Komarov 	*security_id = SECURITY_ID_INVALID;
210982cae269SKonstantin Komarov 
2110e8b8e97fSKari Argillander 	/* Allocate a temporal buffer. */
2111195c52bdSKari Argillander 	d_security = kzalloc(aligned_sec_size, GFP_NOFS);
211282cae269SKonstantin Komarov 	if (!d_security)
211382cae269SKonstantin Komarov 		return -ENOMEM;
211482cae269SKonstantin Komarov 
211582cae269SKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_SECURITY);
211682cae269SKonstantin Komarov 
211782cae269SKonstantin Komarov 	fnd_sdh = fnd_get();
211882cae269SKonstantin Komarov 	if (!fnd_sdh) {
211982cae269SKonstantin Komarov 		err = -ENOMEM;
212082cae269SKonstantin Komarov 		goto out;
212182cae269SKonstantin Komarov 	}
212282cae269SKonstantin Komarov 
212382cae269SKonstantin Komarov 	root_sdh = indx_get_root(indx_sdh, ni, NULL, NULL);
212482cae269SKonstantin Komarov 	if (!root_sdh) {
212582cae269SKonstantin Komarov 		err = -EINVAL;
212682cae269SKonstantin Komarov 		goto out;
212782cae269SKonstantin Komarov 	}
212882cae269SKonstantin Komarov 
212982cae269SKonstantin Komarov 	root_sii = indx_get_root(indx_sii, ni, NULL, NULL);
213082cae269SKonstantin Komarov 	if (!root_sii) {
213182cae269SKonstantin Komarov 		err = -EINVAL;
213282cae269SKonstantin Komarov 		goto out;
213382cae269SKonstantin Komarov 	}
213482cae269SKonstantin Komarov 
213582cae269SKonstantin Komarov 	/*
2136e8b8e97fSKari Argillander 	 * Check if such security already exists.
2137e8b8e97fSKari Argillander 	 * Use "SDH" and hash -> to get the offset in "SDS".
213882cae269SKonstantin Komarov 	 */
213982cae269SKonstantin Komarov 	err = indx_find(indx_sdh, ni, root_sdh, &hash_key, sizeof(hash_key),
214082cae269SKonstantin Komarov 			&d_security->key.sec_id, &diff, (struct NTFS_DE **)&e,
214182cae269SKonstantin Komarov 			fnd_sdh);
214282cae269SKonstantin Komarov 	if (err)
214382cae269SKonstantin Komarov 		goto out;
214482cae269SKonstantin Komarov 
214582cae269SKonstantin Komarov 	while (e) {
214682cae269SKonstantin Komarov 		if (le32_to_cpu(e->sec_hdr.size) == new_sec_size) {
214782cae269SKonstantin Komarov 			err = ntfs_read_run_nb(sbi, &ni->file.run,
214882cae269SKonstantin Komarov 					       le64_to_cpu(e->sec_hdr.off),
214982cae269SKonstantin Komarov 					       d_security, new_sec_size, NULL);
215082cae269SKonstantin Komarov 			if (err)
215182cae269SKonstantin Komarov 				goto out;
215282cae269SKonstantin Komarov 
215382cae269SKonstantin Komarov 			if (le32_to_cpu(d_security->size) == new_sec_size &&
215482cae269SKonstantin Komarov 			    d_security->key.hash == hash_key.hash &&
215582cae269SKonstantin Komarov 			    !memcmp(d_security + 1, sd, size_sd)) {
2156e8b8e97fSKari Argillander 				/* Such security already exists. */
2157d6ca2d25SKonstantin Komarov 				*security_id = d_security->key.sec_id;
215882cae269SKonstantin Komarov 				err = 0;
215982cae269SKonstantin Komarov 				goto out;
216082cae269SKonstantin Komarov 			}
216182cae269SKonstantin Komarov 		}
216282cae269SKonstantin Komarov 
216382cae269SKonstantin Komarov 		err = indx_find_sort(indx_sdh, ni, root_sdh,
216482cae269SKonstantin Komarov 				     (struct NTFS_DE **)&e, fnd_sdh);
216582cae269SKonstantin Komarov 		if (err)
216682cae269SKonstantin Komarov 			goto out;
216782cae269SKonstantin Komarov 
216882cae269SKonstantin Komarov 		if (!e || e->key.hash != hash_key.hash)
216982cae269SKonstantin Komarov 			break;
217082cae269SKonstantin Komarov 	}
217182cae269SKonstantin Komarov 
2172e8b8e97fSKari Argillander 	/* Zero unused space. */
217382cae269SKonstantin Komarov 	next = sbi->security.next_off & (SecurityDescriptorsBlockSize - 1);
217482cae269SKonstantin Komarov 	left = SecurityDescriptorsBlockSize - next;
217582cae269SKonstantin Komarov 
2176e8b8e97fSKari Argillander 	/* Zero gap until SecurityDescriptorsBlockSize. */
217782cae269SKonstantin Komarov 	if (left < new_sec_size) {
2178e8b8e97fSKari Argillander 		/* Zero "left" bytes from sbi->security.next_off. */
217982cae269SKonstantin Komarov 		sbi->security.next_off += SecurityDescriptorsBlockSize + left;
218082cae269SKonstantin Komarov 	}
218182cae269SKonstantin Komarov 
2182e8b8e97fSKari Argillander 	/* Zero tail of previous security. */
218382cae269SKonstantin Komarov 	//used = ni->vfs_inode.i_size & (SecurityDescriptorsBlockSize - 1);
218482cae269SKonstantin Komarov 
218582cae269SKonstantin Komarov 	/*
218682cae269SKonstantin Komarov 	 * Example:
218782cae269SKonstantin Komarov 	 * 0x40438 == ni->vfs_inode.i_size
218882cae269SKonstantin Komarov 	 * 0x00440 == sbi->security.next_off
218982cae269SKonstantin Komarov 	 * need to zero [0x438-0x440)
219082cae269SKonstantin Komarov 	 * if (next > used) {
219182cae269SKonstantin Komarov 	 *  u32 tozero = next - used;
219282cae269SKonstantin Komarov 	 *  zero "tozero" bytes from sbi->security.next_off - tozero
219382cae269SKonstantin Komarov 	 */
219482cae269SKonstantin Komarov 
2195e8b8e97fSKari Argillander 	/* Format new security descriptor. */
219682cae269SKonstantin Komarov 	d_security->key.hash = hash_key.hash;
219782cae269SKonstantin Komarov 	d_security->key.sec_id = cpu_to_le32(sbi->security.next_id);
219882cae269SKonstantin Komarov 	d_security->off = cpu_to_le64(sbi->security.next_off);
219982cae269SKonstantin Komarov 	d_security->size = cpu_to_le32(new_sec_size);
220082cae269SKonstantin Komarov 	memcpy(d_security + 1, sd, size_sd);
220182cae269SKonstantin Komarov 
2202e8b8e97fSKari Argillander 	/* Write main SDS bucket. */
220382cae269SKonstantin Komarov 	err = ntfs_sb_write_run(sbi, &ni->file.run, sbi->security.next_off,
220463544672SKonstantin Komarov 				d_security, aligned_sec_size, 0);
220582cae269SKonstantin Komarov 
220682cae269SKonstantin Komarov 	if (err)
220782cae269SKonstantin Komarov 		goto out;
220882cae269SKonstantin Komarov 
220982cae269SKonstantin Komarov 	mirr_off = sbi->security.next_off + SecurityDescriptorsBlockSize;
221082cae269SKonstantin Komarov 	new_sds_size = mirr_off + aligned_sec_size;
221182cae269SKonstantin Komarov 
221282cae269SKonstantin Komarov 	if (new_sds_size > ni->vfs_inode.i_size) {
221382cae269SKonstantin Komarov 		err = attr_set_size(ni, ATTR_DATA, SDS_NAME,
221482cae269SKonstantin Komarov 				    ARRAY_SIZE(SDS_NAME), &ni->file.run,
221582cae269SKonstantin Komarov 				    new_sds_size, &new_sds_size, false, NULL);
221682cae269SKonstantin Komarov 		if (err)
221782cae269SKonstantin Komarov 			goto out;
221882cae269SKonstantin Komarov 	}
221982cae269SKonstantin Komarov 
2220e8b8e97fSKari Argillander 	/* Write copy SDS bucket. */
222182cae269SKonstantin Komarov 	err = ntfs_sb_write_run(sbi, &ni->file.run, mirr_off, d_security,
222263544672SKonstantin Komarov 				aligned_sec_size, 0);
222382cae269SKonstantin Komarov 	if (err)
222482cae269SKonstantin Komarov 		goto out;
222582cae269SKonstantin Komarov 
2226e8b8e97fSKari Argillander 	/* Fill SII entry. */
222782cae269SKonstantin Komarov 	sii_e.de.view.data_off =
222882cae269SKonstantin Komarov 		cpu_to_le16(offsetof(struct NTFS_DE_SII, sec_hdr));
2229a81f47c4SKonstantin Komarov 	sii_e.de.view.data_size = cpu_to_le16(sizeof(struct SECURITY_HDR));
223082cae269SKonstantin Komarov 	sii_e.de.view.res = 0;
2231a81f47c4SKonstantin Komarov 	sii_e.de.size = cpu_to_le16(sizeof(struct NTFS_DE_SII));
223282cae269SKonstantin Komarov 	sii_e.de.key_size = cpu_to_le16(sizeof(d_security->key.sec_id));
223382cae269SKonstantin Komarov 	sii_e.de.flags = 0;
223482cae269SKonstantin Komarov 	sii_e.de.res = 0;
223582cae269SKonstantin Komarov 	sii_e.sec_id = d_security->key.sec_id;
2236a81f47c4SKonstantin Komarov 	memcpy(&sii_e.sec_hdr, d_security, sizeof(struct SECURITY_HDR));
223782cae269SKonstantin Komarov 
223878ab59feSKonstantin Komarov 	err = indx_insert_entry(indx_sii, ni, &sii_e.de, NULL, NULL, 0);
223982cae269SKonstantin Komarov 	if (err)
224082cae269SKonstantin Komarov 		goto out;
224182cae269SKonstantin Komarov 
2242e8b8e97fSKari Argillander 	/* Fill SDH entry. */
224382cae269SKonstantin Komarov 	sdh_e.de.view.data_off =
224482cae269SKonstantin Komarov 		cpu_to_le16(offsetof(struct NTFS_DE_SDH, sec_hdr));
2245a81f47c4SKonstantin Komarov 	sdh_e.de.view.data_size = cpu_to_le16(sizeof(struct SECURITY_HDR));
224682cae269SKonstantin Komarov 	sdh_e.de.view.res = 0;
224782cae269SKonstantin Komarov 	sdh_e.de.size = cpu_to_le16(SIZEOF_SDH_DIRENTRY);
224882cae269SKonstantin Komarov 	sdh_e.de.key_size = cpu_to_le16(sizeof(sdh_e.key));
224982cae269SKonstantin Komarov 	sdh_e.de.flags = 0;
225082cae269SKonstantin Komarov 	sdh_e.de.res = 0;
225182cae269SKonstantin Komarov 	sdh_e.key.hash = d_security->key.hash;
225282cae269SKonstantin Komarov 	sdh_e.key.sec_id = d_security->key.sec_id;
2253a81f47c4SKonstantin Komarov 	memcpy(&sdh_e.sec_hdr, d_security, sizeof(struct SECURITY_HDR));
225482cae269SKonstantin Komarov 	sdh_e.magic[0] = cpu_to_le16('I');
225582cae269SKonstantin Komarov 	sdh_e.magic[1] = cpu_to_le16('I');
225682cae269SKonstantin Komarov 
225782cae269SKonstantin Komarov 	fnd_clear(fnd_sdh);
225882cae269SKonstantin Komarov 	err = indx_insert_entry(indx_sdh, ni, &sdh_e.de, (void *)(size_t)1,
225978ab59feSKonstantin Komarov 				fnd_sdh, 0);
226082cae269SKonstantin Komarov 	if (err)
226182cae269SKonstantin Komarov 		goto out;
226282cae269SKonstantin Komarov 
226382cae269SKonstantin Komarov 	*security_id = d_security->key.sec_id;
226482cae269SKonstantin Komarov 	if (inserted)
226582cae269SKonstantin Komarov 		*inserted = true;
226682cae269SKonstantin Komarov 
2267e8b8e97fSKari Argillander 	/* Update Id and offset for next descriptor. */
226882cae269SKonstantin Komarov 	sbi->security.next_id += 1;
226982cae269SKonstantin Komarov 	sbi->security.next_off += aligned_sec_size;
227082cae269SKonstantin Komarov 
227182cae269SKonstantin Komarov out:
227282cae269SKonstantin Komarov 	fnd_put(fnd_sdh);
227382cae269SKonstantin Komarov 	mark_inode_dirty(&ni->vfs_inode);
227482cae269SKonstantin Komarov 	ni_unlock(ni);
2275195c52bdSKari Argillander 	kfree(d_security);
227682cae269SKonstantin Komarov 
227782cae269SKonstantin Komarov 	return err;
227882cae269SKonstantin Komarov }
227982cae269SKonstantin Komarov 
228082cae269SKonstantin Komarov /*
2281e8b8e97fSKari Argillander  * ntfs_reparse_init - Load and parse $Extend/$Reparse.
228282cae269SKonstantin Komarov  */
ntfs_reparse_init(struct ntfs_sb_info * sbi)228382cae269SKonstantin Komarov int ntfs_reparse_init(struct ntfs_sb_info *sbi)
228482cae269SKonstantin Komarov {
228582cae269SKonstantin Komarov 	int err;
228682cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->reparse.ni;
228782cae269SKonstantin Komarov 	struct ntfs_index *indx = &sbi->reparse.index_r;
228882cae269SKonstantin Komarov 	struct ATTRIB *attr;
228982cae269SKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
229082cae269SKonstantin Komarov 	const struct INDEX_ROOT *root_r;
229182cae269SKonstantin Komarov 
229282cae269SKonstantin Komarov 	if (!ni)
229382cae269SKonstantin Komarov 		return 0;
229482cae269SKonstantin Komarov 
229582cae269SKonstantin Komarov 	le = NULL;
229682cae269SKonstantin Komarov 	attr = ni_find_attr(ni, NULL, &le, ATTR_ROOT, SR_NAME,
229782cae269SKonstantin Komarov 			    ARRAY_SIZE(SR_NAME), NULL, NULL);
229882cae269SKonstantin Komarov 	if (!attr) {
229982cae269SKonstantin Komarov 		err = -EINVAL;
230082cae269SKonstantin Komarov 		goto out;
230182cae269SKonstantin Komarov 	}
230282cae269SKonstantin Komarov 
230382cae269SKonstantin Komarov 	root_r = resident_data(attr);
230482cae269SKonstantin Komarov 	if (root_r->type != ATTR_ZERO ||
230582cae269SKonstantin Komarov 	    root_r->rule != NTFS_COLLATION_TYPE_UINTS) {
230682cae269SKonstantin Komarov 		err = -EINVAL;
230782cae269SKonstantin Komarov 		goto out;
230882cae269SKonstantin Komarov 	}
230982cae269SKonstantin Komarov 
231082cae269SKonstantin Komarov 	err = indx_init(indx, sbi, attr, INDEX_MUTEX_SR);
231182cae269SKonstantin Komarov 	if (err)
231282cae269SKonstantin Komarov 		goto out;
231382cae269SKonstantin Komarov 
231482cae269SKonstantin Komarov out:
231582cae269SKonstantin Komarov 	return err;
231682cae269SKonstantin Komarov }
231782cae269SKonstantin Komarov 
231882cae269SKonstantin Komarov /*
2319e8b8e97fSKari Argillander  * ntfs_objid_init - Load and parse $Extend/$ObjId.
232082cae269SKonstantin Komarov  */
ntfs_objid_init(struct ntfs_sb_info * sbi)232182cae269SKonstantin Komarov int ntfs_objid_init(struct ntfs_sb_info *sbi)
232282cae269SKonstantin Komarov {
232382cae269SKonstantin Komarov 	int err;
232482cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->objid.ni;
232582cae269SKonstantin Komarov 	struct ntfs_index *indx = &sbi->objid.index_o;
232682cae269SKonstantin Komarov 	struct ATTRIB *attr;
232782cae269SKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
232882cae269SKonstantin Komarov 	const struct INDEX_ROOT *root;
232982cae269SKonstantin Komarov 
233082cae269SKonstantin Komarov 	if (!ni)
233182cae269SKonstantin Komarov 		return 0;
233282cae269SKonstantin Komarov 
233382cae269SKonstantin Komarov 	le = NULL;
233482cae269SKonstantin Komarov 	attr = ni_find_attr(ni, NULL, &le, ATTR_ROOT, SO_NAME,
233582cae269SKonstantin Komarov 			    ARRAY_SIZE(SO_NAME), NULL, NULL);
233682cae269SKonstantin Komarov 	if (!attr) {
233782cae269SKonstantin Komarov 		err = -EINVAL;
233882cae269SKonstantin Komarov 		goto out;
233982cae269SKonstantin Komarov 	}
234082cae269SKonstantin Komarov 
234182cae269SKonstantin Komarov 	root = resident_data(attr);
234282cae269SKonstantin Komarov 	if (root->type != ATTR_ZERO ||
234382cae269SKonstantin Komarov 	    root->rule != NTFS_COLLATION_TYPE_UINTS) {
234482cae269SKonstantin Komarov 		err = -EINVAL;
234582cae269SKonstantin Komarov 		goto out;
234682cae269SKonstantin Komarov 	}
234782cae269SKonstantin Komarov 
234882cae269SKonstantin Komarov 	err = indx_init(indx, sbi, attr, INDEX_MUTEX_SO);
234982cae269SKonstantin Komarov 	if (err)
235082cae269SKonstantin Komarov 		goto out;
235182cae269SKonstantin Komarov 
235282cae269SKonstantin Komarov out:
235382cae269SKonstantin Komarov 	return err;
235482cae269SKonstantin Komarov }
235582cae269SKonstantin Komarov 
ntfs_objid_remove(struct ntfs_sb_info * sbi,struct GUID * guid)235682cae269SKonstantin Komarov int ntfs_objid_remove(struct ntfs_sb_info *sbi, struct GUID *guid)
235782cae269SKonstantin Komarov {
235882cae269SKonstantin Komarov 	int err;
235982cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->objid.ni;
236082cae269SKonstantin Komarov 	struct ntfs_index *indx = &sbi->objid.index_o;
236182cae269SKonstantin Komarov 
236282cae269SKonstantin Komarov 	if (!ni)
236382cae269SKonstantin Komarov 		return -EINVAL;
236482cae269SKonstantin Komarov 
236582cae269SKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_OBJID);
236682cae269SKonstantin Komarov 
236782cae269SKonstantin Komarov 	err = indx_delete_entry(indx, ni, guid, sizeof(*guid), NULL);
236882cae269SKonstantin Komarov 
236982cae269SKonstantin Komarov 	mark_inode_dirty(&ni->vfs_inode);
237082cae269SKonstantin Komarov 	ni_unlock(ni);
237182cae269SKonstantin Komarov 
237282cae269SKonstantin Komarov 	return err;
237382cae269SKonstantin Komarov }
237482cae269SKonstantin Komarov 
ntfs_insert_reparse(struct ntfs_sb_info * sbi,__le32 rtag,const struct MFT_REF * ref)237582cae269SKonstantin Komarov int ntfs_insert_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
237682cae269SKonstantin Komarov 			const struct MFT_REF *ref)
237782cae269SKonstantin Komarov {
237882cae269SKonstantin Komarov 	int err;
237982cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->reparse.ni;
238082cae269SKonstantin Komarov 	struct ntfs_index *indx = &sbi->reparse.index_r;
238182cae269SKonstantin Komarov 	struct NTFS_DE_R re;
238282cae269SKonstantin Komarov 
238382cae269SKonstantin Komarov 	if (!ni)
238482cae269SKonstantin Komarov 		return -EINVAL;
238582cae269SKonstantin Komarov 
238682cae269SKonstantin Komarov 	memset(&re, 0, sizeof(re));
238782cae269SKonstantin Komarov 
238882cae269SKonstantin Komarov 	re.de.view.data_off = cpu_to_le16(offsetof(struct NTFS_DE_R, zero));
238982cae269SKonstantin Komarov 	re.de.size = cpu_to_le16(sizeof(struct NTFS_DE_R));
239082cae269SKonstantin Komarov 	re.de.key_size = cpu_to_le16(sizeof(re.key));
239182cae269SKonstantin Komarov 
239282cae269SKonstantin Komarov 	re.key.ReparseTag = rtag;
239382cae269SKonstantin Komarov 	memcpy(&re.key.ref, ref, sizeof(*ref));
239482cae269SKonstantin Komarov 
239582cae269SKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_REPARSE);
239682cae269SKonstantin Komarov 
239778ab59feSKonstantin Komarov 	err = indx_insert_entry(indx, ni, &re.de, NULL, NULL, 0);
239882cae269SKonstantin Komarov 
239982cae269SKonstantin Komarov 	mark_inode_dirty(&ni->vfs_inode);
240082cae269SKonstantin Komarov 	ni_unlock(ni);
240182cae269SKonstantin Komarov 
240282cae269SKonstantin Komarov 	return err;
240382cae269SKonstantin Komarov }
240482cae269SKonstantin Komarov 
ntfs_remove_reparse(struct ntfs_sb_info * sbi,__le32 rtag,const struct MFT_REF * ref)240582cae269SKonstantin Komarov int ntfs_remove_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
240682cae269SKonstantin Komarov 			const struct MFT_REF *ref)
240782cae269SKonstantin Komarov {
240882cae269SKonstantin Komarov 	int err, diff;
240982cae269SKonstantin Komarov 	struct ntfs_inode *ni = sbi->reparse.ni;
241082cae269SKonstantin Komarov 	struct ntfs_index *indx = &sbi->reparse.index_r;
241182cae269SKonstantin Komarov 	struct ntfs_fnd *fnd = NULL;
241282cae269SKonstantin Komarov 	struct REPARSE_KEY rkey;
241382cae269SKonstantin Komarov 	struct NTFS_DE_R *re;
241482cae269SKonstantin Komarov 	struct INDEX_ROOT *root_r;
241582cae269SKonstantin Komarov 
241682cae269SKonstantin Komarov 	if (!ni)
241782cae269SKonstantin Komarov 		return -EINVAL;
241882cae269SKonstantin Komarov 
241982cae269SKonstantin Komarov 	rkey.ReparseTag = rtag;
242082cae269SKonstantin Komarov 	rkey.ref = *ref;
242182cae269SKonstantin Komarov 
242282cae269SKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_REPARSE);
242382cae269SKonstantin Komarov 
242482cae269SKonstantin Komarov 	if (rtag) {
242582cae269SKonstantin Komarov 		err = indx_delete_entry(indx, ni, &rkey, sizeof(rkey), NULL);
242682cae269SKonstantin Komarov 		goto out1;
242782cae269SKonstantin Komarov 	}
242882cae269SKonstantin Komarov 
242982cae269SKonstantin Komarov 	fnd = fnd_get();
243082cae269SKonstantin Komarov 	if (!fnd) {
243182cae269SKonstantin Komarov 		err = -ENOMEM;
243282cae269SKonstantin Komarov 		goto out1;
243382cae269SKonstantin Komarov 	}
243482cae269SKonstantin Komarov 
243582cae269SKonstantin Komarov 	root_r = indx_get_root(indx, ni, NULL, NULL);
243682cae269SKonstantin Komarov 	if (!root_r) {
243782cae269SKonstantin Komarov 		err = -EINVAL;
243882cae269SKonstantin Komarov 		goto out;
243982cae269SKonstantin Komarov 	}
244082cae269SKonstantin Komarov 
2441e8b8e97fSKari Argillander 	/* 1 - forces to ignore rkey.ReparseTag when comparing keys. */
244282cae269SKonstantin Komarov 	err = indx_find(indx, ni, root_r, &rkey, sizeof(rkey), (void *)1, &diff,
244382cae269SKonstantin Komarov 			(struct NTFS_DE **)&re, fnd);
244482cae269SKonstantin Komarov 	if (err)
244582cae269SKonstantin Komarov 		goto out;
244682cae269SKonstantin Komarov 
244782cae269SKonstantin Komarov 	if (memcmp(&re->key.ref, ref, sizeof(*ref))) {
244882cae269SKonstantin Komarov 		/* Impossible. Looks like volume corrupt? */
244982cae269SKonstantin Komarov 		goto out;
245082cae269SKonstantin Komarov 	}
245182cae269SKonstantin Komarov 
245282cae269SKonstantin Komarov 	memcpy(&rkey, &re->key, sizeof(rkey));
245382cae269SKonstantin Komarov 
245482cae269SKonstantin Komarov 	fnd_put(fnd);
245582cae269SKonstantin Komarov 	fnd = NULL;
245682cae269SKonstantin Komarov 
245782cae269SKonstantin Komarov 	err = indx_delete_entry(indx, ni, &rkey, sizeof(rkey), NULL);
245882cae269SKonstantin Komarov 	if (err)
245982cae269SKonstantin Komarov 		goto out;
246082cae269SKonstantin Komarov 
246182cae269SKonstantin Komarov out:
246282cae269SKonstantin Komarov 	fnd_put(fnd);
246382cae269SKonstantin Komarov 
246482cae269SKonstantin Komarov out1:
246582cae269SKonstantin Komarov 	mark_inode_dirty(&ni->vfs_inode);
246682cae269SKonstantin Komarov 	ni_unlock(ni);
246782cae269SKonstantin Komarov 
246882cae269SKonstantin Komarov 	return err;
246982cae269SKonstantin Komarov }
247082cae269SKonstantin Komarov 
ntfs_unmap_and_discard(struct ntfs_sb_info * sbi,CLST lcn,CLST len)247182cae269SKonstantin Komarov static inline void ntfs_unmap_and_discard(struct ntfs_sb_info *sbi, CLST lcn,
247282cae269SKonstantin Komarov 					  CLST len)
247382cae269SKonstantin Komarov {
247482cae269SKonstantin Komarov 	ntfs_unmap_meta(sbi->sb, lcn, len);
247582cae269SKonstantin Komarov 	ntfs_discard(sbi, lcn, len);
247682cae269SKonstantin Komarov }
247782cae269SKonstantin Komarov 
mark_as_free_ex(struct ntfs_sb_info * sbi,CLST lcn,CLST len,bool trim)247882cae269SKonstantin Komarov void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim)
247982cae269SKonstantin Komarov {
24808335ebe1SKonstantin Komarov 	CLST end, i, zone_len, zlen;
248182cae269SKonstantin Komarov 	struct wnd_bitmap *wnd = &sbi->used.bitmap;
2482bfbe5b31SKonstantin Komarov 	bool dirty = false;
248382cae269SKonstantin Komarov 
248482cae269SKonstantin Komarov 	down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
248582cae269SKonstantin Komarov 	if (!wnd_is_used(wnd, lcn, len)) {
2486bfbe5b31SKonstantin Komarov 		/* mark volume as dirty out of wnd->rw_lock */
2487bfbe5b31SKonstantin Komarov 		dirty = true;
248882cae269SKonstantin Komarov 
248982cae269SKonstantin Komarov 		end = lcn + len;
249082cae269SKonstantin Komarov 		len = 0;
249182cae269SKonstantin Komarov 		for (i = lcn; i < end; i++) {
249282cae269SKonstantin Komarov 			if (wnd_is_used(wnd, i, 1)) {
249382cae269SKonstantin Komarov 				if (!len)
249482cae269SKonstantin Komarov 					lcn = i;
249582cae269SKonstantin Komarov 				len += 1;
249682cae269SKonstantin Komarov 				continue;
249782cae269SKonstantin Komarov 			}
249882cae269SKonstantin Komarov 
249982cae269SKonstantin Komarov 			if (!len)
250082cae269SKonstantin Komarov 				continue;
250182cae269SKonstantin Komarov 
250282cae269SKonstantin Komarov 			if (trim)
250382cae269SKonstantin Komarov 				ntfs_unmap_and_discard(sbi, lcn, len);
250482cae269SKonstantin Komarov 
250582cae269SKonstantin Komarov 			wnd_set_free(wnd, lcn, len);
250682cae269SKonstantin Komarov 			len = 0;
250782cae269SKonstantin Komarov 		}
250882cae269SKonstantin Komarov 
250982cae269SKonstantin Komarov 		if (!len)
251082cae269SKonstantin Komarov 			goto out;
251182cae269SKonstantin Komarov 	}
251282cae269SKonstantin Komarov 
251382cae269SKonstantin Komarov 	if (trim)
251482cae269SKonstantin Komarov 		ntfs_unmap_and_discard(sbi, lcn, len);
251582cae269SKonstantin Komarov 	wnd_set_free(wnd, lcn, len);
251682cae269SKonstantin Komarov 
25178335ebe1SKonstantin Komarov 	/* append to MFT zone, if possible. */
25188335ebe1SKonstantin Komarov 	zone_len = wnd_zone_len(wnd);
25198335ebe1SKonstantin Komarov 	zlen = min(zone_len + len, sbi->zone_max);
25208335ebe1SKonstantin Komarov 
25218335ebe1SKonstantin Komarov 	if (zlen == zone_len) {
25228335ebe1SKonstantin Komarov 		/* MFT zone already has maximum size. */
25238335ebe1SKonstantin Komarov 	} else if (!zone_len) {
25248039edbaSKonstantin Komarov 		/* Create MFT zone only if 'zlen' is large enough. */
25258039edbaSKonstantin Komarov 		if (zlen == sbi->zone_max)
25268335ebe1SKonstantin Komarov 			wnd_zone_set(wnd, lcn, zlen);
25278335ebe1SKonstantin Komarov 	} else {
25288335ebe1SKonstantin Komarov 		CLST zone_lcn = wnd_zone_bit(wnd);
25298335ebe1SKonstantin Komarov 
25308335ebe1SKonstantin Komarov 		if (lcn + len == zone_lcn) {
25318335ebe1SKonstantin Komarov 			/* Append into head MFT zone. */
25328335ebe1SKonstantin Komarov 			wnd_zone_set(wnd, lcn, zlen);
25338335ebe1SKonstantin Komarov 		} else if (zone_lcn + zone_len == lcn) {
25348335ebe1SKonstantin Komarov 			/* Append into tail MFT zone. */
25358335ebe1SKonstantin Komarov 			wnd_zone_set(wnd, zone_lcn, zlen);
25368335ebe1SKonstantin Komarov 		}
25378335ebe1SKonstantin Komarov 	}
25388335ebe1SKonstantin Komarov 
253982cae269SKonstantin Komarov out:
254082cae269SKonstantin Komarov 	up_write(&wnd->rw_lock);
2541bfbe5b31SKonstantin Komarov 	if (dirty)
2542bfbe5b31SKonstantin Komarov 		ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
254382cae269SKonstantin Komarov }
254482cae269SKonstantin Komarov 
254582cae269SKonstantin Komarov /*
2546e8b8e97fSKari Argillander  * run_deallocate - Deallocate clusters.
254782cae269SKonstantin Komarov  */
run_deallocate(struct ntfs_sb_info * sbi,const struct runs_tree * run,bool trim)2548a81f47c4SKonstantin Komarov int run_deallocate(struct ntfs_sb_info *sbi, const struct runs_tree *run,
2549a81f47c4SKonstantin Komarov 		   bool trim)
255082cae269SKonstantin Komarov {
255182cae269SKonstantin Komarov 	CLST lcn, len;
255282cae269SKonstantin Komarov 	size_t idx = 0;
255382cae269SKonstantin Komarov 
255482cae269SKonstantin Komarov 	while (run_get_entry(run, idx++, NULL, &lcn, &len)) {
255582cae269SKonstantin Komarov 		if (lcn == SPARSE_LCN)
255682cae269SKonstantin Komarov 			continue;
255782cae269SKonstantin Komarov 
255882cae269SKonstantin Komarov 		mark_as_free_ex(sbi, lcn, len, trim);
255982cae269SKonstantin Komarov 	}
256082cae269SKonstantin Komarov 
256182cae269SKonstantin Komarov 	return 0;
256282cae269SKonstantin Komarov }
25631d07a9dfSDaniel Pinto 
name_has_forbidden_chars(const struct le_str * fname)25641d07a9dfSDaniel Pinto static inline bool name_has_forbidden_chars(const struct le_str *fname)
25651d07a9dfSDaniel Pinto {
25661d07a9dfSDaniel Pinto 	int i, ch;
25671d07a9dfSDaniel Pinto 
25681d07a9dfSDaniel Pinto 	/* check for forbidden chars */
25691d07a9dfSDaniel Pinto 	for (i = 0; i < fname->len; ++i) {
25701d07a9dfSDaniel Pinto 		ch = le16_to_cpu(fname->name[i]);
25711d07a9dfSDaniel Pinto 
25721d07a9dfSDaniel Pinto 		/* control chars */
25731d07a9dfSDaniel Pinto 		if (ch < 0x20)
25741d07a9dfSDaniel Pinto 			return true;
25751d07a9dfSDaniel Pinto 
25761d07a9dfSDaniel Pinto 		switch (ch) {
25771d07a9dfSDaniel Pinto 		/* disallowed by Windows */
25781d07a9dfSDaniel Pinto 		case '\\':
25791d07a9dfSDaniel Pinto 		case '/':
25801d07a9dfSDaniel Pinto 		case ':':
25811d07a9dfSDaniel Pinto 		case '*':
25821d07a9dfSDaniel Pinto 		case '?':
25831d07a9dfSDaniel Pinto 		case '<':
25841d07a9dfSDaniel Pinto 		case '>':
25851d07a9dfSDaniel Pinto 		case '|':
25861d07a9dfSDaniel Pinto 		case '\"':
25871d07a9dfSDaniel Pinto 			return true;
25881d07a9dfSDaniel Pinto 
25891d07a9dfSDaniel Pinto 		default:
25901d07a9dfSDaniel Pinto 			/* allowed char */
25911d07a9dfSDaniel Pinto 			break;
25921d07a9dfSDaniel Pinto 		}
25931d07a9dfSDaniel Pinto 	}
25941d07a9dfSDaniel Pinto 
25951d07a9dfSDaniel Pinto 	/* file names cannot end with space or . */
25961d07a9dfSDaniel Pinto 	if (fname->len > 0) {
25971d07a9dfSDaniel Pinto 		ch = le16_to_cpu(fname->name[fname->len - 1]);
25981d07a9dfSDaniel Pinto 		if (ch == ' ' || ch == '.')
25991d07a9dfSDaniel Pinto 			return true;
26001d07a9dfSDaniel Pinto 	}
26011d07a9dfSDaniel Pinto 
26021d07a9dfSDaniel Pinto 	return false;
26031d07a9dfSDaniel Pinto }
26041d07a9dfSDaniel Pinto 
is_reserved_name(const struct ntfs_sb_info * sbi,const struct le_str * fname)2605a81f47c4SKonstantin Komarov static inline bool is_reserved_name(const struct ntfs_sb_info *sbi,
26061d07a9dfSDaniel Pinto 				    const struct le_str *fname)
26071d07a9dfSDaniel Pinto {
26081d07a9dfSDaniel Pinto 	int port_digit;
26091d07a9dfSDaniel Pinto 	const __le16 *name = fname->name;
26101d07a9dfSDaniel Pinto 	int len = fname->len;
2611a81f47c4SKonstantin Komarov 	const u16 *upcase = sbi->upcase;
26121d07a9dfSDaniel Pinto 
26131d07a9dfSDaniel Pinto 	/* check for 3 chars reserved names (device names) */
26141d07a9dfSDaniel Pinto 	/* name by itself or with any extension is forbidden */
26151d07a9dfSDaniel Pinto 	if (len == 3 || (len > 3 && le16_to_cpu(name[3]) == '.'))
26161d07a9dfSDaniel Pinto 		if (!ntfs_cmp_names(name, 3, CON_NAME, 3, upcase, false) ||
26171d07a9dfSDaniel Pinto 		    !ntfs_cmp_names(name, 3, NUL_NAME, 3, upcase, false) ||
26181d07a9dfSDaniel Pinto 		    !ntfs_cmp_names(name, 3, AUX_NAME, 3, upcase, false) ||
26191d07a9dfSDaniel Pinto 		    !ntfs_cmp_names(name, 3, PRN_NAME, 3, upcase, false))
26201d07a9dfSDaniel Pinto 			return true;
26211d07a9dfSDaniel Pinto 
26221d07a9dfSDaniel Pinto 	/* check for 4 chars reserved names (port name followed by 1..9) */
26231d07a9dfSDaniel Pinto 	/* name by itself or with any extension is forbidden */
26241d07a9dfSDaniel Pinto 	if (len == 4 || (len > 4 && le16_to_cpu(name[4]) == '.')) {
26251d07a9dfSDaniel Pinto 		port_digit = le16_to_cpu(name[3]);
26261d07a9dfSDaniel Pinto 		if (port_digit >= '1' && port_digit <= '9')
26276827d50bSKonstantin Komarov 			if (!ntfs_cmp_names(name, 3, COM_NAME, 3, upcase,
26286827d50bSKonstantin Komarov 					    false) ||
26296827d50bSKonstantin Komarov 			    !ntfs_cmp_names(name, 3, LPT_NAME, 3, upcase,
26306827d50bSKonstantin Komarov 					    false))
26311d07a9dfSDaniel Pinto 				return true;
26321d07a9dfSDaniel Pinto 	}
26331d07a9dfSDaniel Pinto 
26341d07a9dfSDaniel Pinto 	return false;
26351d07a9dfSDaniel Pinto }
26361d07a9dfSDaniel Pinto 
26371d07a9dfSDaniel Pinto /*
26381d07a9dfSDaniel Pinto  * valid_windows_name - Check if a file name is valid in Windows.
26391d07a9dfSDaniel Pinto  */
valid_windows_name(struct ntfs_sb_info * sbi,const struct le_str * fname)26401d07a9dfSDaniel Pinto bool valid_windows_name(struct ntfs_sb_info *sbi, const struct le_str *fname)
26411d07a9dfSDaniel Pinto {
26421d07a9dfSDaniel Pinto 	return !name_has_forbidden_chars(fname) &&
26431d07a9dfSDaniel Pinto 	       !is_reserved_name(sbi, fname);
26441d07a9dfSDaniel Pinto }
26457832e123SKonstantin Komarov 
26467832e123SKonstantin Komarov /*
26477832e123SKonstantin Komarov  * ntfs_set_label - updates current ntfs label.
26487832e123SKonstantin Komarov  */
ntfs_set_label(struct ntfs_sb_info * sbi,u8 * label,int len)26497832e123SKonstantin Komarov int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len)
26507832e123SKonstantin Komarov {
26517832e123SKonstantin Komarov 	int err;
26527832e123SKonstantin Komarov 	struct ATTRIB *attr;
26537832e123SKonstantin Komarov 	struct ntfs_inode *ni = sbi->volume.ni;
26547832e123SKonstantin Komarov 	const u8 max_ulen = 0x80; /* TODO: use attrdef to get maximum length */
26557832e123SKonstantin Komarov 	/* Allocate PATH_MAX bytes. */
26567832e123SKonstantin Komarov 	struct cpu_str *uni = __getname();
26577832e123SKonstantin Komarov 
26587832e123SKonstantin Komarov 	if (!uni)
26597832e123SKonstantin Komarov 		return -ENOMEM;
26607832e123SKonstantin Komarov 
26617832e123SKonstantin Komarov 	err = ntfs_nls_to_utf16(sbi, label, len, uni, (PATH_MAX - 2) / 2,
26627832e123SKonstantin Komarov 				UTF16_LITTLE_ENDIAN);
26637832e123SKonstantin Komarov 	if (err < 0)
26647832e123SKonstantin Komarov 		goto out;
26657832e123SKonstantin Komarov 
26667832e123SKonstantin Komarov 	if (uni->len > max_ulen) {
26677832e123SKonstantin Komarov 		ntfs_warn(sbi->sb, "new label is too long");
26687832e123SKonstantin Komarov 		err = -EFBIG;
26697832e123SKonstantin Komarov 		goto out;
26707832e123SKonstantin Komarov 	}
26717832e123SKonstantin Komarov 
26727832e123SKonstantin Komarov 	ni_lock(ni);
26737832e123SKonstantin Komarov 
26747832e123SKonstantin Komarov 	/* Ignore any errors. */
26757832e123SKonstantin Komarov 	ni_remove_attr(ni, ATTR_LABEL, NULL, 0, false, NULL);
26767832e123SKonstantin Komarov 
26777832e123SKonstantin Komarov 	err = ni_insert_resident(ni, uni->len * sizeof(u16), ATTR_LABEL, NULL,
26787832e123SKonstantin Komarov 				 0, &attr, NULL, NULL);
26797832e123SKonstantin Komarov 	if (err < 0)
26807832e123SKonstantin Komarov 		goto unlock_out;
26817832e123SKonstantin Komarov 
26827832e123SKonstantin Komarov 	/* write new label in on-disk struct. */
26837832e123SKonstantin Komarov 	memcpy(resident_data(attr), uni->name, uni->len * sizeof(u16));
26847832e123SKonstantin Komarov 
26857832e123SKonstantin Komarov 	/* update cached value of current label. */
26867832e123SKonstantin Komarov 	if (len >= ARRAY_SIZE(sbi->volume.label))
26877832e123SKonstantin Komarov 		len = ARRAY_SIZE(sbi->volume.label) - 1;
26887832e123SKonstantin Komarov 	memcpy(sbi->volume.label, label, len);
26897832e123SKonstantin Komarov 	sbi->volume.label[len] = 0;
26907832e123SKonstantin Komarov 	mark_inode_dirty_sync(&ni->vfs_inode);
26917832e123SKonstantin Komarov 
26927832e123SKonstantin Komarov unlock_out:
26937832e123SKonstantin Komarov 	ni_unlock(ni);
26947832e123SKonstantin Komarov 
26957832e123SKonstantin Komarov 	if (!err)
26967832e123SKonstantin Komarov 		err = _ni_write_inode(&ni->vfs_inode, 0);
26977832e123SKonstantin Komarov 
26987832e123SKonstantin Komarov out:
26997832e123SKonstantin Komarov 	__putname(uni);
27007832e123SKonstantin Komarov 	return err;
27017832e123SKonstantin Komarov }