📄 super.c
字号:
zone_start = initial_location = vol->data1_zone_pos; zone_end = vol->nr_clusters; if (zone_start == vol->mft_zone_end) pass = 2; if (zone_start >= zone_end) { vol->data1_zone_pos = zone_start = vol->mft_zone_end; pass = 2; } break; case 2: ntfs_debug(DEBUG_OTHER, "%s(): Switching from " "data1 zone to data2 zone.\n", __FUNCTION__); /* Update data1 zone position. */ if (rlpos) { ntfs_cluster_t tc; ntfs_debug(DEBUG_OTHER, "%s(): Before checks, " "vol->data1_zone_pos = " "0x%x.\n", __FUNCTION__, vol->data1_zone_pos); tc = rl2[rlpos - 1].lcn + rl2[rlpos - 1].len; if (tc >= vol->nr_clusters) vol->data1_zone_pos = vol->mft_zone_end; else if ((initial_location >= vol->data1_zone_pos || tc > vol->data1_zone_pos) && tc >= vol->mft_zone_end) vol->data1_zone_pos = tc; ntfs_debug(DEBUG_OTHER, "%s(): After checks, " "vol->data1_zone_pos = " "0x%x.\n", __FUNCTION__, vol->data1_zone_pos); } /* Switch from data1 zone to data2 zone. */ search_zone = 4; zone_start = initial_location = vol->data2_zone_pos; zone_end = vol->mft_zone_start; if (!zone_start) pass = 2; if (zone_start >= zone_end) { vol->data2_zone_pos = zone_start = initial_location = (ntfs_cluster_t)0; pass = 2; } break; case 4: ntfs_debug(DEBUG_OTHER, "%s(): Switching from " "data2 zone to data1 zone.\n", __FUNCTION__); /* Update data2 zone position. */ if (rlpos) { ntfs_cluster_t tc; ntfs_debug(DEBUG_OTHER, "%s(): Before checks, " "vol->data2_zone_pos = " "0x%x.\n", __FUNCTION__, vol->data2_zone_pos); tc = rl2[rlpos - 1].lcn + rl2[rlpos - 1].len; if (tc >= vol->mft_zone_start) vol->data2_zone_pos = (ntfs_cluster_t)0; else if (initial_location >= vol->data2_zone_pos || tc > vol->data2_zone_pos) vol->data2_zone_pos = tc; ntfs_debug(DEBUG_OTHER, "%s(): After checks, " "vol->data2_zone_pos = " "0x%x.\n", __FUNCTION__, vol->data2_zone_pos); } /* Switch from data2 zone to data1 zone. */ goto switch_to_data1_zone; /* See above. */ default: BUG(); } ntfs_debug(DEBUG_OTHER, "%s(): After zone switch, " "search_zone = %i, pass = %i, " "initial_location = 0x%x, zone_start " "= 0x%x, zone_end = 0x%x.\n", __FUNCTION__, search_zone, pass, initial_location, zone_start, zone_end); buf_pos = zone_start; if (zone_start == zone_end) { ntfs_debug(DEBUG_OTHER, "%s(): Empty zone, " "going to done_zones_check.\n", __FUNCTION__); /* Empty zone. Don't bother searching it. */ goto done_zones_check; } ntfs_debug(DEBUG_OTHER, "%s(): Continuing outer while " "loop.\n", __FUNCTION__); continue; } /* done_zones == 7 */ ntfs_debug(DEBUG_OTHER, "%s(): All zones are finished.\n", __FUNCTION__); /* * 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(DEBUG_OTHER, "%s(): vol->mft_zone_start = 0x%x, " "vol->mft_zone_end = 0x%x, mft_zone_size = " "0x%x.\n", __FUNCTION__, vol->mft_zone_start, vol->mft_zone_end, mft_zone_size); if (zone == MFT_ZONE || mft_zone_size <= (ntfs_cluster_t)0) { ntfs_debug(DEBUG_OTHER, "%s(): No free clusters left, " "returning -ENOSPC, going to " "fail_ret.\n", __FUNCTION__); /* Really no more space left on device. */ err = -ENOSPC; goto fail_ret; } /* zone == DATA_ZONE && mft_zone_size > 0 */ ntfs_debug(DEBUG_OTHER, "%s(): Shrinking mft zone.\n", __FUNCTION__); zone_end = vol->mft_zone_end; mft_zone_size >>= 1; if (mft_zone_size > (ntfs_cluster_t)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 = (ntfs_cluster_t)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 = (ntfs_cluster_t)0; } buf_pos = zone_start = initial_location = vol->data1_zone_pos = vol->mft_zone_end; search_zone = 2; pass = 2; done_zones &= ~2; ntfs_debug(DEBUG_OTHER, "%s(): After shrinking mft " "zone, mft_zone_size = 0x%x, " "vol->mft_zone_start = 0x%x, vol->mft_zone_end " "= 0x%x, vol->mft_zone_pos = 0x%x, search_zone " "= 2, pass = 2, dones_zones = 0x%x, zone_start " "= 0x%x, zone_end = 0x%x, vol->data1_zone_pos " "= 0x%x, continuing outer while loop.\n", __FUNCTION__, mft_zone_size, vol->mft_zone_start, vol->mft_zone_end, vol->mft_zone_pos, done_zones, zone_start, zone_end, vol->data1_zone_pos); } ntfs_debug(DEBUG_OTHER, "%s(): After outer while loop.\n", __FUNCTION__);done_ret: ntfs_debug(DEBUG_OTHER, "%s(): At done_ret.\n", __FUNCTION__); rl2[rlpos].lcn = (ntfs_cluster_t)-1; rl2[rlpos].len = (ntfs_cluster_t)0; *rl = rl2; *rl_len = rlpos; if (need_writeback) { ntfs_debug(DEBUG_OTHER, "%s(): Writing back.\n", __FUNCTION__); need_writeback = 0; io.param = buf; io.do_read = 0; err = ntfs_readwrite_attr(vol->bitmap, data, last_read_pos, &io); if (err) { ntfs_error("%s(): Bitmap writeback failed in done " "code path with error code %i.\n", __FUNCTION__, -err); goto err_ret; } ntfs_debug(DEBUG_OTHER, "%s(): Wrote 0x%Lx bytes.\n", __FUNCTION__, io.size); }done_fail_ret: ntfs_debug(DEBUG_OTHER, "%s(): At done_fail_ret (follows done_ret).\n", __FUNCTION__); unlock_kernel(); free_page((unsigned long)buf); if (err) ntfs_debug(DEBUG_FILE3, "%s(): Failed to allocate " "clusters. Returning with error code %i.\n", __FUNCTION__, -err); ntfs_debug(DEBUG_OTHER, "%s(): Syncing $Bitmap inode.\n", __FUNCTION__); if (ntfs_update_inode(vol->bitmap)) ntfs_error("%s(): Failed to sync inode $Bitmap. " "Continuing anyway.\n", __FUNCTION__); ntfs_debug(DEBUG_OTHER, "%s(): Returning with code %i.\n", __FUNCTION__, err); return err;fail_ret: ntfs_debug(DEBUG_OTHER, "%s(): At fail_ret.\n", __FUNCTION__); if (rl2) { if (err == -ENOSPC) { /* Return first free lcn and count of free clusters. */ *location = rl2[0].lcn; *count -= clusters; ntfs_debug(DEBUG_OTHER, "%s(): err = -ENOSPC, " "*location = 0x%x, *count = 0x%x.\n", __FUNCTION__, *location, *count); } /* Deallocate all allocated clusters. */ ntfs_debug(DEBUG_OTHER, "%s(): Deallocating allocated " "clusters.\n", __FUNCTION__); ntfs_deallocate_clusters(vol, rl2, rlpos); /* Free the runlist. */ ntfs_vfree(rl2); } else { if (err == -ENOSPC) { /* Nothing free at all. */ *location = vol->data1_zone_pos; /* Irrelevant... */ *count = 0; ntfs_debug(DEBUG_OTHER, "%s(): No space left at all, " "err = -ENOSPC, *location = 0x%x, " "*count = 0.\n", __FUNCTION__, *location); } } *rl = NULL; *rl_len = 0; ntfs_debug(DEBUG_OTHER, "%s(): *rl = NULL, *rl_len = 0, " "going to done_fail_ret.\n", __FUNCTION__); goto done_fail_ret;wb_err_ret: ntfs_debug(DEBUG_OTHER, "%s(): At wb_err_ret.\n", __FUNCTION__); if (need_writeback) { int __err; ntfs_debug(DEBUG_OTHER, "%s(): Writing back.\n", __FUNCTION__); io.param = buf; io.do_read = 0; __err = ntfs_readwrite_attr(vol->bitmap, data, last_read_pos, &io); if (__err) ntfs_error("%s(): Bitmap writeback failed in error " "code path with error code %i.\n", __FUNCTION__, -__err); need_writeback = 0; }err_ret: ntfs_debug(DEBUG_OTHER, "%s(): At err_ret, *location = -1, " "*count = 0, going to fail_ret.\n", __FUNCTION__); *location = -1; *count = 0; goto fail_ret;}/* * IMPORTANT: Caller has to hold big kernel lock or the race monster will come * to get you! (-; * TODO: Need our own lock for bitmap accesses but BKL is more secure for now, * considering we might not have covered all places with a lock yet. In that * case the BKL offers a one way exclusion which is better than no exclusion * at all... (AIA) */static int ntfs_clear_bitrange(ntfs_inode *bitmap, const ntfs_cluster_t start_bit, const ntfs_cluster_t count){ ntfs_cluster_t buf_size, bit, nr_bits = count; unsigned char *buf, *byte; int err; ntfs_io io; io.fn_put = ntfs_put; io.fn_get = ntfs_get; /* Calculate the required buffer size in bytes. */ buf_size = (ntfs_cluster_t)((start_bit & 7) + nr_bits + 7) >> 3; if (buf_size <= (ntfs_cluster_t)(64 * 1024)) buf = ntfs_malloc(buf_size); else buf = ntfs_vmalloc(buf_size); if (!buf) return -ENOMEM; /* Read the bitmap from the data attribute. */ io.param = byte = buf; io.size = buf_size; err = ntfs_read_attr(bitmap, bitmap->vol->at_data, 0, start_bit >> 3, &io); if (err || io.size != buf_size) goto err_out; /* Now clear the bits in the read bitmap. */ bit = start_bit & 7; while (bit && nr_bits) { /* Process first partial byte, if present. */ *byte &= ~(1 << bit++); nr_bits--; bit &= 7; if (!bit) byte++; } while (nr_bits >= 8) { /* Process full bytes. */ *byte = 0; nr_bits -= 8; byte++; } bit = 0; while (nr_bits) { /* Process last partial byte, if present. */ *byte &= ~(1 << bit); nr_bits--; bit++; } /* Write the modified bitmap back to disk. */ io.param = buf; io.size = buf_size; err = ntfs_write_attr(bitmap, bitmap->vol->at_data, 0, start_bit >> 3, &io);err_out: if (buf_size <= (ntfs_cluster_t)(64 * 1024)) ntfs_free(buf); else ntfs_vfree(buf); if (!err && io.size != buf_size) err = -EIO; return err;}/* * See comments for lack of zone adjustments below in the description of the * function ntfs_deallocate_clusters(). */int ntfs_deallocate_cluster_run(const ntfs_volume *vol, const ntfs_cluster_t lcn, const ntfs_cluster_t len){ int err; lock_kernel(); err = ntfs_clear_bitrange(vol->bitmap, lcn, len); unlock_kernel(); return err;}/* * This is inefficient, but logically trivial, so will do for now. Note, we * do not touch the mft nor the data zones here because we want to minimize * recycling of clusters to enhance the chances of data being undeleteable. * Also we don't want the overhead. Instead we do one additional sweep of the * current data zone during cluster allocation to check for freed clusters. */int ntfs_deallocate_clusters(const ntfs_volume *vol, const ntfs_runlist *rl, const int rl_len){ int i, err; lock_kernel(); for (i = err = 0; i < rl_len && !err; i++) err = ntfs_clear_bitrange(vol->bitmap, rl[i].lcn, rl[i].len); unlock_kernel(); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -