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

📄 fatent.c

📁 linux环境下基于FAT的文件系统的通用代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct super_block *sb = inode->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);	struct fatent_operations *ops = sbi->fatent_ops;	int err, offset;	sector_t blocknr;	if (entry < FAT_START_ENT || sbi->max_cluster <= entry) {		fatent_brelse(fatent);		fat_fs_panic(sb, "invalid access to FAT (entry 0x%08x)", entry);		return -EIO;	}	fatent_set_entry(fatent, entry);	ops->ent_blocknr(sb, entry, &offset, &blocknr);	if (!fat_ent_update_ptr(sb, fatent, offset, blocknr)) {		fatent_brelse(fatent);		err = ops->ent_bread(sb, fatent, offset, blocknr);		if (err)			return err;	}	return ops->ent_get(fatent);}/* FIXME: We can write the blocks as more big chunk. */static int fat_mirror_bhs(struct super_block *sb, struct buffer_head **bhs,			  int nr_bhs){	struct msdos_sb_info *sbi = MSDOS_SB(sb);	struct buffer_head *c_bh;	int err, n, copy;	err = 0;	for (copy = 1; copy < sbi->fats; copy++) {		sector_t backup_fat = sbi->fat_length * copy;		for (n = 0; n < nr_bhs; n++) {			c_bh = sb_getblk(sb, backup_fat + bhs[n]->b_blocknr);			if (!c_bh) {				err = -ENOMEM;				goto error;			}			memcpy(c_bh->b_data, bhs[n]->b_data, sb->s_blocksize);			set_buffer_uptodate(c_bh);			mark_buffer_dirty(c_bh);			if (sb->s_flags & MS_SYNCHRONOUS)				err = sync_dirty_buffer(c_bh);			brelse(c_bh);			if (err)				goto error;		}	}error:	return err;}int fat_ent_write(struct inode *inode, struct fat_entry *fatent,		  int new, int wait){	struct super_block *sb = inode->i_sb;	struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;	int err;	ops->ent_put(fatent, new);	if (wait) {		err = fat_sync_bhs(fatent->bhs, fatent->nr_bhs);		if (err)			return err;	}	return fat_mirror_bhs(sb, fatent->bhs, fatent->nr_bhs);}static inline int fat_ent_next(struct msdos_sb_info *sbi,			       struct fat_entry *fatent){	if (sbi->fatent_ops->ent_next(fatent)) {		if (fatent->entry < sbi->max_cluster)			return 1;	}	return 0;}static inline int fat_ent_read_block(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);}static void fat_collect_bhs(struct buffer_head **bhs, int *nr_bhs,			    struct fat_entry *fatent){	int n, i;	for (n = 0; n < fatent->nr_bhs; n++) {		for (i = 0; i < *nr_bhs; i++) {			if (fatent->bhs[n] == bhs[i])				break;		}		if (i == *nr_bhs) {			get_bh(fatent->bhs[n]);			bhs[i] = fatent->bhs[n];			(*nr_bhs)++;		}	}}int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster){	struct super_block *sb = inode->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	struct fatent_operations *ops = sbi->fatent_ops;	struct fat_entry fatent, prev_ent;	struct buffer_head *bhs[MAX_BUF_PER_PAGE];	int i, count, err, nr_bhs, idx_clus;	BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2));	/* fixed limit */	lock_fat(sbi);	if (sbi->free_clusters != -1 && sbi->free_clus_valid &&	    sbi->free_clusters < nr_cluster) {		unlock_fat(sbi);		return -ENOSPC;	}	err = nr_bhs = idx_clus = 0;	count = FAT_START_ENT;	fatent_init(&prev_ent);	fatent_init(&fatent);	fatent_set_entry(&fatent, sbi->prev_free + 1);	while (count < sbi->max_cluster) {		if (fatent.entry >= sbi->max_cluster)			fatent.entry = FAT_START_ENT;		fatent_set_entry(&fatent, fatent.entry);		err = fat_ent_read_block(sb, &fatent);		if (err)			goto out;		/* Find the free entries in a block */		do {			if (ops->ent_get(&fatent) == FAT_ENT_FREE) {				int entry = fatent.entry;				/* make the cluster chain */				ops->ent_put(&fatent, FAT_ENT_EOF);				if (prev_ent.nr_bhs)					ops->ent_put(&prev_ent, entry);				fat_collect_bhs(bhs, &nr_bhs, &fatent);				sbi->prev_free = entry;				if (sbi->free_clusters != -1)					sbi->free_clusters--;				sb->s_dirt = 1;				cluster[idx_clus] = entry;				idx_clus++;				if (idx_clus == nr_cluster)					goto out;				/*				 * fat_collect_bhs() gets ref-count of bhs,				 * so we can still use the prev_ent.				 */				prev_ent = fatent;			}			count++;			if (count == sbi->max_cluster)				break;		} while (fat_ent_next(sbi, &fatent));	}	/* Couldn't allocate the free entries */	sbi->free_clusters = 0;	sbi->free_clus_valid = 1;	sb->s_dirt = 1;	err = -ENOSPC;out:	unlock_fat(sbi);	fatent_brelse(&fatent);	if (!err) {		if (inode_needs_sync(inode))			err = fat_sync_bhs(bhs, nr_bhs);		if (!err)			err = fat_mirror_bhs(sb, bhs, nr_bhs);	}	for (i = 0; i < nr_bhs; i++)		brelse(bhs[i]);	if (err && idx_clus)		fat_free_clusters(inode, cluster[0]);	return err;}int fat_free_clusters(struct inode *inode, int cluster){	struct super_block *sb = inode->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	struct fatent_operations *ops = sbi->fatent_ops;	struct fat_entry fatent;	struct buffer_head *bhs[MAX_BUF_PER_PAGE];	int i, err, nr_bhs;	int first_cl = cluster;	nr_bhs = 0;	fatent_init(&fatent);	lock_fat(sbi);	do {		cluster = fat_ent_read(inode, &fatent, cluster);		if (cluster < 0) {			err = cluster;			goto error;		} else if (cluster == FAT_ENT_FREE) {			fat_fs_panic(sb, "%s: deleting FAT entry beyond EOF",				     __func__);			err = -EIO;			goto error;		}		/* 		 * Issue discard for the sectors we no longer care about,		 * batching contiguous clusters into one request		 */		if (cluster != fatent.entry + 1) {			int nr_clus = fatent.entry - first_cl + 1;			sb_issue_discard(sb, fat_clus_to_blknr(sbi, first_cl),					 nr_clus * sbi->sec_per_clus);			first_cl = cluster;		}		ops->ent_put(&fatent, FAT_ENT_FREE);		if (sbi->free_clusters != -1) {			sbi->free_clusters++;			sb->s_dirt = 1;		}		if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) {			if (sb->s_flags & MS_SYNCHRONOUS) {				err = fat_sync_bhs(bhs, nr_bhs);				if (err)					goto error;			}			err = fat_mirror_bhs(sb, bhs, nr_bhs);			if (err)				goto error;			for (i = 0; i < nr_bhs; i++)				brelse(bhs[i]);			nr_bhs = 0;		}		fat_collect_bhs(bhs, &nr_bhs, &fatent);	} while (cluster != FAT_ENT_EOF);	if (sb->s_flags & MS_SYNCHRONOUS) {		err = fat_sync_bhs(bhs, nr_bhs);		if (err)			goto error;	}	err = fat_mirror_bhs(sb, bhs, nr_bhs);error:	fatent_brelse(&fatent);	for (i = 0; i < nr_bhs; i++)		brelse(bhs[i]);	unlock_fat(sbi);	return err;}EXPORT_SYMBOL_GPL(fat_free_clusters);/* 128kb is the whole sectors for FAT12 and FAT16 */#define FAT_READA_SIZE		(128 * 1024)static void fat_ent_reada(struct super_block *sb, struct fat_entry *fatent,			  unsigned long reada_blocks){	struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;	sector_t blocknr;	int i, offset;	ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);	for (i = 0; i < reada_blocks; i++)		sb_breadahead(sb, blocknr + i);}int fat_count_free_clusters(struct super_block *sb){	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;	lock_fat(sbi);	if (sbi->free_clusters != -1 && sbi->free_clus_valid)		goto out;	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_reada(sb, &fatent, min(reada_blocks, rest));		}		cur_block++;		err = fat_ent_read_block(sb, &fatent);		if (err)			goto out;		do {			if (ops->ent_get(&fatent) == FAT_ENT_FREE)				free++;		} while (fat_ent_next(sbi, &fatent));	}	sbi->free_clusters = free;	sbi->free_clus_valid = 1;	sb->s_dirt = 1;	fatent_brelse(&fatent);out:	unlock_fat(sbi);	return err;}

⌨️ 快捷键说明

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