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

📄 lcnalloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
				/* Empty zone. Don't bother searching it. */				goto done_zones_check;			}			ntfs_debug("Continuing outer while loop.");			continue;		} /* done_zones == 7 */		ntfs_debug("All zones are finished.");		/*		 * All zones are finished!  If DATA_ZONE, shrink mft zone.  If		 * MFT_ZONE, we have really run out of space.		 */		mft_zone_size = vol->mft_zone_end - vol->mft_zone_start;		ntfs_debug("vol->mft_zone_start 0x%llx, vol->mft_zone_end "				"0x%llx, mft_zone_size 0x%llx.",				(unsigned long long)vol->mft_zone_start,				(unsigned long long)vol->mft_zone_end,				(unsigned long long)mft_zone_size);		if (zone == MFT_ZONE || mft_zone_size <= 0) {			ntfs_debug("No free clusters left, going to out.");			/* Really no more space left on device. */			err = -ENOSPC;			goto out;		} /* zone == DATA_ZONE && mft_zone_size > 0 */		ntfs_debug("Shrinking mft zone.");		zone_end = vol->mft_zone_end;		mft_zone_size >>= 1;		if (mft_zone_size > 0)			vol->mft_zone_end = vol->mft_zone_start + mft_zone_size;		else /* mft zone and data2 zone no longer exist. */			vol->data2_zone_pos = vol->mft_zone_start =					vol->mft_zone_end = 0;		if (vol->mft_zone_pos >= vol->mft_zone_end) {			vol->mft_zone_pos = vol->mft_lcn;			if (!vol->mft_zone_end)				vol->mft_zone_pos = 0;		}		bmp_pos = zone_start = bmp_initial_pos =				vol->data1_zone_pos = vol->mft_zone_end;		search_zone = 2;		pass = 2;		done_zones &= ~2;		ntfs_debug("After shrinking mft zone, mft_zone_size 0x%llx, "				"vol->mft_zone_start 0x%llx, "				"vol->mft_zone_end 0x%llx, "				"vol->mft_zone_pos 0x%llx, search_zone 2, "				"pass 2, dones_zones 0x%x, zone_start 0x%llx, "				"zone_end 0x%llx, vol->data1_zone_pos 0x%llx, "				"continuing outer while loop.",				(unsigned long long)mft_zone_size,				(unsigned long long)vol->mft_zone_start,				(unsigned long long)vol->mft_zone_end,				(unsigned long long)vol->mft_zone_pos,				done_zones, (unsigned long long)zone_start,				(unsigned long long)zone_end,				(unsigned long long)vol->data1_zone_pos);	}	ntfs_debug("After outer while loop.");out:	ntfs_debug("At out.");	/* Add runlist terminator element. */	if (likely(rl)) {		rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;		rl[rlpos].lcn = is_extension ? LCN_ENOENT : LCN_RL_NOT_MAPPED;		rl[rlpos].length = 0;	}	if (likely(page && !IS_ERR(page))) {		if (need_writeback) {			ntfs_debug("Marking page dirty.");			flush_dcache_page(page);			set_page_dirty(page);			need_writeback = 0;		}		ntfs_unmap_page(page);	}	if (likely(!err)) {		up_write(&vol->lcnbmp_lock);		ntfs_debug("Done.");		return rl;	}	ntfs_error(vol->sb, "Failed to allocate clusters, aborting "			"(error %i).", err);	if (rl) {		int err2;		if (err == -ENOSPC)			ntfs_debug("Not enough space to complete allocation, "					"err -ENOSPC, first free lcn 0x%llx, "					"could allocate up to 0x%llx "					"clusters.",					(unsigned long long)rl[0].lcn,					(unsigned long long)(count - clusters));		/* Deallocate all allocated clusters. */		ntfs_debug("Attempting rollback...");		err2 = ntfs_cluster_free_from_rl_nolock(vol, rl);		if (err2) {			ntfs_error(vol->sb, "Failed to rollback (error %i).  "					"Leaving inconsistent metadata!  "					"Unmount and run chkdsk.", err2);			NVolSetErrors(vol);		}		/* Free the runlist. */		ntfs_free(rl);	} else if (err == -ENOSPC)		ntfs_debug("No space left at all, err = -ENOSPC, first free "				"lcn = 0x%llx.",				(long long)vol->data1_zone_pos);	up_write(&vol->lcnbmp_lock);	return ERR_PTR(err);}/** * __ntfs_cluster_free - free clusters on an ntfs volume * @ni:		ntfs inode whose runlist describes the clusters to free * @start_vcn:	vcn in the runlist of @ni at which to start freeing clusters * @count:	number of clusters to free or -1 for all clusters * @ctx:	active attribute search context if present or NULL if not * @is_rollback:	true if this is a rollback operation * * Free @count clusters starting at the cluster @start_vcn in the runlist * described by the vfs inode @ni. * * If @count is -1, all clusters from @start_vcn to the end of the runlist are * deallocated.  Thus, to completely free all clusters in a runlist, use * @start_vcn = 0 and @count = -1. * * If @ctx is specified, it is an active search context of @ni and its base mft * record.  This is needed when __ntfs_cluster_free() encounters unmapped * runlist fragments and allows their mapping.  If you do not have the mft * record mapped, you can specify @ctx as NULL and __ntfs_cluster_free() will * perform the necessary mapping and unmapping. * * Note, __ntfs_cluster_free() saves the state of @ctx on entry and restores it * before returning.  Thus, @ctx will be left pointing to the same attribute on * return as on entry.  However, the actual pointers in @ctx may point to * different memory locations on return, so you must remember to reset any * cached pointers from the @ctx, i.e. after the call to __ntfs_cluster_free(), * you will probably want to do: *	m = ctx->mrec; *	a = ctx->attr; * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that * you cache ctx->mrec in a variable @m of type MFT_RECORD *. * * @is_rollback should always be 'false', it is for internal use to rollback * errors.  You probably want to use ntfs_cluster_free() instead. * * Note, __ntfs_cluster_free() does not modify the runlist, so you have to * remove from the runlist or mark sparse the freed runs later. * * Return the number of deallocated clusters (not counting sparse ones) on * success and -errno on error. * * WARNING: If @ctx is supplied, regardless of whether success or failure is *	    returned, you need to check IS_ERR(@ctx->mrec) and if 'true' the @ctx *	    is no longer valid, i.e. you need to either call *	    ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it. *	    In that case PTR_ERR(@ctx->mrec) will give you the error code for *	    why the mapping of the old inode failed. * * Locking: - The runlist described by @ni must be locked for writing on entry *	      and is locked on return.  Note the runlist may be modified when *	      needed runlist fragments need to be mapped. *	    - The volume lcn bitmap must be unlocked on entry and is unlocked *	      on return. *	    - This function takes the volume lcn bitmap lock for writing and *	      modifies the bitmap contents. *	    - If @ctx is NULL, the base mft record of @ni must not be mapped on *	      entry and it will be left unmapped on return. *	    - If @ctx is not NULL, the base mft record must be mapped on entry *	      and it will be left mapped on return. */s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,		ntfs_attr_search_ctx *ctx, const bool is_rollback){	s64 delta, to_free, total_freed, real_freed;	ntfs_volume *vol;	struct inode *lcnbmp_vi;	runlist_element *rl;	int err;	BUG_ON(!ni);	ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count "			"0x%llx.%s", ni->mft_no, (unsigned long long)start_vcn,			(unsigned long long)count,			is_rollback ? " (rollback)" : "");	vol = ni->vol;	lcnbmp_vi = vol->lcnbmp_ino;	BUG_ON(!lcnbmp_vi);	BUG_ON(start_vcn < 0);	BUG_ON(count < -1);	/*	 * Lock the lcn bitmap for writing but only if not rolling back.  We	 * must hold the lock all the way including through rollback otherwise	 * rollback is not possible because once we have cleared a bit and	 * dropped the lock, anyone could have set the bit again, thus	 * allocating the cluster for another use.	 */	if (likely(!is_rollback))		down_write(&vol->lcnbmp_lock);	total_freed = real_freed = 0;	rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, ctx);	if (IS_ERR(rl)) {		if (!is_rollback)			ntfs_error(vol->sb, "Failed to find first runlist "					"element (error %li), aborting.",					PTR_ERR(rl));		err = PTR_ERR(rl);		goto err_out;	}	if (unlikely(rl->lcn < LCN_HOLE)) {		if (!is_rollback)			ntfs_error(vol->sb, "First runlist element has "					"invalid lcn, aborting.");		err = -EIO;		goto err_out;	}	/* Find the starting cluster inside the run that needs freeing. */	delta = start_vcn - rl->vcn;	/* The number of clusters in this run that need freeing. */	to_free = rl->length - delta;	if (count >= 0 && to_free > count)		to_free = count;	if (likely(rl->lcn >= 0)) {		/* Do the actual freeing of the clusters in this run. */		err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn + delta,				to_free, likely(!is_rollback) ? 0 : 1);		if (unlikely(err)) {			if (!is_rollback)				ntfs_error(vol->sb, "Failed to clear first run "						"(error %i), aborting.", err);			goto err_out;		}		/* We have freed @to_free real clusters. */		real_freed = to_free;	};	/* Go to the next run and adjust the number of clusters left to free. */	++rl;	if (count >= 0)		count -= to_free;	/* Keep track of the total "freed" clusters, including sparse ones. */	total_freed = to_free;	/*	 * Loop over the remaining runs, using @count as a capping value, and	 * free them.	 */	for (; rl->length && count != 0; ++rl) {		if (unlikely(rl->lcn < LCN_HOLE)) {			VCN vcn;			/* Attempt to map runlist. */			vcn = rl->vcn;			rl = ntfs_attr_find_vcn_nolock(ni, vcn, ctx);			if (IS_ERR(rl)) {				err = PTR_ERR(rl);				if (!is_rollback)					ntfs_error(vol->sb, "Failed to map "							"runlist fragment or "							"failed to find "							"subsequent runlist "							"element.");				goto err_out;			}			if (unlikely(rl->lcn < LCN_HOLE)) {				if (!is_rollback)					ntfs_error(vol->sb, "Runlist element "							"has invalid lcn "							"(0x%llx).",							(unsigned long long)							rl->lcn);				err = -EIO;				goto err_out;			}		}		/* The number of clusters in this run that need freeing. */		to_free = rl->length;		if (count >= 0 && to_free > count)			to_free = count;		if (likely(rl->lcn >= 0)) {			/* Do the actual freeing of the clusters in the run. */			err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn,					to_free, likely(!is_rollback) ? 0 : 1);			if (unlikely(err)) {				if (!is_rollback)					ntfs_error(vol->sb, "Failed to clear "							"subsequent run.");				goto err_out;			}			/* We have freed @to_free real clusters. */			real_freed += to_free;		}		/* Adjust the number of clusters left to free. */		if (count >= 0)			count -= to_free;			/* Update the total done clusters. */		total_freed += to_free;	}	if (likely(!is_rollback))		up_write(&vol->lcnbmp_lock);	BUG_ON(count > 0);	/* We are done.  Return the number of actually freed clusters. */	ntfs_debug("Done.");	return real_freed;err_out:	if (is_rollback)		return err;	/* If no real clusters were freed, no need to rollback. */	if (!real_freed) {		up_write(&vol->lcnbmp_lock);		return err;	}	/*	 * Attempt to rollback and if that succeeds just return the error code.	 * If rollback fails, set the volume errors flag, emit an error	 * message, and return the error code.	 */	delta = __ntfs_cluster_free(ni, start_vcn, total_freed, ctx, true);	if (delta < 0) {		ntfs_error(vol->sb, "Failed to rollback (error %i).  Leaving "				"inconsistent metadata!  Unmount and run "				"chkdsk.", (int)delta);		NVolSetErrors(vol);	}	up_write(&vol->lcnbmp_lock);	ntfs_error(vol->sb, "Aborting (error %i).", err);	return err;}#endif /* NTFS_RW */

⌨️ 快捷键说明

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