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; }
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; }
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; }
/* 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); }