1: /*

   2:  * We use the same basic approach as the old NTFS driver, i.e. we parse the

   3:  * index root entries and then the index allocation entries that are marked

   4:  * as in use in the index bitmap.

   5:  *

   6:  * While this will return the names in random order this doesn't matter for

   7:  * ->readdir but OTOH results in a faster ->readdir.

   8:  *

   9:  * VFS calls ->readdir without BKL but with i_mutex held. This protects the VFS

  10:  * parts (e.g. ->f_pos and ->i_size, and it also protects against directory

  11:  * modifications).

  12:  *

  13:  * Locking:  - Caller must hold i_mutex on the directory.

  14:  *         - Each page cache page in the index allocation mapping must be

  15:  *           locked whilst being accessed otherwise we may find a corrupt

  16:  *           page due to it being under ->writepage at the moment which

  17:  *           applies the mst protection fixups before writing out and then

  18:  *           removes them again after the write is complete after which it 

  19:  *           unlocks the page.

  20:  */

  21: static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)

  22: {

We use the same basic approach as the old NTFS driver, i.e. we parse the
index root entries and then the index allocation entries that are marked
as in use in the index bitmap.

根据这名注释,可以推测index bitmap是用来标注多个index allocation的使用情况的。

那么这些index allocation都存在哪里呢,因为通常一个File Record中只有一个index allocation属性。

   1: /*

   2:      * Copy the index root attribute value to a buffer so that we can put

   3:      * the search context and unmap the mft record before calling the

   4:      * filldir() callback.  We need to do this because of NFSd which calls

   5:      * ->lookup() from its filldir callback() and this causes NTFS to

   6:      * deadlock as ntfs_lookup() maps the mft record of the directory and

   7:      * we have got it mapped here already.  The only solution is for us to

   8:      * unmap the mft record here so that a call to ntfs_lookup() is able to

   9:      * map the mft record without deadlocking.

  10:      */

  11:     rc = le32_to_cpu(ctx->attr->data.resident.value_length);

  12:     ir = kmalloc(rc, GFP_NOFS);

  13:     if (unlikely(!ir)) {

  14:         err = -ENOMEM;

  15:         goto err_out;

  16:     }

  17:     /* Copy the index root value (it has been verified in read_inode). */

  18:     memcpy(ir, (u8*)ctx->attr +

  19:             le16_to_cpu(ctx->attr->data.resident.value_offset), rc);

  20:     ntfs_attr_put_search_ctx(ctx);

  21:     unmap_mft_record(ndir);

  22:     ctx = NULL;

  23:     m = NULL;

  24:     index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);

  25:     /* The first index entry. */

  26:     ie = (INDEX_ENTRY*)((u8*)&ir->index +

  27:             le32_to_cpu(ir->index.entries_offset));

  28:     /*

  29:      * Loop until we exceed valid memory (corruption case) or until we

  30:      * reach the last entry or until filldir tells us it has had enough

  31:      * or signals an error (both covered by the rc test).

  32:      */

  33:     for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {

  34:         ntfs_debug("In index root, offset 0x%zx.", (u8*)ie - (u8*)ir);

  35:         /* Bounds checks. */

  36:         if (unlikely((u8*)ie < (u8*)ir || (u8*)ie +

  37:                 sizeof(INDEX_ENTRY_HEADER) > index_end ||

  38:                 (u8*)ie + le16_to_cpu(ie->key_length) >

  39:                 index_end))

  40:             goto err_out;

  41:         /* The last entry cannot contain a name. */

  42:         if (ie->flags & INDEX_ENTRY_END)

  43:             break;

  44:         /* Skip index root entry if continuing previous readdir. */

  45:         if (ir_pos > (u8*)ie - (u8*)ir)

  46:             continue;

  47:         /* Advance the position even if going to skip the entry. */

  48:         fpos = (u8*)ie - (u8*)ir;

  49:         /* Submit the name to the filldir callback. */

  50:         rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent,

  51:                 filldir);

  52:         if (rc) {

  53:             kfree(ir);

  54:             goto abort;

  55:         }

  56:     }

/* Copy the index root value (it has been verified in read_inode). */
    memcpy(ir, (u8*)ctx->attr +
            le16_to_cpu(ctx->attr->data.resident.value_offset), rc);

这段代码是从index root属性中提取文件名信息,如果遇到index entry的flags被设置了INDEX_ENTRY_END标志,就跳出循环。

index root是存放于resident,即File Record本地的index entry集合。

/* If there is no index allocation attribute we are finished. */
if (!NInoIndexAllocPresent(ndir))
    goto EOD;

如果没有Index Allocation属性,我们就已经遍历完了所有的目录项,结束。

读取到Bitmap的内容

   1: bmp = (u8*)page_address(bmp_page);

   2:     /* Find next index block in use. */

   3:     while (!(bmp[cur_bmp_pos >> 3] & (1 << (cur_bmp_pos & 7)))) {

   4: find_next_index_buffer:

   5:         cur_bmp_pos++;

   6:         /*

   7:          * If we have reached the end of the bitmap page, get the next

   8:          * page, and put away the old one.

   9:          */

  10:         if (unlikely((cur_bmp_pos >> 3) >= PAGE_CACHE_SIZE)) {

  11:             ntfs_unmap_page(bmp_page);

  12:             bmp_pos += PAGE_CACHE_SIZE * 8;

  13:             cur_bmp_pos = 0;

  14:             goto get_next_bmp_page;

  15:         }

  16:         /* If we have reached the end of the bitmap, we are done. */

  17:         if (unlikely(((bmp_pos + cur_bmp_pos) >> 3) >= i_size))

  18:             goto unm_EOD;

  19:         ia_pos = (bmp_pos + cur_bmp_pos) <<

  20:                 ndir->itype.index.block_size_bits;

  21:     }

Bitmap里面的每一位,代表着index allocation中的一个cluster是否有效。

如果Bitmap中某一比特位为0,则其对应的index allocation中的数据就要越过相应的cluster去读下一个cluster的内容。

Linux操作系统中对于NTFS读取目录功能的实现的更多相关文章

  1. Linux操作系统中的文件目录结构详细介绍

    "/" :Linux文件系统的入口.也是最高一级的目录. "/bin":基本系统所需要的命令,功能和"/usr/bin"类似,这个目录下的文 ...

  2. 在Linux系统中使用ntfs、fat32格式的存储设备

    在Linux系统中使用ntfs.fat32格式的存储设备   我们通常使用的移动硬盘或U盘一般都是ntfs或fat32的文件系统,作为一名运维工程师,经常会遇到把移动硬盘或者U盘上的内容拷贝的Linu ...

  3. [转帖]Linux操作系统中,*.zip、*.tar、*.tar.gz、*.tar.bz2、*.tar.xz、*.jar、*.7z等格式的压缩与解压

    Linux操作系统中,*.zip.*.tar.*.tar.gz.*.tar.bz2.*.tar.xz.*.jar.*.7z等格式的压缩与解压 https://blog.csdn.net/gatieme ...

  4. Linux操作系统中打开文件数量的查看方法

    Linux操作系统中打开文件数量的查看方法ulimit -n 4096也就是限制用户的最大文件打开数为4096个 在网上查了关于怎么查看文件打开数的文章大致有两种说法/proc/sys/fs/file ...

  5. Linux操作系统中/sbin/init程序的执行过程

    当init启动后,它通过执行各种启动事务来继续引导进程(检查并监视文件系统,启动后台程序daemons,等等),直至完成用户所有操作环境的设置工作.这里主要涉及4个程序:init.getty(aget ...

  6. Linux操作系统中系统调用接口

    进程控制 fork 创建一个新进程 clone 按指定条件创建子进程 execve 运行可执行文件 exit 终止进程 _exit 立即终止当前进程 getdtablesize 进程所能打开的最大文件 ...

  7. VMware下的Linux系统中Windows的共享目录,不支持创建软连接

    [问题]  在编译VMware下的Linux系统对从Windows中共享过来的文件,进行编译的时候,遇到:  ln: creating symbolic link XXXXXX : Operation ...

  8. Linux系统中/opt 和 /usr目录

    重点:usr是Unix Software Resource的缩写,即“UNIX操作系统软件资源”所放置的目录. 下面是个人找到的适合类似我这种从Windows转向Linux小白的文章. Ref:htt ...

  9. linux操作系统中的netstat命令查看端口状态的使用和window操作系统查看端口号

    1:linux操作系统 netstat 命令用于显示各种网络相关信息,即网络状态.而我主要使用netstat查看端口号是否启动: 参数详情: 1 -a (all)显示所有选项,默认不显示LISTEN相 ...

随机推荐

  1. Android 测试点归纳总结

    前言 除了测试平台工具,业务测试的总结和思考同样重要,这里总结了一些Android测试知识点,可以辅助业务测试快速形成测试用例和检查点,当作抛砖引玉分享给大家.如有思考不全面的地方,欢迎大家指出来. ...

  2. JS - 计算两个数组的交集、差集、并集、补集(多种实现方式)

    方法一:最普遍的做法 使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本.也不用引入其他第三方库. 1,直接使用 filter.concat 来计算 var ...

  3. 使用 vue.js 的一些操作记录

    vue.js不支持ie8以下 1. 在html的属性中赋值: 需要在属性前加上 v-bind

  4. PAT甲级——A1144 TheMissingNumber【20】

    Given N integers, you are supposed to find the smallest positive integer that is NOT in the given li ...

  5. 一道面试题:js返回函数, 函数名后带多个括号的用法及join()的注意事项

    博客搬迁,给你带来的不便,敬请谅解! http://www.suanliutudousi.com/2017/11/13/js%E8%BF%94%E5%9B%9E%E5%87%BD%E6%95%B0%E ...

  6. Linux部分常用命令详解(二)

    date 命令详解 date命令可以按照指定格式显示日期,只键入date则以默认格式显示当前时间 例如: 如果需要以指定的格式显示日期,可以使用“+”开头的字符串指定其格式,详细格式如下: %n : ...

  7. uoj#186 【UR #13】Yist

    题目 orz myy 首先注意到答案有单调性,于是我们可以考虑二分一个\(x\),之后去判断一下每次只使用长度为\(x\)的区间能否删出目标序列 显然我们应该贪心地删除需要删除元素中最小的那一个,感性 ...

  8. LeetCode Array Easy 1. Two Sum

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  9. 批量修改root密码

    公司有五十多台服务器.每台服务器中使用的密码完全不同,同时操作系统也不一样,centos5,6,7 .ubuntu,windows都有,更不用提其中各种小版本. root密码定期更改是一个大问题(wi ...

  10. 73. PrintStream(打印流)

    PrintStream(打印流)   打印流可以打印任意类型的数据,而且打印前都会把数据转换成字符串再进行打印(就是把数据存入硬盘中) 编码与解码图例:下面我们来看看一个简单的字节输出流 public ...