inode.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,057 行 · 第 1/5 页

C
2,057
字号
						"type 0x%x, name_len %i). "						"Please report you saw this "						"message to linux-ntfs-dev@"						"lists.sourceforge.net",						vi->i_ino, ni->type,						ni->name_len);				goto unm_err_out;			}			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 "						"(mft_no 0x%lx, type 0x%x, "						"name_len %i). Please report "						"you saw this message to "						"linux-ntfs-dev@lists."						"sourceforge.net",						vi->i_ino, ni->type,						ni->name_len);				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 ((ctx->attr->flags & ATTR_COMPRESSION_MASK)					!= ATTR_IS_COMPRESSED) {				ntfs_error(vi->i_sb, "Found unknown "						"compression method or "						"corrupt file.");				goto unm_err_out;			}			ni->itype.compressed.block_clusters = 1U <<					ctx->attr->data.non_resident.					compression_unit;			if (ctx->attr->data.non_resident.compression_unit != 4) {				ntfs_error(vi->i_sb, "Found "					"nonstandard compression unit "					"(%u instead of 4). Cannot "					"handle this. This might "					"indicate corruption so you "					"should run chkdsk.",					ctx->attr->data.non_resident.					compression_unit);				err = -EOPNOTSUPP;				goto unm_err_out;			}			ni->itype.compressed.block_size = 1U << (					ctx->attr->data.non_resident.					compression_unit +					vol->cluster_size_bits);			ni->itype.compressed.block_size_bits = ffs(				ni->itype.compressed.block_size) - 1;		}		if (ctx->attr->flags & ATTR_IS_ENCRYPTED) {			if (ctx->attr->flags & ATTR_COMPRESSION_MASK) {				ntfs_error(vi->i_sb, "Found encrypted "						"and compressed data.");				goto unm_err_out;			}			if (NInoMstProtected(ni)) {				ntfs_error(vi->i_sb, "Found mst protected "						"attribute but the attribute "						"is encrypted (mft_no 0x%lx, "						"type 0x%x, name_len %i). "						"Please report you saw this "						"message to linux-ntfs-dev@"						"lists.sourceforge.net",						vi->i_ino, ni->type,						ni->name_len);				goto unm_err_out;			}			NInoSetEncrypted(ni);		}		if (ctx->attr->flags & ATTR_IS_SPARSE) {			if (NInoMstProtected(ni)) {				ntfs_error(vi->i_sb, "Found mst protected "						"attribute but the attribute "						"is sparse (mft_no 0x%lx, "						"type 0x%x, name_len %i). "						"Please report you saw this "						"message to linux-ntfs-dev@"						"lists.sourceforge.net",						vi->i_ino, ni->type,						ni->name_len);				goto unm_err_out;			}			NInoSetSparse(ni);		}		if (ctx->attr->data.non_resident.lowest_vcn) {			ntfs_error(vi->i_sb, "First extent of attribute has "					"non-zero lowest_vcn. Inode is "					"corrupt. You should run chkdsk.");			goto unm_err_out;		}		/* Setup all the sizes. */		vi->i_size = sle64_to_cpu(				ctx->attr->data.non_resident.data_size);		ni->initialized_size = sle64_to_cpu(				ctx->attr->data.non_resident.initialized_size);		ni->allocated_size = sle64_to_cpu(				ctx->attr->data.non_resident.allocated_size);		if (NInoCompressed(ni)) {			ni->itype.compressed.size = sle64_to_cpu(					ctx->attr->data.non_resident.					compressed_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))		vi->i_blocks = ni->allocated_size >> 9;	else		vi->i_blocks = ni->itype.compressed.size >> 9;	/*	 * Make sure the base inode doesn't 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(vi->i_sb, "Failed with error code %i while reading "			"attribute inode (mft_no 0x%lx, type 0x%x, name_len "			"%i.", -err, vi->i_ino, ni->type, ni->name_len);	make_bad_inode(vi);	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){	ntfs_volume *vol = NTFS_SB(vi->i_sb);	ntfs_inode *ni, *base_ni, *bni;	struct inode *bvi;	MFT_RECORD *m;	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_blksize	= base_vi->i_blksize;	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;	}	/* Set up the state. */	if (ctx->attr->non_resident) {		ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is not resident.  "				"Not allowed.");		goto unm_err_out;	}	/* Compressed/encrypted/sparse index root is not allowed. */	if (ctx->attr->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED |			ATTR_IS_SPARSE)) {		ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index "				"root attribute.  Not allowed.");		goto unm_err_out;	}	ir = (INDEX_ROOT*)((u8*)ctx->attr +			le16_to_cpu(ctx->attr->data.resident.value_offset));	ir_end = (u8*)ir + le32_to_cpu(ctx->attr->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).  "				"Not allowed.", 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;	}	if (!ctx->attr->non_resident) {		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "				"resident.");		goto unm_err_out;	}	if (ctx->attr->flags & ATTR_IS_ENCRYPTED) {		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "				"encrypted.");		goto unm_err_out;	}	if (ctx->attr->flags & ATTR_IS_SPARSE) {		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is sparse.");		goto unm_err_out;	}	if (ctx->attr->flags & ATTR_COMPRESSION_MASK) {		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "				"compressed.");		goto unm_err_out;	}	if (ctx->attr->data.non_resident.lowest_vcn) {		ntfs_error(vi->i_sb, "First extent of $INDEX_ALLOCATION "				"attribute has non zero lowest_vcn.  Inode is "				"corrupt. You should run chkdsk.");		goto unm_err_out;	}	vi->i_size = sle64_to_cpu(ctx->attr->data.non_resident.data_size);	ni->initialized_size = sle64_to_cpu(			ctx->attr->data.non_resident.initialized_size);	ni->allocated_size = sle64_to_cpu(			ctx->attr->data.non_resident.allocated_size);	/*	 * We are done with the mft record, so we release it.  Otherwise	 * we would deadlock in ntfs_attr_iget().	 */	ntfs_attr_put_search_ctx(ctx);	unmap_mft_record(base_ni);	m = NULL;	ctx = NULL;	/* Get the index bitmap attribute inode. */	bvi = ntfs_attr_iget(base_vi, AT_BITMAP, ni->name, ni->name_len);	if (IS_ERR(bvi)) {		ntfs_error(vi->i_sb, "Failed to get bitmap attribute.");		err = PTR_ERR(bvi);		goto unm_err_out;	}	bni = NTFS_I(bvi);	if (NInoCompressed(bni) || NInoEncrypted(bni) ||			NInoSparse(bni)) {		ntfs_error(vi->i_sb, "$BITMAP attribute is compressed "				"and/or encrypted and/or sparse.");		goto iput_unm_err_out;	}	/* Consistency check bitmap size vs. index allocation size. */	if ((bvi->i_size << 3) < (vi->i_size >>			ni->itype.index.block_size_bits)) {		ntfs_error(vi->i_sb, "Index bitmap too small (0x%llx) "				"for index allocation (0x%llx).",				bvi->i_size << 3, vi->i_size);		goto iput_unm_err_out;	}	ni->itype.index.bmp_ino = bvi;skip_large_index_stuff:	/* Setup the operations for this index inode. */	vi->i_op = NULL;	vi->i_fop = NULL;	vi->i_mapping->a_ops = &ntfs_mst_aops;	vi->i_blocks = ni->allocated_size >> 9;	/*	 * Make sure the base inode doesn't go away and attach it to the	 * index inode.	 */	igrab(base_vi);	ni->ext.base_ntfs_ino = base_ni;	ni->nr_extents = -1;	ntfs_debug("Done.");	return 0;iput_unm_err_out:	iput(bvi);unm_err_out:	if (!err)		err = -EIO;	if (ctx)		ntfs_attr_put_search_ctx(ctx);	if (m)		unmap_mft_record(base_ni);err_out:

⌨️ 快捷键说明

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