super.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,070 行 · 第 1/5 页
C
2,070 行
/** * setup_lcn_allocator - initialize the cluster allocator * @vol: volume structure for which to setup the lcn allocator * * Setup the cluster (lcn) allocator to the starting values. */static void setup_lcn_allocator(ntfs_volume *vol){#ifdef NTFS_RW LCN mft_zone_size, mft_lcn;#endif /* NTFS_RW */ ntfs_debug("vol->mft_zone_multiplier = 0x%x", vol->mft_zone_multiplier);#ifdef NTFS_RW /* Determine the size of the MFT zone. */ mft_zone_size = vol->nr_clusters; switch (vol->mft_zone_multiplier) { /* % of volume size in clusters */ case 4: mft_zone_size >>= 1; /* 50% */ break; case 3: mft_zone_size = (mft_zone_size + (mft_zone_size >> 1)) >> 2; /* 37.5% */ break; case 2: mft_zone_size >>= 2; /* 25% */ break; /* case 1: */ default: mft_zone_size >>= 3; /* 12.5% */ break; } /* Setup the mft zone. */ vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn; ntfs_debug("vol->mft_zone_pos = 0x%llx", (unsigned long long)vol->mft_zone_pos); /* * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs * source) and if the actual mft_lcn is in the expected place or even * further to the front of the volume, extend the mft_zone to cover the * beginning of the volume as well. This is in order to protect the * area reserved for the mft bitmap as well within the mft_zone itself. * On non-standard volumes we do not protect it as the overhead would * be higher than the speed increase we would get by doing it. */ mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size; if (mft_lcn * vol->cluster_size < 16 * 1024) mft_lcn = (16 * 1024 + vol->cluster_size - 1) / vol->cluster_size; if (vol->mft_zone_start <= mft_lcn) vol->mft_zone_start = 0; ntfs_debug("vol->mft_zone_start = 0x%llx", (unsigned long long)vol->mft_zone_start); /* * Need to cap the mft zone on non-standard volumes so that it does * not point outside the boundaries of the volume. We do this by * halving the zone size until we are inside the volume. */ vol->mft_zone_end = vol->mft_lcn + mft_zone_size; while (vol->mft_zone_end >= vol->nr_clusters) { mft_zone_size >>= 1; vol->mft_zone_end = vol->mft_lcn + mft_zone_size; } ntfs_debug("vol->mft_zone_end = 0x%llx", (unsigned long long)vol->mft_zone_end); /* * Set the current position within each data zone to the start of the * respective zone. */ vol->data1_zone_pos = vol->mft_zone_end; ntfs_debug("vol->data1_zone_pos = 0x%llx", (unsigned long long)vol->data1_zone_pos); vol->data2_zone_pos = 0; ntfs_debug("vol->data2_zone_pos = 0x%llx", (unsigned long long)vol->data2_zone_pos);#endif /* NTFS_RW */}#ifdef NTFS_RW/** * load_and_init_mft_mirror - load and setup the mft mirror inode for a volume * @vol: ntfs super block describing device whose mft mirror to load * * Return TRUE on success or FALSE on error. */static BOOL load_and_init_mft_mirror(ntfs_volume *vol){ struct inode *tmp_ino; ntfs_inode *tmp_ni; ntfs_debug("Entering."); /* Get mft mirror inode. */ tmp_ino = ntfs_iget(vol->sb, FILE_MFTMirr); if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { if (!IS_ERR(tmp_ino)) iput(tmp_ino); /* Caller will display error message. */ return FALSE; } /* * Re-initialize some specifics about $MFTMirr's inode as * ntfs_read_inode() will have set up the default ones. */ /* Set uid and gid to root. */ tmp_ino->i_uid = tmp_ino->i_gid = 0; /* Regular file. No access for anyone. */ tmp_ino->i_mode = S_IFREG; /* No VFS initiated operations allowed for $MFTMirr. */ tmp_ino->i_op = &ntfs_empty_inode_ops; tmp_ino->i_fop = &ntfs_empty_file_ops; /* Put back our special address space operations. */ tmp_ino->i_mapping->a_ops = &ntfs_mft_aops; tmp_ni = NTFS_I(tmp_ino); /* The $MFTMirr, like the $MFT is multi sector transfer protected. */ NInoSetMstProtected(tmp_ni); /* * Set up our little cheat allowing us to reuse the async read io * completion handler for directories. */ tmp_ni->itype.index.block_size = vol->mft_record_size; tmp_ni->itype.index.block_size_bits = vol->mft_record_size_bits; vol->mftmirr_ino = tmp_ino; ntfs_debug("Done."); return TRUE;}/** * check_mft_mirror - compare contents of the mft mirror with the mft * @vol: ntfs super block describing device whose mft mirror to check * * Return TRUE on success or FALSE on error. */static BOOL check_mft_mirror(ntfs_volume *vol){ unsigned long index; struct super_block *sb = vol->sb; ntfs_inode *mirr_ni; struct page *mft_page, *mirr_page; u8 *kmft, *kmirr; runlist_element *rl, rl2[2]; int mrecs_per_page, i; ntfs_debug("Entering."); /* Compare contents of $MFT and $MFTMirr. */ mrecs_per_page = PAGE_CACHE_SIZE / vol->mft_record_size; BUG_ON(!mrecs_per_page); BUG_ON(!vol->mftmirr_size); mft_page = mirr_page = NULL; kmft = kmirr = NULL; index = i = 0; do { u32 bytes; /* Switch pages if necessary. */ if (!(i % mrecs_per_page)) { if (index) { ntfs_unmap_page(mft_page); ntfs_unmap_page(mirr_page); } /* Get the $MFT page. */ mft_page = ntfs_map_page(vol->mft_ino->i_mapping, index); if (IS_ERR(mft_page)) { ntfs_error(sb, "Failed to read $MFT."); return FALSE; } kmft = page_address(mft_page); /* Get the $MFTMirr page. */ mirr_page = ntfs_map_page(vol->mftmirr_ino->i_mapping, index); if (IS_ERR(mirr_page)) { ntfs_error(sb, "Failed to read $MFTMirr."); goto mft_unmap_out; } kmirr = page_address(mirr_page); ++index; } /* Make sure the record is ok. */ if (ntfs_is_baad_recordp((le32*)kmft)) { ntfs_error(sb, "Incomplete multi sector transfer " "detected in mft record %i.", i);mm_unmap_out: ntfs_unmap_page(mirr_page);mft_unmap_out: ntfs_unmap_page(mft_page); return FALSE; } if (ntfs_is_baad_recordp((le32*)kmirr)) { ntfs_error(sb, "Incomplete multi sector transfer " "detected in mft mirror record %i.", i); goto mm_unmap_out; } /* Get the amount of data in the current record. */ bytes = le32_to_cpu(((MFT_RECORD*)kmft)->bytes_in_use); if (!bytes || bytes > vol->mft_record_size) { bytes = le32_to_cpu(((MFT_RECORD*)kmirr)->bytes_in_use); if (!bytes || bytes > vol->mft_record_size) bytes = vol->mft_record_size; } /* Compare the two records. */ if (memcmp(kmft, kmirr, bytes)) { ntfs_error(sb, "$MFT and $MFTMirr (record %i) do not " "match. Run ntfsfix or chkdsk.", i); goto mm_unmap_out; } kmft += vol->mft_record_size; kmirr += vol->mft_record_size; } while (++i < vol->mftmirr_size); /* Release the last pages. */ ntfs_unmap_page(mft_page); ntfs_unmap_page(mirr_page); /* Construct the mft mirror runlist by hand. */ rl2[0].vcn = 0; rl2[0].lcn = vol->mftmirr_lcn; rl2[0].length = (vol->mftmirr_size * vol->mft_record_size + vol->cluster_size - 1) / vol->cluster_size; rl2[1].vcn = rl2[0].length; rl2[1].lcn = LCN_ENOENT; rl2[1].length = 0; /* * Because we have just read all of the mft mirror, we know we have * mapped the full runlist for it. */ mirr_ni = NTFS_I(vol->mftmirr_ino); down_read(&mirr_ni->runlist.lock); rl = mirr_ni->runlist.rl; /* Compare the two runlists. They must be identical. */ i = 0; do { if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn || rl2[i].length != rl[i].length) { ntfs_error(sb, "$MFTMirr location mismatch. " "Run chkdsk."); up_read(&mirr_ni->runlist.lock); return FALSE; } } while (rl2[i++].length); up_read(&mirr_ni->runlist.lock); ntfs_debug("Done."); return TRUE;}/** * load_and_check_logfile - load and check the logfile inode for a volume * @vol: ntfs super block describing device whose logfile to load * * Return TRUE on success or FALSE on error. */static BOOL load_and_check_logfile(ntfs_volume *vol){ struct inode *tmp_ino; ntfs_debug("Entering."); tmp_ino = ntfs_iget(vol->sb, FILE_LogFile); if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { if (!IS_ERR(tmp_ino)) iput(tmp_ino); /* Caller will display error message. */ return FALSE; } if (!ntfs_check_logfile(tmp_ino)) { iput(tmp_ino); /* ntfs_check_logfile() will have displayed error output. */ return FALSE; } vol->logfile_ino = tmp_ino; ntfs_debug("Done."); return TRUE;}/** * load_and_init_quota - load and setup the quota file for a volume if present * @vol: ntfs super block describing device whose quota file to load * * Return TRUE on success or FALSE on error. If $Quota is not present, we * leave vol->quota_ino as NULL and return success. */static BOOL load_and_init_quota(ntfs_volume *vol){ MFT_REF mref; struct inode *tmp_ino; ntfs_name *name = NULL; static const ntfschar Quota[7] = { const_cpu_to_le16('$'), const_cpu_to_le16('Q'), const_cpu_to_le16('u'), const_cpu_to_le16('o'), const_cpu_to_le16('t'), const_cpu_to_le16('a'), 0 }; static ntfschar Q[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('Q'), 0 }; ntfs_debug("Entering."); /* * Find the inode number for the quota file by looking up the filename * $Quota in the extended system files directory $Extend. */ down(&vol->extend_ino->i_sem); mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), Quota, 6, &name); up(&vol->extend_ino->i_sem); if (IS_ERR_MREF(mref)) { /* * If the file does not exist, quotas are disabled and have * never been enabled on this volume, just return success. */ if (MREF_ERR(mref) == -ENOENT) { ntfs_debug("$Quota not present. Volume does not have " "quotas enabled."); /* * No need to try to set quotas out of date if they are * not enabled. */ NVolSetQuotaOutOfDate(vol); return TRUE; } /* A real error occured. */ ntfs_error(vol->sb, "Failed to find inode number for $Quota."); return FALSE; } /* We do not care for the type of match that was found. */ if (name) kfree(name); /* Get the inode. */ tmp_ino = ntfs_iget(vol->sb, MREF(mref)); if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { if (!IS_ERR(tmp_ino)) iput(tmp_ino); ntfs_error(vol->sb, "Failed to load $Quota."); return FALSE; } vol->quota_ino = tmp_ino; /* Get the $Q index allocation attribute. */ tmp_ino = ntfs_index_iget(vol->quota_ino, Q, 2); if (IS_ERR(tmp_ino)) { ntfs_error(vol->sb, "Failed to load $Quota/$Q index."); return FALSE; } vol->quota_q_ino = tmp_ino; ntfs_debug("Done."); return TRUE;}/** * load_and_init_attrdef - load the attribute definitions table for a volume * @vol: ntfs super block describing device whose attrdef to load * * Return TRUE on success or FALSE on error. */static BOOL load_and_init_attrdef(ntfs_volume *vol){ struct super_block *sb = vol->sb; struct inode *ino; struct page *page; unsigned long index, max_index; unsigned int size; ntfs_debug("Entering."); /* Read attrdef table and setup vol->attrdef and vol->attrdef_size. */ ino = ntfs_iget(sb, FILE_AttrDef); if (IS_ERR(ino) || is_bad_inode(ino)) { if (!IS_ERR(ino)) iput(ino); goto failed; } /* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */ if (!ino->i_size || ino->i_size > 0x7fffffff) goto iput_failed; vol->attrdef = (ATTR_DEF*)ntfs_malloc_nofs(ino->i_size); if (!vol->attrdef) goto iput_failed; index = 0; max_index = ino->i_size >> PAGE_CACHE_SHIFT; size = PAGE_CACHE_SIZE; while (index < max_index) { /* Read the attrdef table and copy it into the linear buffer. */read_partial_attrdef_page: page = ntfs_map_page(ino->i_mapping, index); if (IS_ERR(page)) goto free_iput_failed; memcpy((u8*)vol->attrdef + (index++ << PAGE_CACHE_SHIFT), page_address(page), size); ntfs_unmap_page(page); }; if (size == PAGE_CACHE_SIZE) { size = ino->i_size & ~PAGE_CACHE_MASK; if (size) goto read_partial_attrdef_page; } vol->attrdef_size = ino->i_size; ntfs_debug("Read %llu bytes from $AttrDef.", ino->i_size); iput(ino); return TRUE;free_iput_failed: ntfs_free(vol->attrdef); vol->attrdef = NULL;iput_failed: iput(ino);failed: ntfs_error(sb, "Failed to initialize attribute definition table."); return FALSE;}#endif /* NTFS_RW *//** * load_and_init_upcase - load the upcase table for an ntfs volume * @vol: ntfs super block describing device whose upcase to load * * Return TRUE on success or FALSE on error. */static BOOL load_and_init_upcase(ntfs_volume *vol){ struct super_block *sb = vol->sb;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?