SDcardFS文件系统浅析(五)- sdcardfs在文件系统调用中

SDcardFS文件系统浅析(五)- sdcardfs在文件系统调用中

上一节从ftrace中可以看到在cat过程中sdcardfs调用顺序,我们知道了sdcardfs的调用流程,但是这些函数在整个文件系统的调用中是怎么配合的,怎么被串起来的?下面补齐缺失的trace,来看下其在整个文件系统调用中的位置。食用下面ftrace log需要有一定的文件系统基础,可以配合这个博客:open()在Linux内核的实现-准备工作这各博客里对linux中的open()中实现的流程以及其中各函数作用都做了注解。

  1. open()
 SyS_openat() {//系统调用
 4)               |    do_sys_open() {
 4)               |      getname() {//1. 将文件名由用户态拷贝到内核态
 4)               |        getname_flags() {
 4)               |          kmem_cache_alloc() {
 4)   2.604 us    |          }
 4)               |          __check_object_size() {
 4)   0.052 us    |            is_vmalloc_addr();
 4)               |            pfn_valid() {
 4)               |              memblock_is_map_memory() {
 4)   0.105 us    |                memblock_search();
 4)   0.677 us    |              }
 4)   1.250 us    |            }
 4)   0.104 us    |            __check_heap_object();
 4)   0.104 us    |            check_stack_object();
 4)   3.594 us    |          }
 4)   7.760 us    |        }
 4)   8.333 us    |      }
 4)               |      get_unused_fd_flags() {//2. 为即将打开的文件分配文件描述符
 4)               |        __alloc_fd() {
 4)               |          _etext() {
 4)   0.156 us    |            preempt_count_add();
 4)   1.458 us    |          }
 4)   0.104 us    |          expand_files();
 4)               |          _etext() {
 4)   0.157 us    |            preempt_count_sub();
 4)   0.729 us    |          }
 4)   4.218 us    |        }
 4)   4.740 us    |      }
 4)               |      do_filp_open() {/*3. 根据用户传入的路径去执行open,如果找到则为文件创建
                                       file结构体.open的核心操作函数,其解析文件路径创建
                                       file结构体*/
 4)               |        path_openat() {//3.1 路径查找
 4)               |          get_empty_filp() {//3.1.1 创建新的file结构体
 4)               |            kmem_cache_alloc() {
 4)   2.865 us    |            }
 4)               |            security_file_alloc() {
 4)               |              selinux_file_alloc_security() {
 4)               |                kmem_cache_alloc() {
 4)   2.760 us    |                }
 4)   3.334 us    |              }
 4)   3.906 us    |            }
 4)   0.052 us    |            __mutex_init();
 4) + 10.885 us   |          }
 4)               |          path_init() {/*3.1.2 路径查找前准备工作,主要判断遍历路径的起始位置
                                       根目录‘/’ or 当前路径 or 指定路径
                                       根据起始位置配置nameidata *nd中的一些参数*/
 4)   0.052 us    |            __rcu_read_lock();
 4)   1.719 us    |          }
 4)               |          link_path_walk() {/*3.1.3 逐一解析文件路径,将解析结果存入
                                            struct nameidata *nd */
 4)               |            inode_permission2() { //这个函数是被may_lookup()调用,作用权限检查
 4)               |              __inode_permission2() {
 4)               |                sdcardfs_permission() { //可以看到最终调用到sdcardfs的权限检查
 4)   0.105 us    |                  generic_permission();
 4)   2.188 us    |                }
 4)               |                security_inode_permission() {/*安全操作,最后决定是否有权限,
                                       调用内核自己注册的security_ops结构体的函数,新的内核特性属于                                        linux 安全模块(LSM)*/  
 4)               |                  selinux_inode_permission() {
 4)   0.052 us    |                    __rcu_read_lock();
 4)               |                    avc_lookup() {
 4)   1.823 us    |                    }
 4)   0.104 us    |                    __rcu_read_unlock();
 4)   3.750 us    |                  }
 4)   4.375 us    |                }
 4)   8.281 us    |              }
 4)   8.959 us    |            }
 4)   0.678 us    |            sdcardfs_hash_ci(); //根据dentry拿到 hash_len name

     ------------------------------------------------------------------------------------
      /* parent->d_op->d_hash(parent, &this);通过这种方式被调用,把hash_len 和 name写入this中*/
                struct qstr this = { { .hash_len = hash_len }, .name = name };
                err = parent->d_op->d_hash(parent, &this);
                if (err < 0)
                    return err;
                hash_len = this.hash_len;
                name = this.name;
     ------------------------------------------------------------------------------------

 4) + 11.510 us   |          }
 4)               |          lookup_fast() {/*这个是被walk_component()调用,作用处理当前目录项
                                           更新nd next(path类型,指向下一个目录项)*/
 4)               |            __d_lookup_rcu() { //rcu方式的dentry lookup
 4)               |              slow_dentry_cmp() {
 4)   0.365 us    |                sdcardfs_cmp_ci();/*parent->d_op->d_compare(parent, dentry,                                                      tlen, tname, name),需要注意这个比较是大小                                                    写敏感的比较*/
 4)   1.145 us    |              }
 4)   2.136 us    |            }
 4)   0.468 us    |            sdcardfs_d_revalidate();

     ------------------------------------------------------------------------------------------
     /*一致性检查,dentry->d_op->d_revalidate(dentry,flags);在调用到sdcardfs_d_revalidate后其返回
     0 随后在lookup_fast中会调用unlazy_walk(),返回err = 0代码如下*/
         /*这里判断,如果sdcardfs的inode中的data不存在或者被标记为abandoned,则认为这个dentry过时,通过d_drop释放当前dentry,置err = 0 */
         /* If our top's inode is gone, we may be out of date */
        inode = igrab(d_inode(dentry));
        if (inode) {
            data = top_data_get(SDCARDFS_I(inode));
            if (!data || data->abandoned) {
                d_drop(dentry);
                err = 0;
            }
            if (data)
                data_put(data);
            iput(inode);
        }
   -------------------------------------------------------------------------------------------

 4)               |            unlazy_walk() { //unlazy_walk()将当前的rcu-walk切换到ref-walk
 4)               |              legitimize_mnt() {
 4)               |                __legitimize_mnt() {
 4)   0.156 us    |                  preempt_count_add();
 4)   0.156 us    |                  preempt_count_sub();
 4)   1.927 us    |                }
 4)   2.552 us    |              }
 4)   0.104 us    |              __rcu_read_unlock();
 4)   3.750 us    |            }
 4)               |            sdcardfs_d_revalidate() {//再次调用sdcardfs_d_revalidate
                            ...................
 4)               |              igrab() {
 4)               |                _etext() {
 4)   0.156 us    |                  preempt_count_add();
 4)   0.937 us    |                }
 4)               |                _etext() {
                            ................
 4)   0.104 us    |            follow_managed();//重定位dentry
 4) + 65.521 us   |          }
 4)               |          mntget() {
 4)   0.156 us    |            preempt_count_add();
 4)   0.156 us    |            preempt_count_sub();
 4)   1.355 us    |          }
 4)   0.105 us    |          complete_walk();
 4)               |          may_open() { //3.1.4,被do_last调用,作用权限,模式检查

     ---------------------------------------------------------------------------------------
    /*link_path_walk 之后就是 do_last 对最后的对路径中最后一个目录项做处理,对open最常用的两种操作是
     打开文件或创建文件,这里就是open 这里是通过 do_last -> finish_open_created: -> may_open */
     ---------------------------------------------------------------------------------------

 4)               |            __inode_permission2() {
 4)               |              sdcardfs_permission() {
 4)   0.104 us    |                generic_permission();
 4)   0.937 us    |              }
 4)               |              security_inode_permission() {
 4)               |                selinux_inode_permission() {
 4)   0.104 us    |                  __rcu_read_lock();
 4)               |                  avc_lookup() {
 4)   0.156 us    |                    preempt_count_add();
 4)   0.156 us    |                    preempt_count_sub();
 4)   2.396 us    |                  }
 4)   0.052 us    |                  __rcu_read_unlock();
 4)   4.219 us    |                }
 4)   4.792 us    |              }
 4)   7.552 us    |            }
 4)   8.125 us    |          }
 4)               |          vfs_open() { //在 may_open 之后调用 vfs_open,这是第一次调用vfs_open
 4)               |            do_dentry_open() {
 4)               |              path_get() {
 4)               |                mntget() {
 4)   0.156 us    |                  preempt_count_add();
 4)   0.156 us    |                  preempt_count_sub();
 4)   1.823 us    |                }
 4)   2.500 us    |              }
 4)   0.052 us    |              try_module_get();
 4)               |              security_file_open() {
 4)               |                selinux_file_open() {
 4)   0.052 us    |                  avc_policy_seqno();
 4)               |                  avc_has_perm() {
 4)   0.052 us    |                    __rcu_read_lock();
 4)               |                    avc_lookup() {
 4)   0.156 us    |                      preempt_count_add();
 4)   0.156 us    |                      preempt_count_sub();
 4)   1.355 us    |                    }
 4)   0.052 us    |                    __rcu_read_unlock();
 4)   2.969 us    |                  }
 4)   4.114 us    |                }
 4)   0.104 us    |                __fsnotify_parent();
 4)   0.364 us    |                fsnotify();
 4)   6.094 us    |              }
 4)               |              sdcardfs_open() { //open = f->f_op->open;调用sdcardfs_open
 4)               |                dget_parent() {
 4)   0.052 us    |                  __rcu_read_lock();
 4)   0.104 us    |                  __rcu_read_unlock();
 4)   1.146 us    |                }
 4)   0.104 us    |                check_caller_access_to_name(); /*通过packgelist控制权限,可以看上一节*/
 4)               |                override_fsids() {
 4)               |                  prepare_creds() {
 4)               |                    kmem_cache_alloc() {
 4)   2.969 us    |                    }
 4)               |                    security_prepare_creds() {
 4)               |                      selinux_cred_prepare() {
 4)               |                        kmemdup() {
 4)               |                          __kmalloc_track_caller() {
 4)   0.104 us    |                            kmalloc_slab();
 4)   4.219 us    |                          }
 4)   4.792 us    |                        }
 4)   5.365 us    |                      }
 4)   6.146 us    |                    }
 4) + 11.250 us   |                  }
 4)   0.104 us    |                  override_creds();
 4) + 12.864 us   |                }
 4)               |                kmem_cache_alloc_trace() {
 4)   2.708 us    |                }
 4)               |                _etext() {
 4)   0.156 us    |                  preempt_count_add();
 4)   0.677 us    |                }
 4)               |                path_get() {
 4)               |                  mntget() {
 4)   1.146 us    |                  }
 4)   1.718 us    |                }
 4)               |                _etext() {
 4)   0.156 us    |                  preempt_count_sub();
 4)   0.729 us    |                }
 4)               |                dentry_open() { //在sdcardfs中执行dentry_open
 4)               |                  get_empty_filp() {
 4)               |                    kmem_cache_alloc() {
 4)   3.386 us    |                    }
 4)               |                    security_file_alloc() {
 4)               |                      selinux_file_alloc_security() {
 4)               |                        kmem_cache_alloc() {
 4)   2.604 us    |                        }
 4)   3.177 us    |                      }
 4)   3.802 us    |                    }
 4)   0.052 us    |                    __mutex_init();
 4) + 11.042 us   |                  }
 4)               |                  do_dentry_open() { 

     -----------------------------------------------------------------------------------
      /*do_dentry_open这个是被 dentry_open -> vfs_open -> do_dentry_open这样调用,也就是说
         sdcardfs被vfs_open调用后,执行一些权限管控,又调用vfs_open执行*/
     ------------------------------------------------------------------------------------

 4)               |                    path_get() {
 4)               |                      mntget() {
 4)   1.302 us    |                      }
 4)   1.875 us    |                    }
 4)   0.052 us    |                    try_module_get();
 4)               |                    security_file_open() {
 4)               |                      selinux_file_open() {
 4)   0.052 us    |                        avc_policy_seqno();
 4)               |                        avc_has_perm() {
 4)   0.104 us    |                          __rcu_read_lock();
 4)               |                          avc_lookup() {
 4)   1.718 us    |                          }
 4)   0.104 us    |                          __rcu_read_unlock();
 4)   3.386 us    |                        }
 4)   4.635 us    |                      }
 4)   0.052 us    |                      __fsnotify_parent();
 4)   0.885 us    |                      fsnotify();
 4)   7.136 us    |                    }
 4)               |                    f2fs_file_open() {
 4)   0.053 us    |                      generic_file_open();
 4)   0.625 us    |                    }
 4)   0.677 us    |                    file_ra_state_init();
 4) + 14.427 us   |                  }
 4) + 26.511 us   |                }
 4)               |                path_put() {
 4)               |                  dput() {
 4)   0.053 us    |                    __rcu_read_lock();
 4)   0.052 us    |                    __rcu_read_unlock();
 4)   1.198 us    |                  }
 4)               |                  mntput() {
 4)               |                    mntput_no_expire() {
 4)   2.396 us    |                    }
 4)   2.968 us    |                  }
 4)   5.156 us    |                }
 4)   0.052 us    |                set_nlink();
 4)               |                revert_fsids() {
 4)   0.625 us    |                  revert_creds();
 4)   1.146 us    |                }
 4)               |                dput() {
 4)   2.031 us    |                }
 4) + 63.282 us   |              }
 4)   0.261 us    |              file_ra_state_init();
 4) + 75.989 us   |            }
 4) + 76.511 us   |          }
 4)   0.105 us    |          open_check_o_direct();//检查是否为无缓存的读取,直接IO
 4)               |          dput() {
 4)   1.198 us    |          }
 4)               |          mntput() {
 4)               |            mntput_no_expire() {
 4)   2.448 us    |            }
 4)   2.969 us    |          }//dentry_open结束
 4)               |          terminate_walk() {//3.2 释放nd
 4)   0.104 us    |            drop_links.isra.30();
 4)               |            dput() {
 4)   1.146 us    |            }
 4)               |            mntput() {
 4)               |              mntput_no_expire() {
 4)   2.396 us    |              }
 4)   2.916 us    |            }
 4)   5.730 us    |          }
 4) ! 191.719 us  |        }
 4) ! 192.500 us  |      }//path_openat结束
 4)   0.052 us    |      __fsnotify_parent();
 4)   0.104 us    |      fsnotify(); //将filp的监控点打开,将其添加到监控系统中
 4)               |      fd_install() {//将fd和file关联
 4)               |        __fd_install() {
 4)   0.156 us    |          preempt_count_add();
 4)   0.156 us    |          preempt_count_sub();
 4)   1.354 us    |        }
 4)   1.927 us    |      }
 4)               |      putname() {
 4)               |        kmem_cache_free() {
 4)   0.156 us    |          preempt_count_add();
 4)   0.156 us    |          preempt_count_sub();
 4)   0.104 us    |          preempt_count_add();
 4)   0.156 us    |          preempt_count_sub();
 4)   2.657 us    |        }
 4)   3.229 us    |      }
 4) ! 214.375 us  |    }
 4) ! 214.948 us  |  }
 4)   0.052 us    |  post_ttbr_update_workaround();
  1. read()

read相对来说比较简单,没有open那么复杂,调用流程就是 vfs_read -> sdcardfs_read -> vfs_read

 SyS_read() {
 4)   0.104 us    |    __fdget_pos();
 4)               |    vfs_read() {//第一次调用,会指向sdcardfs
 4)               |      rw_verify_area() {//检查读权限
 4)               |        security_file_permission() {
 4)               |          selinux_file_permission() {
 4)   0.052 us    |            avc_policy_seqno();
 4)   0.677 us    |          }
 4)   0.104 us    |          __fsnotify_parent();
 4)   0.105 us    |          fsnotify();
 4)   2.344 us    |        }
 4)   2.916 us    |      }
 4)               |      sdcardfs_read() {//file->f_op->read(file, buf, count, pos);
 4)               |        vfs_read() {//第二次调用指向底层文件系统,这里是f2fs
 4)               |          rw_verify_area() {
 4)               |            security_file_permission() {
 4)               |              selinux_file_permission() {
 4)   0.052 us    |                avc_policy_seqno();
 4)   0.729 us    |              }
 4)   0.052 us    |              __fsnotify_parent();
 4)   0.104 us    |              fsnotify();
 4)   2.604 us    |            }
 4)   3.750 us    |          }
 4)               |          new_sync_read() { // 应为底层支持read_iter,所以用new_sync_read
 4)               |            generic_file_read_iter() {
 4)   0.105 us    |              _cond_resched();
 4)               |              pagecache_get_page() {
 4)               |                find_get_entry() {
 4)   0.104 us    |                  __rcu_read_lock();
 4)   0.104 us    |                  __rcu_read_unlock();
 4)   1.406 us    |                }
 4)   1.927 us    |              }
 4)   0.104 us    |              mark_page_accessed();
 4)               |              do_page_fault() {
 4)   0.104 us    |                down_read_trylock();
 4)               |                find_vma() {
 4)   0.156 us    |                  vmacache_find();
 4)   0.104 us    |                  vmacache_update();
 4)   1.407 us    |                }
 4)               |                handle_mm_fault() {
 4)   0.208 us    |                  preempt_count_add();
 4)   0.156 us    |                  preempt_count_sub();
 4)   0.104 us    |                  anon_vma_prepare();
                                    ...............
 4)   0.052 us    |                  add_mm_counter_fast();
 4)               |                  page_add_new_anon_rmap() {
 4)   0.104 us    |                    __mod_zone_page_state();
 4)   0.678 us    |                  }
 4)               |                  lru_cache_add_active_or_unevictable() {
 4)               |                    __lru_cache_add() {
 4)   0.052 us    |                      preempt_count_add();
 4)   0.104 us    |                      preempt_count_sub();
 4)   1.198 us    |                    }
 4)   1.771 us    |                  }
 4)               |                  _etext() {
 4)   0.157 us    |                    preempt_count_sub();
 4)   0.729 us    |                  }
 4) + 41.980 us   |                }
 4)   0.053 us    |                up_read();
 4) + 45.885 us   |              }
 4)   0.208 us    |              preempt_count_add();
 4)               |              __check_object_size() {
 4)   0.052 us    |                is_vmalloc_addr();
 4)               |                pfn_valid() {
 4)               |                  memblock_is_map_memory() {
 4)   0.104 us    |                    memblock_search();
 4)   0.677 us    |                  }
 4)   1.250 us    |                }
 4)   0.052 us    |                check_stack_object();
 4)   3.021 us    |              }
 4)   0.156 us    |              preempt_count_sub();
 4)   0.052 us    |              put_page();
 4)   0.104 us    |              _cond_resched();
 4)               |              pagecache_get_page() {
 4)               |                find_get_entry() {
 4)   0.052 us    |                  __rcu_read_lock();
 4)   0.104 us    |                  __rcu_read_unlock();
 4)   1.250 us    |                }
 4)   1.823 us    |              }
 4)   0.053 us    |              put_page();
 4)               |              touch_atime() {
 4)   0.364 us    |                atime_needs_update();
 4)   0.886 us    |              }
 4) + 84.635 us   |            }
 4) + 85.261 us   |          }
 4)   0.052 us    |          __fsnotify_parent();
 4)   0.053 us    |          fsnotify();
 4) + 91.250 us   |        }
 4) + 91.822 us   |      } //这些加号是中间穿插着中断,因为要从磁盘读数据,我把这部分删掉了
 4)   0.052 us    |      __fsnotify_parent();
 4)   0.052 us    |      fsnotify();//这部分都是些收尾动作
 4) + 97.136 us   |    }
 4) + 98.385 us   |  }
  1. close()
 SyS_close() {
 4)               |    __close_fd() {
 4)               |      _etext() {
 4)   0.156 us    |        preempt_count_add();
 4)   0.833 us    |      }
 4)               |      _etext() {
 4)   0.156 us    |        preempt_count_sub();
 4)   0.730 us    |      }
 4)               |      filp_close() {
 4)   0.052 us    |        sdcardfs_flush();//回写
 4)   0.104 us    |        dnotify_flush();
 4)   0.104 us    |        locks_remove_posix();
 4)               |        fput() {
 4)               |          task_work_add() {
 4)               |            kick_process() {
 4)   0.157 us    |              preempt_count_add();
 4)   0.104 us    |              preempt_count_sub();
 4)   1.354 us    |            }
 4)   1.928 us    |          }
 4)   2.500 us    |        }
 4)   5.000 us    |      }
 4)   8.386 us    |    }
 4)   8.958 us    |  }

你可能感兴趣的:(Linux,Android)