⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Set inode type to zero but preserve permissions. */	vi->i_mode	= base_vi->i_mode & ~S_IFMT;	m = map_mft_record(base_ni);	if (IS_ERR(m)) {		err = PTR_ERR(m);		goto err_out;	}	ctx = ntfs_attr_get_search_ctx(base_ni, m);	if (!ctx) {		err = -ENOMEM;		goto unm_err_out;	}	/* Find the attribute. */	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,			CASE_SENSITIVE, 0, NULL, 0, ctx);	if (unlikely(err))		goto unm_err_out;	a = ctx->attr;	if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {		if (a->flags & ATTR_COMPRESSION_MASK) {			NInoSetCompressed(ni);			if ((ni->type != AT_DATA) || (ni->type == AT_DATA &&					ni->name_len)) {				ntfs_error(vi->i_sb, "Found compressed "						"non-data or named data "						"attribute.  Please report "						"you saw this message to "						"linux-ntfs-dev@lists."						"sourceforge.net");				goto unm_err_out;			}			if (vol->cluster_size > 4096) {				ntfs_error(vi->i_sb, "Found compressed "						"attribute but compression is "						"disabled due to cluster size "						"(%i) > 4kiB.",						vol->cluster_size);				goto unm_err_out;			}			if ((a->flags & ATTR_COMPRESSION_MASK) !=					ATTR_IS_COMPRESSED) {				ntfs_error(vi->i_sb, "Found unknown "						"compression method.");				goto unm_err_out;			}		}		/*		 * The compressed/sparse flag set in an index root just means		 * to compress all files.		 */		if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {			ntfs_error(vi->i_sb, "Found mst protected attribute "					"but the attribute is %s.  Please "					"report you saw this message to "					"linux-ntfs-dev@lists.sourceforge.net",					NInoCompressed(ni) ? "compressed" :					"sparse");			goto unm_err_out;		}		if (a->flags & ATTR_IS_SPARSE)			NInoSetSparse(ni);	}	if (a->flags & ATTR_IS_ENCRYPTED) {		if (NInoCompressed(ni)) {			ntfs_error(vi->i_sb, "Found encrypted and compressed "					"data.");			goto unm_err_out;		}		/*		 * The encryption flag set in an index root just means to		 * encrypt all files.		 */		if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {			ntfs_error(vi->i_sb, "Found mst protected attribute "					"but the attribute is encrypted.  "					"Please report you saw this message "					"to linux-ntfs-dev@lists.sourceforge."					"net");			goto unm_err_out;		}		if (ni->type != AT_DATA) {			ntfs_error(vi->i_sb, "Found encrypted non-data "					"attribute.");			goto unm_err_out;		}		NInoSetEncrypted(ni);	}	if (!a->non_resident) {		/* Ensure the attribute name is placed before the value. */		if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >=				le16_to_cpu(a->data.resident.value_offset)))) {			ntfs_error(vol->sb, "Attribute name is placed after "					"the attribute value.");			goto unm_err_out;		}		if (NInoMstProtected(ni)) {			ntfs_error(vi->i_sb, "Found mst protected attribute "					"but the attribute is resident.  "					"Please report you saw this message to "					"linux-ntfs-dev@lists.sourceforge.net");			goto unm_err_out;		}		vi->i_size = ni->initialized_size = le32_to_cpu(				a->data.resident.value_length);		ni->allocated_size = le32_to_cpu(a->length) -				le16_to_cpu(a->data.resident.value_offset);		if (vi->i_size > ni->allocated_size) {			ntfs_error(vi->i_sb, "Resident attribute is corrupt "					"(size exceeds allocation).");			goto unm_err_out;		}	} else {		NInoSetNonResident(ni);		/*		 * Ensure the attribute name is placed before the mapping pairs		 * array.		 */		if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >=				le16_to_cpu(				a->data.non_resident.mapping_pairs_offset)))) {			ntfs_error(vol->sb, "Attribute name is placed after "					"the mapping pairs array.");			goto unm_err_out;		}		if (NInoCompressed(ni) || NInoSparse(ni)) {			if (NInoCompressed(ni) && a->data.non_resident.					compression_unit != 4) {				ntfs_error(vi->i_sb, "Found non-standard "						"compression unit (%u instead "						"of 4).  Cannot handle this.",						a->data.non_resident.						compression_unit);				err = -EOPNOTSUPP;				goto unm_err_out;			}			if (a->data.non_resident.compression_unit) {				ni->itype.compressed.block_size = 1U <<						(a->data.non_resident.						compression_unit +						vol->cluster_size_bits);				ni->itype.compressed.block_size_bits =						ffs(ni->itype.compressed.						block_size) - 1;				ni->itype.compressed.block_clusters = 1U <<						a->data.non_resident.						compression_unit;			} else {				ni->itype.compressed.block_size = 0;				ni->itype.compressed.block_size_bits = 0;				ni->itype.compressed.block_clusters = 0;			}			ni->itype.compressed.size = sle64_to_cpu(					a->data.non_resident.compressed_size);		}		if (a->data.non_resident.lowest_vcn) {			ntfs_error(vi->i_sb, "First extent of attribute has "					"non-zero lowest_vcn.");			goto unm_err_out;		}		vi->i_size = sle64_to_cpu(a->data.non_resident.data_size);		ni->initialized_size = sle64_to_cpu(				a->data.non_resident.initialized_size);		ni->allocated_size = sle64_to_cpu(				a->data.non_resident.allocated_size);	}	/* Setup the operations for this attribute inode. */	vi->i_op = NULL;	vi->i_fop = NULL;	if (NInoMstProtected(ni))		vi->i_mapping->a_ops = &ntfs_mst_aops;	else		vi->i_mapping->a_ops = &ntfs_aops;	if ((NInoCompressed(ni) || NInoSparse(ni)) && ni->type != AT_INDEX_ROOT)		vi->i_blocks = ni->itype.compressed.size >> 9;	else		vi->i_blocks = ni->allocated_size >> 9;	/*	 * Make sure the base inode does not go away and attach it to the	 * attribute inode.	 */	igrab(base_vi);	ni->ext.base_ntfs_ino = base_ni;	ni->nr_extents = -1;	ntfs_attr_put_search_ctx(ctx);	unmap_mft_record(base_ni);	ntfs_debug("Done.");	return 0;unm_err_out:	if (!err)		err = -EIO;	if (ctx)		ntfs_attr_put_search_ctx(ctx);	unmap_mft_record(base_ni);err_out:	ntfs_error(vol->sb, "Failed with error code %i while reading attribute "			"inode (mft_no 0x%lx, type 0x%x, name_len %i).  "			"Marking corrupt inode and base inode 0x%lx as bad.  "			"Run chkdsk.", err, vi->i_ino, ni->type, ni->name_len,			base_vi->i_ino);	make_bad_inode(vi);	if (err != -ENOMEM)		NVolSetErrors(vol);	return err;}/** * ntfs_read_locked_index_inode - read an index inode from its base inode * @base_vi:	base inode * @vi:		index inode to read * * ntfs_read_locked_index_inode() is called from ntfs_index_iget() to read the * index inode described by @vi into memory from the base mft record described * by @base_ni. * * ntfs_read_locked_index_inode() maps, pins and locks the base inode for * reading and looks up the attributes relating to the index described by @vi * before setting up the necessary fields in @vi as well as initializing the * ntfs inode. * * Note, index inodes are essentially attribute inodes (NInoAttr() is true) * with the attribute type set to AT_INDEX_ALLOCATION.  Apart from that, they * are setup like directory inodes since directories are a special case of * indices ao they need to be treated in much the same way.  Most importantly, * for small indices the index allocation attribute might not actually exist. * However, the index root attribute always exists but this does not need to * have an inode associated with it and this is why we define a new inode type * index.  Also, like for directories, we need to have an attribute inode for * the bitmap attribute corresponding to the index allocation attribute and we * can store this in the appropriate field of the inode, just like we do for * normal directory inodes. * * Q: What locks are held when the function is called? * A: i_state has I_LOCK set, hence the inode is locked, also *    i_count is set to 1, so it is not going to go away * * Return 0 on success and -errno on error.  In the error case, the inode will * have had make_bad_inode() executed on it. */static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi){	loff_t bvi_size;	ntfs_volume *vol = NTFS_SB(vi->i_sb);	ntfs_inode *ni, *base_ni, *bni;	struct inode *bvi;	MFT_RECORD *m;	ATTR_RECORD *a;	ntfs_attr_search_ctx *ctx;	INDEX_ROOT *ir;	u8 *ir_end, *index_end;	int err = 0;	ntfs_debug("Entering for i_ino 0x%lx.", vi->i_ino);	ntfs_init_big_inode(vi);	ni	= NTFS_I(vi);	base_ni = NTFS_I(base_vi);	/* Just mirror the values from the base inode. */	vi->i_version	= base_vi->i_version;	vi->i_uid	= base_vi->i_uid;	vi->i_gid	= base_vi->i_gid;	vi->i_nlink	= base_vi->i_nlink;	vi->i_mtime	= base_vi->i_mtime;	vi->i_ctime	= base_vi->i_ctime;	vi->i_atime	= base_vi->i_atime;	vi->i_generation = ni->seq_no = base_ni->seq_no;	/* Set inode type to zero but preserve permissions. */	vi->i_mode	= base_vi->i_mode & ~S_IFMT;	/* Map the mft record for the base inode. */	m = map_mft_record(base_ni);	if (IS_ERR(m)) {		err = PTR_ERR(m);		goto err_out;	}	ctx = ntfs_attr_get_search_ctx(base_ni, m);	if (!ctx) {		err = -ENOMEM;		goto unm_err_out;	}	/* Find the index root attribute. */	err = ntfs_attr_lookup(AT_INDEX_ROOT, ni->name, ni->name_len,			CASE_SENSITIVE, 0, NULL, 0, ctx);	if (unlikely(err)) {		if (err == -ENOENT)			ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is "					"missing.");		goto unm_err_out;	}	a = ctx->attr;	/* Set up the state. */	if (unlikely(a->non_resident)) {		ntfs_error(vol->sb, "$INDEX_ROOT attribute is not resident.");		goto unm_err_out;	}	/* Ensure the attribute name is placed before the value. */	if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >=			le16_to_cpu(a->data.resident.value_offset)))) {		ntfs_error(vol->sb, "$INDEX_ROOT attribute name is placed "				"after the attribute value.");		goto unm_err_out;	}	/*	 * Compressed/encrypted/sparse index root is not allowed, except for	 * directories of course but those are not dealt with here.	 */	if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED |			ATTR_IS_SPARSE)) {		ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index "				"root attribute.");		goto unm_err_out;	}	ir = (INDEX_ROOT*)((u8*)a + le16_to_cpu(a->data.resident.value_offset));	ir_end = (u8*)ir + le32_to_cpu(a->data.resident.value_length);	if (ir_end > (u8*)ctx->mrec + vol->mft_record_size) {		ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is corrupt.");		goto unm_err_out;	}	index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);	if (index_end > ir_end) {		ntfs_error(vi->i_sb, "Index is corrupt.");		goto unm_err_out;	}	if (ir->type) {		ntfs_error(vi->i_sb, "Index type is not 0 (type is 0x%x).",				le32_to_cpu(ir->type));		goto unm_err_out;	}	ni->itype.index.collation_rule = ir->collation_rule;	ntfs_debug("Index collation rule is 0x%x.",			le32_to_cpu(ir->collation_rule));	ni->itype.index.block_size = le32_to_cpu(ir->index_block_size);	if (ni->itype.index.block_size & (ni->itype.index.block_size - 1)) {		ntfs_error(vi->i_sb, "Index block size (%u) is not a power of "				"two.", ni->itype.index.block_size);		goto unm_err_out;	}	if (ni->itype.index.block_size > PAGE_CACHE_SIZE) {		ntfs_error(vi->i_sb, "Index block size (%u) > PAGE_CACHE_SIZE "				"(%ld) is not supported.  Sorry.",				ni->itype.index.block_size, PAGE_CACHE_SIZE);		err = -EOPNOTSUPP;		goto unm_err_out;	}	if (ni->itype.index.block_size < NTFS_BLOCK_SIZE) {		ntfs_error(vi->i_sb, "Index block size (%u) < NTFS_BLOCK_SIZE "				"(%i) is not supported.  Sorry.",				ni->itype.index.block_size, NTFS_BLOCK_SIZE);		err = -EOPNOTSUPP;		goto unm_err_out;	}	ni->itype.index.block_size_bits = ffs(ni->itype.index.block_size) - 1;	/* Determine the size of a vcn in the index. */	if (vol->cluster_size <= ni->itype.index.block_size) {		ni->itype.index.vcn_size = vol->cluster_size;		ni->itype.index.vcn_size_bits = vol->cluster_size_bits;	} else {		ni->itype.index.vcn_size = vol->sector_size;		ni->itype.index.vcn_size_bits = vol->sector_size_bits;	}	/* Check for presence of index allocation attribute. */	if (!(ir->index.flags & LARGE_INDEX)) {		/* No index allocation. */		vi->i_size = ni->initialized_size = ni->allocated_size = 0;		/* We are done with the mft record, so we release it. */		ntfs_attr_put_search_ctx(ctx);		unmap_mft_record(base_ni);		m = NULL;		ctx = NULL;		goto skip_large_index_stuff;	} /* LARGE_INDEX:  Index allocation present.  Setup state. */	NInoSetIndexAllocPresent(ni);	/* Find index allocation attribute. */	ntfs_attr_reinit_search_ctx(ctx);	err = ntfs_attr_lookup(AT_INDEX_ALLOCATION, ni->name, ni->name_len,			CASE_SENSITIVE, 0, NULL, 0, ctx);	if (unlikely(err)) {		if (err == -ENOENT)			ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "					"not present but $INDEX_ROOT "					"indicated it is.");		else			ntfs_error(vi->i_sb, "Failed to lookup "					"$INDEX_ALLOCATION attribute.");		goto unm_err_out;	}	a = ctx->attr;	if (!a->non_resident) {		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "				"resident.");		goto unm_err_out;	}	/*	 * Ensure the attribute name is placed before the mapping pairs array.	 */	if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >=			le16_to_cpu(			a->data.non_resident.mapping_pairs_offset)))) {		ntfs_error(vol->sb, "$INDEX_ALLOCATION attribute name is "				"placed after the mapping pairs array.");		goto unm_err_out;	}	if (a->flags & ATTR_IS_ENCRYPTED) {		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "				"encrypted.");		goto unm_err_out;	}	if (a->flags & ATTR_IS_SPARSE) {		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is sparse.");		goto unm_err_out;	}	if (a->flags & ATTR_COMPRESSION_MASK) {		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -