从layout到extent的演变史(二)

本文详细介绍了PNFS中从layout到extent的演变过程,并重点分析了pnfs_open_layout函数的工作原理,包括layout的初始化和分配过程,以及如何通过优化减少RPC调用次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从layout到extent的演变史(二)

  交流了一下,发现了理解这个过程的好流程。pnfs中读写操作的流程是,client先发送open的RPC,server返回open的结果(应该和fh相关),client再发送getlayout的RPC,client拿到layout后,直接从磁盘上读文件内容。我们做的优化是在发送open RPC时同时将layout也获取过来,这样可以节省一次getlayout的RPC的时间。

pnfs_open_layout

  pnfs中读文件过程,到函数_nfs4_do_open,如果inode->size不为0,文件不空,则调用pnfs_open_layout预取该文件的layout保存在nfs_inode里面中。下面开始讲解pnfs_open_layout的函数。
  根据inode获取到pnfs_layout_type(下文用变量名称lo代替),如果为空,则分配初始化锁上;如果非空,则引用计数加1,直接锁上。先根据inode获取到nfs_inode,nfs_inode中有pnfs_layout_type,每个文件对应一个lo。重点介绍一下分配并初始化lo的过程。

lo的初始化过程

  如果lo为空,会分配并初始化lo。那都初始化lo的什么内容呢?
lo结构体中有void *ld_data指针,这个是指向layout driver的私有数据,那这个私有数据就是指pnfs_block_layout。初始化struct layoutdriver_io_operations *io_ops,调用bl_alloc_layout分配和初始化pnfs_block_layout,这个结构体还是值得一看的。

struct pnfs_block_layout {
    struct pnfs_inval_markings bl_inval; /* tracks INVAL->RW transition */
    spinlock_t      bl_ext_lock;   /* Protects list manipulation */
    struct list_head    bl_extents[EXTENT_LISTS]; /* R and RW extents */
    struct list_head    bl_commit;  /* Needs layout commit */
    unsigned int        bl_count;   /* entries in bl_commit */
    sector_t        bl_blocksize;  /* Server blocksize in sectors */
};

看到了吧,日思夜想的extent终于出现了,你会不会突然的出现,在街角的咖啡店。出现了,这里仅仅是初始化,初始化bl_extents[0]和bl_extent[1]两个list_head链表,初始化bl_commit链表,这是需要提交layout的链表,设置bl_count是0,设置bl_blocksize,再看它是什么作用。初始化结束后,返回这个pnfs_block_layout。lo->ld_data指向返回的pnfs_block_layout。
  给lo分配lseg。和struct pnfs_layoutdriver_type初始化相关。

/* Per-layout driver specific registration structure */
struct pnfs_layoutdriver_type {
    const u32 id;
    const char *name;
    struct layoutdriver_io_operations *ld_io_ops;
    struct layoutdriver_policy_operations *ld_policy_ops;
};

lo是有了,再分配struct pnfs_layout_segment *lseg。先看sruct layoutdriver_io_operations,真正的从磁盘上读写文件的函数(我的理解)。调用bl_alloc_lseg分配lseg。

static struct layoutdriver_io_operations blocklayout_io_operations = {
    .commit             = bl_commit,
    .read_pagelist          = bl_read_pagelist,
    .write_pagelist         = bl_write_pagelist,
    .write_begin            = bl_write_begin,
    .write_end          = bl_write_end,
    .write_end_cleanup      = bl_write_end_cleanup,
    .alloc_layout           = bl_alloc_layout,
    .free_layout            = bl_free_layout,
    .alloc_lseg         = bl_alloc_lseg,
    .free_lseg          = bl_free_lseg,
    .setup_layoutcommit     = bl_setup_layoutcommit,
    .encode_layoutcommit        = bl_encode_layoutcommit,
    .cleanup_layoutcommit       = bl_cleanup_layoutcommit,
};

bl_alloc_lseg()

原型:static struct pnfs_layout_segment *bl_alloc_lseg(struct pnfs_layout_type *lo, struct nfs4_pnfs_layoutget_res *lgr)
功能:根据server返回的lgr内容来初始化lseg。
实际上起作用的函数是nfs4_blk_process_layoutget。

04-01
<think>好的,我现在需要帮助用户理解“EXTENT”在数据库或存储上下文中的概念或用法。首先,我得回忆一下自己对这个术语的了解。在数据库系统中,“EXTENT”通常指的是存储空间分配的单位。可能和表空间、数据文件相关。比如,当数据库需要存储数据时,会按一定大小的块来分配空间,这个块可能就是EXTENT。 接下来,我需要确认这个理解是否正确。可能需要查阅一些数据库管理的资料,比如Oracle或者MySQL的文档。记得用户提供的引用里有一个是MySQL的文档链接,虽然具体内容是关于列统计的,但可能相关的存储结构部分会有提到EXTENT。不过,可能更常见的是在Oracle中,EXTENT是表空间中分配给段(segment)的连续数据块集合。每个段由多个EXTENT组成,当现有空间不足时,数据库会自动分配新的EXTENT。 另外,在存储系统的上下文中,比如存储硬件或文件系统,EXTENT可能指连续分配的存储区域,用于提高读写效率。例如,某些文件系统在分配大文件时会使用连续的EXTENT来减少碎片。 需要区分不同数据库系统中的具体实现。比如,在Oracle中,段(如表或索引)由多个EXTENT构成,每个EXTENT是一组连续的数据块。而在PostgreSQL中,可能使用不同的术语,比如“扩展”来管理表的空间分配。但用户问的是通用的概念,所以需要概括。 还要考虑用户可能的实际应用场景。比如,当用户设计表空间或管理存储时,了解EXTENT的大小和分配策略可以帮助优化性能。如果EXTENT设置过小,可能导致频繁的空间分配操作,影响性能;过大则可能浪费空间。此外,自动扩展和手动管理EXTENT的区别也是需要注意的点。 现在需要组织这些信息,以清晰的结构呈现给用户。首先定义EXTENT,然后解释其在数据库中的角色,比如作为空间分配单位,属于段的一部分。接着,说明其结构特点,如连续性、大小可配置。再举例不同数据库中的实现,比如Oracle和MySQL。此外,存储系统中的EXTENT概念也要提到,比如文件系统中的连续块分配。最后,讨论管理EXTENT的最佳实践,如设置合理大小,监控碎片情况等。 还要生成相关问题,可能包括EXTENT与数据块的区别、如何配置大小、碎片处理、不同数据库中的实现差异等。这样用户可以有进一步的学习方向。 需要确保使用正确的中文术语,比如“区段”或“扩展”,但可能直接使用英文术语“EXTENT”更准确,因为通常中文资料中也会保留这个术语。同时,注意LaTeX格式的应用,比如提到数据块时使用$data block$,不过可能不需要太多数学表达式,这里更多是术语解释。 最后,检查是否有遗漏的重要点,比如EXTENT和段的关系,自动扩展特性,以及实际应用中的管理策略。确保回答准确且易于理解,符合用户的需求。</think>在数据库和存储系统中,**EXTENT(区段)** 是存储空间分配的基本单位,用于管理数据的物理存储。以下是详细解释: ### 1. 核心概念 - **EXTENT的定义** EXTENT 是 **一组连续的存储单元**(如数据块或磁盘块),通常作为数据库或文件系统分配空间的最小逻辑单位。例如,在数据库中,当表或索引需要更多空间时,系统会为其分配一个或多个 EXTENT[^1]。 - **EXTENT与数据块的关系** - 数据块(Block)是存储的最小单元(如 8 KB 或 16 KB),而 EXTENT 包含多个连续的数据块。 - 公式化表示:一个 EXTENT 包含 $n$ 个数据块,即 $EXTENT = \{Block_1, Block_2, ..., Block_n\}$。 ### 2. 数据库中的 EXTENT - **表空间与段(Segment)** 在 Oracle 等数据库中,EXTENT 属于 **段(Segment)**(如表段、索引段),而段属于表空间(Tablespace)。每个段由多个 EXTENT 组成,用于动态扩展存储空间。 ```plaintext 表空间 (Tablespace) ├─ 段 (Segment) │ ├─ EXTENT 1 │ ├─ EXTENT 2 │ └─ ... └─ ... ``` - **自动扩展特性** 数据库可配置 `AUTOEXTEND` 属性,当 EXTENT 空间不足时自动分配新的 EXTENT(如每次扩展 64 MB)。 ### 3. 存储系统中的 EXTENT 在分布式存储或文件系统中,EXTENT 表示 **连续的物理存储区域**,例如: - **HDFS(Hadoop)**:EXTENT 用于管理大文件的分布式存储块。 - **ZFS 文件系统**:通过 EXTENT 优化数据写入的连续性,减少碎片。 ### 4. 管理与优化 - **EXTENT 大小配置** 合理设置 EXTENT 大小可平衡性能与空间利用率: - 过小:频繁分配导致性能下降。 - 过大:空间浪费。 - **碎片问题** 频繁删除/更新操作可能导致 EXTENT 碎片化,需定期执行 `REORGANIZE` 或 `SHRINK` 操作。 ### 5. 示例:成本与 EXTENT 分配 假设存储系统中 EXTENT 大小为 1 GB,高性能层每 GB 成本为 $72,则单个 EXTENT 成本为 $72。若某表需要 200 GB 空间,则需分配 200 个 EXTENT,总成本为 $14,400[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值