Ejemplo n.º 1
0
static long fat_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
{      
	int err = 0;
	struct inode *inode = file->f_mapping->host;
	int cluster, nr_cluster, fclus, dclus, free_bytes, nr_bytes;
	struct super_block *sb = inode->i_sb;
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	if (mode & ~FALLOC_FL_KEEP_SIZE)
		return -EOPNOTSUPP;
	if ((offset + len) <= MSDOS_I(inode)->mmu_private) {
		fat_msg(sb, KERN_ERR,
				"fat_fallocate():Blocks already allocated");
		return -EINVAL;
	}
	if ((mode & FALLOC_FL_KEEP_SIZE)) {
		if (inode->i_size > 0) {
			err = fat_get_cluster(inode, FAT_ENT_EOF,
					&fclus, &dclus);
			if (err < 0) {
				fat_msg(sb, KERN_ERR,
						"fat_fallocate():fat_get_cluster() error");
				return err;
			}
			free_bytes = ((fclus+1) << sbi->cluster_bits) -
				(inode->i_size);
			nr_bytes = (offset + len - inode->i_size) - free_bytes;
		} else
			nr_bytes = (offset + len - inode->i_size);
		nr_cluster = (nr_bytes + (sbi->cluster_size - 1)) >>
			sbi->cluster_bits;
		mutex_lock(&inode->i_mutex);
		while (nr_cluster-- > 0) {
			err = fat_alloc_clusters(inode, &cluster, 1);
			if (err) {
				fat_msg(sb, KERN_ERR,
						"fat_fallocate():fat_alloc_clusters() error");
				goto error;
			}
			err = fat_chain_add(inode, cluster, 1);
			if (err) {
				fat_free_clusters(inode, cluster);
				goto error;
			}
		}
		err = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
		if (err < 0) {
			fat_msg(sb, KERN_ERR,
					"fat_fallocate():fat_get_cluster() error");
			goto error;
		}
		MSDOS_I(inode)->mmu_private = (fclus + 1) << sbi->cluster_bits;
	} else {
Ejemplo n.º 2
0
/*
* Desc: Return the size of a directory file in bytes
*
*/
static int fat_calc_dir_size(struct inode *inode)
{
	struct fat_sb_info *sbi = MSDOS_SB(inode->i_sb);
	int ret, fclus, dclus;

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

	ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
	if (ret < 0)
		return ret;
	inode->i_size = (fclus + 1) << sbi->cluster_bits;

	return 0;
}
Ejemplo n.º 3
0
/** Walk the cluster chain.
 *
 * @param bs		Buffer holding the boot sector for the file.
 * @param service_id	Service ID of the device with the file.
 * @param firstc	First cluster to start the walk with.
 * @param lastc		If non-NULL, output argument hodling the last cluster
 *			number visited.
 * @param numc		If non-NULL, output argument holding the number of
 *			clusters seen during the walk.
 * @param max_clusters	Maximum number of clusters to visit.
 *
 * @return		EOK on success or a negative error code.
 */
int
fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
    fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
{
	uint32_t clusters = 0;
	fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
	fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
	int rc;

	if (firstc == FAT_CLST_RES0) {
		/* No space allocated to the file. */
		if (lastc)
			*lastc = firstc;
		if (numc)
			*numc = 0;
		return EOK;
	}

	while (clst < clst_last1 && clusters < max_clusters) {
		assert(clst >= FAT_CLST_FIRST);
		if (lastc)
			*lastc = clst;	/* remember the last cluster number */

		/* read FAT1 */
		rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
		if (rc != EOK)
			return rc;

		assert(clst != clst_bad);
		clusters++;
	}

	if (lastc && clst < clst_last1)
		*lastc = clst;
	if (numc)
		*numc = clusters;

	return EOK;
}
Ejemplo n.º 4
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);
}