static inline int fat_ent_read_block2(struct super_block *sb,
				     struct fat_entry *fatent)
{
	struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
	sector_t blocknr;
	int offset;

	fatent_brelse(fatent);
	ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
	return ops->ent_bread(sb, fatent, offset, blocknr);
}
int isNodeContinuous(struct inode *inode)
{
	struct fat_entry fatent;
	int dclus = 0;
	int nr = 0;
	struct msdos_inode_info * msinode= NULL;

	struct super_block *sb = NULL;
	struct msdos_sb_info *sbi = NULL;
	struct msdos_dir_entry *uninitialized_var(de);

	/*if (NULL != file && NULL != file->f_mapping)
	{
		inode = file->f_mapping->host;
	}
	else
	{
		printk(KERN_INFO "file or file->f_mapping is null, file:%x\n", (unsigned int)file);
		return 0;
	}*/

	if (NULL != inode)
	{
		msinode= MSDOS_I(inode);
		sb = inode->i_sb;
	}
	else
	{
		printk(KERN_INFO "inode is null\n");
		return 0;
	}
	//printk(KERN_INFO "3, inode:%x\n", (unsigned int)inode);

	if (NULL == msinode)
	{
		printk(KERN_INFO "msinode is null\n");
		return 0;
	}

	if (NULL != sb)
	{
		sbi = MSDOS_SB(sb);
	}

	if (NULL == sbi)
	{
		printk(KERN_INFO "sbi is null\n");
		return 0;
	}

	if (msinode->i_start < FAT_START_ENT || msinode->i_start > sbi->max_cluster)
	{
		printk(KERN_INFO "!!!start cluster is not correct\n");
		return 1;
	}

	lock_fat2(sbi);

	dclus = msinode->i_start;
	fatent_init(&fatent);

	while (dclus < FAT_ENT_EOF)
	{
		//printk(KERN_INFO "%d ", dclus);
		nr = fat_ent_read(inode, &fatent, dclus);
		if (FAT_ENT_EOF != nr && nr != (dclus + 1))
		{
			fatent_brelse(&fatent);
			unlock_fat2(sbi);
			printk(KERN_INFO "file is not contiguous\n");
			return 0;
		}

		dclus = nr;
	}

	fatent_brelse(&fatent);
	unlock_fat2(sbi);

	return 1;
}
int fat_find_first_free_clusters(struct super_block *sb,
	u_int32_t MinimumLcn, u_int32_t MinimumSize,  u_int32_t *BeginLcn, u_int32_t *EndLcn)
{
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	struct fatent_operations *ops = sbi->fatent_ops;
	struct fat_entry fatent;
	unsigned long reada_blocks, reada_mask, cur_block;
	int err = 0;
	u_int32_t start = 0;

	*BeginLcn = 0;
	*EndLcn = 0;

	if (MinimumLcn >= sbi->max_cluster)
	{
		printk(KERN_INFO "fat_find_first_free_clusters minimum lcn is out of side\n");
		return 0;
	}

	lock_fat2(sbi);

	if (sbi->free_clusters != -1 && sbi->free_clus_valid && sbi->free_clusters < MinimumSize)
	{
		printk(KERN_INFO "fat_find_first_free_clusters failed, free_clusters:%d, free_clus_valid:%d\n",
			sbi->free_clusters, sbi->free_clus_valid);
		goto out2;
	}

	reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
	reada_mask = reada_blocks - 1;
	cur_block = 0;

	fatent_init(&fatent);
	fatent_set_entry(&fatent, MinimumLcn);

	while (fatent.entry < sbi->max_cluster)
	{
		/* readahead of fat blocks */
		/*if ((cur_block & reada_mask) == 0)
		{
			unsigned long rest = sbi->fat_length - cur_block;
			fat_ent_reada2(sb, &fatent, min(reada_blocks, rest));
		}
		cur_block++;*/

		fatent_set_entry(&fatent, fatent.entry);

		err = fat_ent_read_block2(sb, &fatent);
		if (err)
		{
			printk(KERN_INFO "fat_find_first_free_clusters fat_ent_read_block2 failed\n");
			goto out1;
		}

		do
		{
			if (ops->ent_get(&fatent) == FAT_ENT_FREE)
			{
				if (start == 0)
				{
					start = fatent.entry;
				}

				if (fatent.entry >= sbi->max_cluster)
				{
					if ((fatent.entry - start) >= MinimumSize)
					{
						//printk(KERN_INFO "fat_find_first_free_clusters OK\n");
						*BeginLcn = start;
						*EndLcn = fatent.entry;
						goto out1;
					}
				}
			}
			else
			{
				if (0 != start)
				{
					if ((fatent.entry - start) >= MinimumSize)
					{
						*BeginLcn = start;
						*EndLcn = fatent.entry;
						goto out1;
					}
				}
				start = 0;
			}
		} while (fat_ent_next2(sbi, &fatent));

		if (fatent.entry >= sbi->max_cluster)
		{
			if (0 != start)
			{
				if ((fatent.entry - start) >= MinimumSize)
				{
					*BeginLcn = start;
					*EndLcn = fatent.entry;
				}
			}
			//printk(KERN_INFO "fat_find_first_free_clusters end...\n");
		}
	}
out1:
	//printk(KERN_INFO "fat_find_first_free_clusters out1:%d, val:%d, *BeginLcn:%d, sbi->fat_length:%ld, free_clusters:%d\n",
	//	fatent.entry, ops->ent_get(&fatent), *BeginLcn, sbi->fat_length, sbi->free_clusters);
	fatent_brelse(&fatent);
out2:
	unlock_fat2(sbi);

	return *BeginLcn;
}
unsigned long fat_find_free_clusters(struct super_block *sb, unsigned long clusterSum, int *contiguous)
{
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	struct fatent_operations *ops = sbi->fatent_ops;
	struct fat_entry fatent;
	unsigned long reada_blocks, reada_mask, cur_block;
	int err = 0, free;


	unsigned long clusters = 0;
	unsigned long start = 0;

	*contiguous = 0;

	lock_fat2(sbi);

	if (sbi->free_clusters != -1 && sbi->free_clus_valid && sbi->free_clusters < clusterSum)
	{
		printk(KERN_INFO "fat_find_free_clusters failed, free_clusters:%d, free_clus_valid:%d\n",
			sbi->free_clusters, sbi->free_clus_valid);
		start = 0;
		goto out2;
	}

	reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
	reada_mask = reada_blocks - 1;
	cur_block = 0;

	free = 0;
	fatent_init(&fatent);
	fatent_set_entry(&fatent, FAT_START_ENT);
	while (fatent.entry < sbi->max_cluster)
	{
		/* readahead of fat blocks */
		/*if ((cur_block & reada_mask) == 0)
		{
			unsigned long rest = sbi->fat_length - cur_block;
			fat_ent_reada2(sb, &fatent, min(reada_blocks, rest));
		}
		cur_block++;*/

		fatent_set_entry(&fatent, fatent.entry);

		err = fat_ent_read_block2(sb, &fatent);
		if (err)
		{
			printk(KERN_INFO "fat_find_first_free_clusters fat_ent_read_block2 failed\n");
			start = 0;
			goto out1;
		}

		do
		{
			if (ops->ent_get(&fatent) == FAT_ENT_FREE)
			{
				free++;

				if (start == 0)
				{
					start = fatent.entry;
				}

				clusters++;

				if (clusters >= clusterSum)
				{
					//printk(KERN_INFO "fat_find_free_clusters start = %ld\n", start);

					start--;
					if (start < FAT_START_ENT)
					{
						start = sbi->max_cluster - 1;
					}

					sbi->prev_free = start;
					sb->s_dirt = 1;

					*contiguous = 1;

					goto out1;
				}
			}
			else
			{
				start = 0;
				clusters = 0;
			}
			if (fatent.entry >= sbi->max_cluster)
			{
				start = 0;
				break;
			}
		} while (fat_ent_next2(sbi, &fatent));
	}
out1:
	//sbi->free_clusters = free;
	//sbi->free_clus_valid = 1;
	//sb->s_dirt = 1;
	fatent_brelse(&fatent);
out2:
	unlock_fat2(sbi);

	return start;
}
示例#5
0
/* Free all clusters after the skip'th cluster. */
static int fat_free(struct inode *inode, int skip)
{
	struct super_block *sb = inode->i_sb;
	int err, wait, free_start, i_start, i_logstart;

	if (MSDOS_I(inode)->i_start == 0)
		return 0;

	fat_cache_inval_inode(inode);

	wait = IS_DIRSYNC(inode);
	i_start = free_start = MSDOS_I(inode)->i_start;
	i_logstart = MSDOS_I(inode)->i_logstart;

	/* First, we write the new file size. */
	if (!skip) {
		MSDOS_I(inode)->i_start = 0;
		MSDOS_I(inode)->i_logstart = 0;
	}
	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
	if (wait) {
		err = fat_sync_inode(inode);
		if (err) {
			MSDOS_I(inode)->i_start = i_start;
			MSDOS_I(inode)->i_logstart = i_logstart;
			return err;
		}
	} else
		mark_inode_dirty(inode);

	/* Write a new EOF, and get the remaining cluster chain for freeing. */
	if (skip) {
		struct fat_entry fatent;
		int ret, fclus, dclus;

		ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
		if (ret < 0)
			return ret;
		else if (ret == FAT_ENT_EOF)
			return 0;

		fatent_init(&fatent);
		ret = fat_ent_read(inode, &fatent, dclus);
		if (ret == FAT_ENT_EOF) {
			fatent_brelse(&fatent);
			return 0;
		} else if (ret == FAT_ENT_FREE) {
			fat_fs_panic(sb,
				     "%s: invalid cluster chain (i_pos %lld)",
				     __FUNCTION__, MSDOS_I(inode)->i_pos);
			ret = -EIO;
		} else if (ret > 0) {
			err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
			if (err)
				ret = err;
		}
		fatent_brelse(&fatent);
		if (ret < 0)
			return ret;

		free_start = ret;
	}
	inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);

	/* Freeing the remained cluster chain */
	return fat_free_clusters(inode, free_start);
}