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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * is still mapped. Teach this nesting to the lock validator by creating * a separate class for nested inode's mrec_lock's: */static struct lock_class_key extent_inode_mrec_lock_key;inline ntfs_inode *ntfs_new_extent_inode(struct super_block *sb,		unsigned long mft_no){	ntfs_inode *ni = ntfs_alloc_extent_inode();	ntfs_debug("Entering.");	if (likely(ni != NULL)) {		__ntfs_init_inode(sb, ni);		lockdep_set_class(&ni->mrec_lock, &extent_inode_mrec_lock_key);		ni->mft_no = mft_no;		ni->type = AT_UNUSED;		ni->name = NULL;		ni->name_len = 0;	}	return ni;}/** * ntfs_is_extended_system_file - check if a file is in the $Extend directory * @ctx:	initialized attribute search context * * Search all file name attributes in the inode described by the attribute * search context @ctx and check if any of the names are in the $Extend system * directory. * * Return values: *	   1: file is in $Extend directory *	   0: file is not in $Extend directory *    -errno: failed to determine if the file is in the $Extend directory */static int ntfs_is_extended_system_file(ntfs_attr_search_ctx *ctx){	int nr_links, err;	/* Restart search. */	ntfs_attr_reinit_search_ctx(ctx);	/* Get number of hard links. */	nr_links = le16_to_cpu(ctx->mrec->link_count);	/* Loop through all hard links. */	while (!(err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0,			ctx))) {		FILE_NAME_ATTR *file_name_attr;		ATTR_RECORD *attr = ctx->attr;		u8 *p, *p2;		nr_links--;		/*		 * Maximum sanity checking as we are called on an inode that		 * we suspect might be corrupt.		 */		p = (u8*)attr + le32_to_cpu(attr->length);		if (p < (u8*)ctx->mrec || (u8*)p > (u8*)ctx->mrec +				le32_to_cpu(ctx->mrec->bytes_in_use)) {err_corrupt_attr:			ntfs_error(ctx->ntfs_ino->vol->sb, "Corrupt file name "					"attribute. You should run chkdsk.");			return -EIO;		}		if (attr->non_resident) {			ntfs_error(ctx->ntfs_ino->vol->sb, "Non-resident file "					"name. You should run chkdsk.");			return -EIO;		}		if (attr->flags) {			ntfs_error(ctx->ntfs_ino->vol->sb, "File name with "					"invalid flags. You should run "					"chkdsk.");			return -EIO;		}		if (!(attr->data.resident.flags & RESIDENT_ATTR_IS_INDEXED)) {			ntfs_error(ctx->ntfs_ino->vol->sb, "Unindexed file "					"name. You should run chkdsk.");			return -EIO;		}		file_name_attr = (FILE_NAME_ATTR*)((u8*)attr +				le16_to_cpu(attr->data.resident.value_offset));		p2 = (u8*)attr + le32_to_cpu(attr->data.resident.value_length);		if (p2 < (u8*)attr || p2 > p)			goto err_corrupt_attr;		/* This attribute is ok, but is it in the $Extend directory? */		if (MREF_LE(file_name_attr->parent_directory) == FILE_Extend)			return 1;	/* YES, it's an extended system file. */	}	if (unlikely(err != -ENOENT))		return err;	if (unlikely(nr_links)) {		ntfs_error(ctx->ntfs_ino->vol->sb, "Inode hard link count "				"doesn't match number of name attributes. You "				"should run chkdsk.");		return -EIO;	}	return 0;	/* NO, it is not an extended system file. */}/** * ntfs_read_locked_inode - read an inode from its device * @vi:		inode to read * * ntfs_read_locked_inode() is called from ntfs_iget() to read the inode * described by @vi into memory from the device. * * The only fields in @vi that we need to/can look at when the function is * called are i_sb, pointing to the mounted device's super block, and i_ino, * the number of the inode to load. * * ntfs_read_locked_inode() maps, pins and locks the mft record number i_ino * for reading and sets up the necessary @vi fields as well as initializing * the ntfs inode. * * 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 *    i_flags is set to 0 and we have no business touching it.  Only an ioctl() *    is allowed to write to them. We should of course be honouring them but *    we need to do that using the IS_* macros defined in include/linux/fs.h. *    In any case ntfs_read_locked_inode() has nothing to do with i_flags. * * 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_inode(struct inode *vi){	ntfs_volume *vol = NTFS_SB(vi->i_sb);	ntfs_inode *ni;	struct inode *bvi;	MFT_RECORD *m;	ATTR_RECORD *a;	STANDARD_INFORMATION *si;	ntfs_attr_search_ctx *ctx;	int err = 0;	ntfs_debug("Entering for i_ino 0x%lx.", vi->i_ino);	/* Setup the generic vfs inode parts now. */	/*	 * This is for checking whether an inode has changed w.r.t. a file so	 * that the file can be updated if necessary (compare with f_version).	 */	vi->i_version = 1;	vi->i_uid = vol->uid;	vi->i_gid = vol->gid;	vi->i_mode = 0;	/*	 * Initialize the ntfs specific part of @vi special casing	 * FILE_MFT which we need to do at mount time.	 */	if (vi->i_ino != FILE_MFT)		ntfs_init_big_inode(vi);	ni = NTFS_I(vi);	m = map_mft_record(ni);	if (IS_ERR(m)) {		err = PTR_ERR(m);		goto err_out;	}	ctx = ntfs_attr_get_search_ctx(ni, m);	if (!ctx) {		err = -ENOMEM;		goto unm_err_out;	}	if (!(m->flags & MFT_RECORD_IN_USE)) {		ntfs_error(vi->i_sb, "Inode is not in use!");		goto unm_err_out;	}	if (m->base_mft_record) {		ntfs_error(vi->i_sb, "Inode is an extent inode!");		goto unm_err_out;	}	/* Transfer information from mft record into vfs and ntfs inodes. */	vi->i_generation = ni->seq_no = le16_to_cpu(m->sequence_number);	/*	 * FIXME: Keep in mind that link_count is two for files which have both	 * a long file name and a short file name as separate entries, so if	 * we are hiding short file names this will be too high. Either we need	 * to account for the short file names by subtracting them or we need	 * to make sure we delete files even though i_nlink is not zero which	 * might be tricky due to vfs interactions. Need to think about this	 * some more when implementing the unlink command.	 */	vi->i_nlink = le16_to_cpu(m->link_count);	/*	 * FIXME: Reparse points can have the directory bit set even though	 * they would be S_IFLNK. Need to deal with this further below when we	 * implement reparse points / symbolic links but it will do for now.	 * Also if not a directory, it could be something else, rather than	 * a regular file. But again, will do for now.	 */	/* Everyone gets all permissions. */	vi->i_mode |= S_IRWXUGO;	/* If read-only, noone gets write permissions. */	if (IS_RDONLY(vi))		vi->i_mode &= ~S_IWUGO;	if (m->flags & MFT_RECORD_IS_DIRECTORY) {		vi->i_mode |= S_IFDIR;		/*		 * Apply the directory permissions mask set in the mount		 * options.		 */		vi->i_mode &= ~vol->dmask;		/* Things break without this kludge! */		if (vi->i_nlink > 1)			vi->i_nlink = 1;	} else {		vi->i_mode |= S_IFREG;		/* Apply the file permissions mask set in the mount options. */		vi->i_mode &= ~vol->fmask;	}	/*	 * Find the standard information attribute in the mft record. At this	 * stage we haven't setup the attribute list stuff yet, so this could	 * in fact fail if the standard information is in an extent record, but	 * I don't think this actually ever happens.	 */	err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0, 0, 0, NULL, 0,			ctx);	if (unlikely(err)) {		if (err == -ENOENT) {			/*			 * TODO: We should be performing a hot fix here (if the			 * recover mount option is set) by creating a new			 * attribute.			 */			ntfs_error(vi->i_sb, "$STANDARD_INFORMATION attribute "					"is missing.");		}		goto unm_err_out;	}	a = ctx->attr;	/* Get the standard information attribute value. */	si = (STANDARD_INFORMATION*)((u8*)a +			le16_to_cpu(a->data.resident.value_offset));	/* Transfer information from the standard information into vi. */	/*	 * Note: The i_?times do not quite map perfectly onto the NTFS times,	 * but they are close enough, and in the end it doesn't really matter	 * that much...	 */	/*	 * mtime is the last change of the data within the file. Not changed	 * when only metadata is changed, e.g. a rename doesn't affect mtime.	 */	vi->i_mtime = ntfs2utc(si->last_data_change_time);	/*	 * ctime is the last change of the metadata of the file. This obviously	 * always changes, when mtime is changed. ctime can be changed on its	 * own, mtime is then not changed, e.g. when a file is renamed.	 */	vi->i_ctime = ntfs2utc(si->last_mft_change_time);	/*	 * Last access to the data within the file. Not changed during a rename	 * for example but changed whenever the file is written to.	 */	vi->i_atime = ntfs2utc(si->last_access_time);	/* Find the attribute list attribute if present. */	ntfs_attr_reinit_search_ctx(ctx);	err = ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx);	if (err) {		if (unlikely(err != -ENOENT)) {			ntfs_error(vi->i_sb, "Failed to lookup attribute list "					"attribute.");			goto unm_err_out;		}	} else /* if (!err) */ {		if (vi->i_ino == FILE_MFT)			goto skip_attr_list_load;		ntfs_debug("Attribute list found in inode 0x%lx.", vi->i_ino);		NInoSetAttrList(ni);		a = ctx->attr;		if (a->flags & ATTR_COMPRESSION_MASK) {			ntfs_error(vi->i_sb, "Attribute list attribute is "					"compressed.");			goto unm_err_out;		}		if (a->flags & ATTR_IS_ENCRYPTED ||				a->flags & ATTR_IS_SPARSE) {			if (a->non_resident) {				ntfs_error(vi->i_sb, "Non-resident attribute "						"list attribute is encrypted/"						"sparse.");				goto unm_err_out;			}			ntfs_warning(vi->i_sb, "Resident attribute list "					"attribute in inode 0x%lx is marked "					"encrypted/sparse which is not true.  "					"However, Windows allows this and "					"chkdsk does not detect or correct it "					"so we will just ignore the invalid "					"flags and pretend they are not set.",					vi->i_ino);		}		/* Now allocate memory for the attribute list. */		ni->attr_list_size = (u32)ntfs_attr_size(a);		ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size);		if (!ni->attr_list) {			ntfs_error(vi->i_sb, "Not enough memory to allocate "					"buffer for attribute list.");			err = -ENOMEM;			goto unm_err_out;		}		if (a->non_resident) {			NInoSetAttrListNonResident(ni);			if (a->data.non_resident.lowest_vcn) {				ntfs_error(vi->i_sb, "Attribute list has non "						"zero lowest_vcn.");				goto unm_err_out;			}			/*			 * Setup the runlist. No need for locking as we have			 * exclusive access to the inode at this time.			 */			ni->attr_list_rl.rl = ntfs_mapping_pairs_decompress(vol,					a, NULL);			if (IS_ERR(ni->attr_list_rl.rl)) {				err = PTR_ERR(ni->attr_list_rl.rl);				ni->attr_list_rl.rl = NULL;				ntfs_error(vi->i_sb, "Mapping pairs "						"decompression failed.");				goto unm_err_out;			}			/* Now load the attribute list. */			if ((err = load_attribute_list(vol, &ni->attr_list_rl,					ni->attr_list, ni->attr_list_size,					sle64_to_cpu(a->data.non_resident.					initialized_size)))) {				ntfs_error(vi->i_sb, "Failed to load "						"attribute list attribute.");				goto unm_err_out;			}		} else /* if (!a->non_resident) */ {			if ((u8*)a + le16_to_cpu(a->data.resident.value_offset)					+ le32_to_cpu(					a->data.resident.value_length) >					(u8*)ctx->mrec + vol->mft_record_size) {				ntfs_error(vi->i_sb, "Corrupt attribute list "						"in inode.");				goto unm_err_out;			}			/* Now copy the attribute list. */			memcpy(ni->attr_list, (u8*)a + le16_to_cpu(					a->data.resident.value_offset),					le32_to_cpu(					a->data.resident.value_length));		}	}skip_attr_list_load:	/*	 * If an attribute list is present we now have the attribute list value	 * in ntfs_ino->attr_list and it is ntfs_ino->attr_list_size bytes.	 */	if (S_ISDIR(vi->i_mode)) {		loff_t bvi_size;		ntfs_inode *bni;		INDEX_ROOT *ir;		u8 *ir_end, *index_end;		/* It is a directory, find index root attribute. */		ntfs_attr_reinit_search_ctx(ctx);		err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE,				0, NULL, 0, ctx);		if (unlikely(err)) {			if (err == -ENOENT) {				// FIXME: File is corrupt! Hot-fix with empty				// index root attribute if recovery option is				// set.				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 index root just means that the newly		 * created files in that directory should be created compressed/		 * encrypted. However index root cannot be both compressed and		 * encrypted.		 */		if (a->flags & ATTR_COMPRESSION_MASK)			NInoSetCompressed(ni);		if (a->flags & ATTR_IS_ENCRYPTED) {			if (a->flags & ATTR_COMPRESSION_MASK) {				ntfs_error(vi->i_sb, "Found encrypted and "						"compressed attribute.");				goto unm_err_out;			}			NInoSetEncrypted(ni);		}

⌨️ 快捷键说明

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