QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2054|回复: 11

LVM2+ReiserFS使用小记

[复制链接]
发表于 2005-2-15 19:09:07 | 显示全部楼层 |阅读模式
lvm真是好东东,分区-------  想怎么分就怎么分,想怎么变,随你喜欢!
    本想这个东东应该很容易搞定了,不想又搞了一下午。陷在不断的编译内核
    lvm程序不断的"segment fault" 估计程序错误中就这个问题比较难办了。
    完全靠经验解决 (对我等菜鸟来说,就是瞎猫碰死耗子,碰上就阿弥陀佛啦)
    经过一下午的 编译内核<---->创建lvm 的折磨,终于搞定了,还算走运   :p

    注:LVM现在有LVM1,LVM2两种版本,本文使用的是LVM2

什么是 LVM ? (Logical Volume Manager(逻辑卷管理))

[code:1]LVM为计算机提供了更高层次的磁盘存储。
它使系统管理员可以更方便的为应用与用户分配存储空间。
在LVM管理下的存储卷可以按需要随时改变大小与移除
(可能需对文件系统工具进行升级)。LVM也允许按用户组对存储卷进行管理,
允许管理员用更直观的名称(如"sales'、'development')代替物理磁盘名
(如'sda'、'sdb')来标识存储卷。[/code:1]

        简单的说就是LVM管理介于物理介质(hda,md,loop)和文件系统(ReiserFS)之间
        使用LVM可以灵活的管理分区,在需要时,方便的增加或减小分区的大小
        不用重新"格式化",甚至不用重新启动系统,这对于服务器系统来说很实用。
        对于个人用户也是分区管理的绝佳选择,例如用几十G的空间来装linux
        分区是很头疼的,简单的分成 "/","SWAP" 太过草率,也不利于管理,而分出/usr
        /var /opt .... 对于每个分区大小要评估的准确,不然以后使用中出现
        空间不够的情况,可能就需要转移数据,重新分区,很麻烦。

        而使用LVM管理,就容易多了,可以先按照当前需要分配空间,当不够用的时候再增加
        而这一切只是简单的几条命令就可以完成,甚至不用重新启动就可以使用扩展后的空间了。


        使用LVM2需要三件事:

           1. 安装device-mapper库
           2. 安装lvm2 tools
           3. 在内核中支持device-mapper


        注意:以下方法仅适用于2.6.x内核,使用udev或devps管理设备文件。
        2.4.x内核请详细查看device-mapper的INSTALL文件。


        首先下载device-mapper库以及lvm2 tools:
        http://sources.redhat.com/lvm2/ 这里会得到lvm2相关资源信息
        ftp://sources.redhat.com/pub/dm/ 这里下载device-mapper库
        ftp://sources.redhat.com/pub/lvm2/ 这里下载lvm2 tools
        我使用的版本是:LVM2.0-stable.tgz  device-mapper-stable.tgz

安装device-mapper库,lvm2 tools :

        device-mapper-stable.tgz使用如下命令安装:
      tar zxvf device-mapper-stable.tgz &&
        cd device-mapper.1.00.21/  &&
        ./configure && make && make install


        安装好device-mapper后安装lvm2.0-stable.tgz :
        tar zxvf LVM2.0-stable.tgz &&
        cd LVM2.2.00.33 &&
        ./configure && make install

内核中支持device-mapper :

        就是这里,害我编译内核十几次,我使用的是2.6.10-mm3支持ReiserFS 4.0的内核
       [code:1] Device Drivers  --->
               [*] Multiple devices driver support (RAID and LVM) ---->
                          <*>   Device mapper support
                          < >     Crypt target support
                          < >     Snapshot target (EXPERIMENTAL)               
                          < >     Mirror target (EXPERIMENTAL)
                          < >     Zero target (EXPERIMENTAL)[/code:1]

        只是支持了Device mapper,没有选择其他的特性。

        编译安装好device-mapper lvm-tools 后,使用pvcreate,vgcreate成功的创建了
        物理卷(PV),卷组(VG),当使用lvcreate创建逻辑卷(LV)时,出现了"segment fault"

        首先怀疑是因为gcc的CFLAGS,CXXFLAGS(优化参数)造成的,于是unset CFLAGS CXXFLAGS
        重新编译device-mapper lvm2,仍然出现错误。
        难道是内核错误?重新编译内核......

        将Device mapper support 下面的全部选择,编译进核心,仍然错误。。。。
        编译内核去掉CFLAGS,CXXFLAGS再编译,还是错误。。。。 莫非是整个环境问题?
        换到未优化的lfs中,编译。。安装。。。。错误。。。

        不甘心,换到Mandrake 使用标准2.6.10内核,另一个.config编译,安装。。
        竟然成功了!?把这个内核作为两个lfs的内核启动,竟然都正常了!
        把成功的.config  拿到2.6.10-mm3中,编译。。。。安装。。。又出错了。。
        难道只有在MDK环境编译出来的才可用?
        不应该,没道理。  内核版本问题??
        mv过来标准的2.6.10内核,编译。。。安装。。。。成功了!!
        faint...竟然是2.6.10-mm3内核的问题。。。lvm+ReiserFS 4.0 是不可以了
       所以这里建议最好使用标准的内核,不容易出问题。。。。。。。

        最终我只选择了<*>  Device mapper support  如果希望使用其他特性
        比如pvmove 就要选择Mirror target的支持. 这些特性请查看相关文档.

        编译好内核,udev/devps就应该会根据/proc/misc中的"Num device-mapper"
        在/dev/下 建立mapper目录,并且在目录中建立control这个字符设备。
        其设备号由Num决定,如:我的/proc/misc中是:63 device-mapper
        则control应该为:
        crw-------  1 root root 10, 63 2005-02-10 09:22 /dev/mapper/control

        如果你没有这个control就需要手动建立一个:
        [root@NEWLFS ~]#cat /proc/misc | grep device-mapper | awk '{print $1}'
        得到control的设备号,我的是63.
        [root@NEWLFS ~]#mkdir /dev/mapper
        [root@NEWLFS ~]#mknod /dev/mapper/control c 10 设备号
        基本使用udev/devps管理设备,都会自动建立好这些的。
        现在已经编译好了内核,安装好了device-mapper lvm2,一切准备就绪,开始动工

        先说一下几个需要知道的概念:

        来看看LVM的组成:

[code:1]hda1   hdc1      (PV:s on partitions or whole disks)

       \   /                                          

        \ /                                    

       diskvg        (VG)                           

       /  |  \                                    

      /   |   \                                                                 

  usrlv rootlv varlv (LV:s)

    |      |     |                                                              

ext2  reiserfs  xfs (filesystems)
[/code:1]
PV (Physical Volume物理卷):

        物理卷可以是整个硬盘(hda),也可以是某个分区(hda1),md(software raid),loop设备....

VG (Volume Group 卷组):

        卷组是LVM中最高抽象层,是由一个或多个物理卷所组成的存储器池。

        从图中可以看出,卷组是由一个或几个物理卷组成,然后分支成若干个LV.

LV (Logical Volume 逻辑卷):

        逻辑卷相当于非LVM系统中的分区,它在卷组上建立
        是一个标准的块设备,可以在其上建立文件系统。
[code:1]
+-- Volume Group --------------------------------+

|                                                |

|    +----------------------------------------+         |

| PV | PE |  PE | PE | PE | PE | PE | PE | PE |         |

|    +----------------------------------------+         |

|      .                 .                 .               .                        |

|      .          .                 .        .                 |

|    +----------------------------------------+         |

| LV | LE |  LE | LE | LE | LE | LE | LE | LE |         |

|    +----------------------------------------+         |

|            .          .        .                .     |

|            .                 .        .                .     |

|    +----------------------------------------+         |

| PV | PE |  PE | PE | PE | PE | PE | PE | PE |         |

|    +----------------------------------------+         |

|                                                |

+------------------------------------------------+[/code:1]

PE (Physical Extent物理块):


        物理卷按大小相等的"块"为单位存储,块的大小与卷组中逻辑卷块的大小相同。

LE (Logical Extent 逻辑块):

        逻辑卷按"块"为单位存储,在一卷组中的所有逻辑卷的块大小是相同的。

        OK,基本概念已经了解了,使用lvm基本流程就是:
         
        初始化物理卷---> 创建卷组,将PV加入到卷组中--->创建逻辑卷---->创建文件系统

1. 初始化物理卷 :

        在初始化物理卷之前,我已经清空了/dev/hda5,并且标识分区类型为83(linux分区)
       在LVM1中,必须将分区类型标识为8E(LVM分区)才可以使用,lvm2中没有这个限制。

        在创建之前,先修改下/etc/lvm/lvm.conf :
        # Exclude the cdrom drive
             filter = [ "r|/dev/cdrom|" ]

        找到上面两行,将filter前面的#去掉,这样创建LV时就不会搜寻/dev/cdrom了。
        不然也很烦,总是提示/dev/cdrom错误。修改好后,执行vgscan命令使生效.
        [root@NEWLFS LVM2.2.00.33]#vgscan

        使用pvcreate PV1 [PV2.....] 创建物理卷:

        [root@NEWLFS mnt]#pvcreate /dev/hda5
        Physical volume "/dev/hda5" successfully created
        [root@NEWLFS mnt]#

        使用 pvdisplay 查看PV详细信息:

    [root@NEWLFS mnt]#pvdisplay
         [code:1] --- Physical volume ---
          PV Name               /dev/hda5
          VG Name               lvm_vg
          PV Size               20.85 GB / not usable 0
          Allocatable           yes
          PE Size (KByte)       4096
          Total PE              5338
          Free PE               4076
          Allocated PE          1262
          PV UUID               y5LlEs-iBIY-t3PU-gTaT-ZIUt-iDmE-b9J9aC

        [root@NEWLFS mnt]#[/code:1]

        2.创建卷组,并将PV加入到卷组中:

        使用vgcreate  VGNAME PV1 [PV2......]创建卷组

        [root@NEWLFS mnt]#vgcreate lvm_vg /dev/hda5
          Volume group "lvm_vg" successfully created
        [root@NEWLFS mnt]#

        使用vgdisplay 查看VG详细信息:

        [root@NEWLFS mnt]#vgdisplay
       [code:1]   --- Volume group ---
          VG Name               lvm_vg
          System ID
          Format                lvm2
          Metadata Areas        1
          Metadata Sequence No  3
          VG Access             read/write
          VG Status             resizable
          MAX LV                0
          Cur LV                2
          Open LV               0
          Max PV                0
          Cur PV                1
          Act PV                1
          VG Size               20.85 GB
          PE Size               4.00 MB
          Total PE              5338
          Alloc PE / Size       1262 / 4.93 GB
          Free  PE / Size       4076 / 15.92 GB
          VG UUID               TFjqOG-5aHq-6SUz-q96N-Lu20-GrrP-Qvh2WM

        [root@NEWLFS mnt]#[/code:1]

        当重新启动或执行vgchange -a n 后,需要重新激活VG,才可以访问VG,LV

        [root@NEWLFS mnt]#vgchange -a y lvm_vg
          1 logical volume(s) in volume group "lvm_vg" now active
        [root@NEWLFS mnt]#

        当关机或不再使用VG时,使用 vgchage -a n VGNAME 使VG不可用。
         
        [root@NEWLFS mnt]#vgchange -a n lvm_vg
          0 logical volume(s) in volume group "lvm_vg" now active
        [root@NEWLFS mnt]#

       3. 创建逻辑卷:

        使用lvcreate -L Size -n NAME VGNAME 创建逻辑卷:

        [root@NEWLFS ~]#lvcreate -L 2G -n lv_home lvm_vg
          Logical volume "lv_home" created
        [root@NEWLFS ~]#

        使用lvdisplay 查看LV详细信息:

        [root@NEWLFS mnt]#lvdisplay
      [code:1]    --- Logical volume ---
          LV Name                /dev/lvm_vg/lv_usr
          VG Name                lvm_vg
          LV UUID                zrpaw1-vMdI-KvT2-4XlA-2TxZ-4iV8-38fN88
          LV Write Access        read/write
          LV Status              NOT available
          LV Size                2.93 GB
          Current LE             750
          Segments               1
          Allocation             inherit
          Read ahead sectors     0

          --- Logical volume ---
          LV Name                /dev/lvm_vg/lv_home
          VG Name                lvm_vg
          LV UUID                spGvLc-8lOM-CgAi-8XvI-E5Jt-xCce-l4B54K
          LV Write Access        read/write
          LV Status              available
          # open                 0
          LV Size                2.00 GB
          Current LE             512
          Segments               1
          Allocation             inherit
          Read ahead sectors     0
          Block device           253:0

        [root@NEWLFS mnt]#[/code:1]
        由于我之前已经创建了一个lv_usr 所以这里显示两个LV
                  

最后一步,创建文件系统。这里我使用ReiserFS 3.6.19 :

[root@NEWLFS mnt]#mkreiserfs /dev/lvm_vg/lv_home
[code:1]
        ..........略
        Continue (y/n):y
        Initializing journal -   0%....20%....40%....60%....80%....100%
        Syncing..ok

        Tell your friends to use a kernel based on 2.4.18 or later,
        and especially not a
        kernel based on 2.4.9, when you use reiserFS. Have fun.

        ReiserFS is successfully created on /dev/lvm_vg/lv_home.
        [root@NEWLFS mnt]#
[/code:1]
        创建挂载点,挂载它:
        [root@NEWLFS mnt]#mkdir lvm_usr lvm_home
        [root@NEWLFS mnt]#mount -t reiserfs /dev/lvm_vg/lv_home lvm_home/
        [root@NEWLFS mnt]#df
     [code:1]   Filesystem            Size  Used Avail Use% Mounted on
        /dev/md0              5.4G  2.8G  2.7G  51% /
        /dev/hda1             6.4G  4.0G  2.5G  62% /mnt/C
        /dev/hda6              25G   22G  3.6G  86% /mnt/E
        /dev/hda7             9.7G  3.7G  5.6G  40% /mnt/lfs
        /dev/hda8              99M   18M   76M  20% /boot
        /dev/hda10            6.7G  2.9G  3.4G  46% /mnt/mdk
        /dev/mapper/lvm_vg-lv_home
                              2.0G   33M  2.0G   2% /mnt/lvm_home
[root@NEWLFS mnt]#
[/code:1]
        
        OK,现在已经成功的创建好了逻辑卷,并且使用了ReiserFS,可以投入使用啦。
        下一部分说一下 如何管理LVM
        Have Fun !  
发表于 2005-2-15 19:20:33 | 显示全部楼层
最好能写一些VFS和LVM的区别!

一起来说比较好!
回复

使用道具 举报

发表于 2005-2-15 19:20:58 | 显示全部楼层
不过的确是好文章!
回复

使用道具 举报

 楼主| 发表于 2005-2-15 19:22:16 | 显示全部楼层
OK 继续  :D

下面说一下如何扩充,删除,管理它

使用lvextend -L size LVNAME 增大一个逻辑卷的大小。
[root@NEWLFS mnt]#lvextend -L +1G /dev/lvm_vg/lv_home
  Extending logical volume lv_home to 3.00 GB
  Logical volume lv_home successfully resized
[root@NEWLFS mnt]#                     
-L +1G 为lv_home加上 1G 空间。或者使用这种格式:
[root@NEWLFS mnt]#lvextend -L 3G /dev/lvm_vg/lv_home
指定lv_home更改后的大小,效果相同。

更改逻辑卷大小后,还应该更改文件系统的大小,保持一致:
[root@NEWLFS mnt]#resize_reiserfs -f /dev/lvm_vg/lv_home
[code:1]resize_reiserfs 3.6.19 (2003 www.namesys.com)

ReiserFS report:
blocksize             4096
block count           786432 (524288)
free blocks           778197 (516061)
bitmap block count    24 (16)

Syncing..done

resize_reiserfs: Resizing finished successfully.
[/code:1]
[root@NEWLFS mnt]df
Filesystem            Size  Used Avail Use% Mounted on
/dev/md0              5.4G  2.8G  2.7G  51% /
/dev/hda1             6.4G  4.0G  2.5G  62% /mnt/C
/dev/hda6              25G   22G  3.6G  86% /mnt/E
/dev/hda7             9.7G  3.7G  5.6G  40% /mnt/lfs
/dev/mapper/lvm_vg-lv_home
                      3.0G   33M  3.0G   2% /mnt/lvm_home
[root@NEWLFS mnt]#

成功的将lvm_home扩展到了3G,没有重新启动,并且没有卸载文件系统。
ReiserFS真是好用!  ^_^

当然,ReiserFS 也允许卸载文件系统后resize,使用下列命令:
[root@NEWLFS mnt]#umount /dev/lvm_vg/lv_home
卸载文件系统
[root@NEWLFS mnt]#resize_reiserfs /dev/lvm_vg/lv_home
调整大小,与上面不同的地方是没有 -f 参数.
[root@NEWLFS mnt]#mount -t reiserfs /dev/lvm_vg/lv_home lvm_home/
重新挂载上.

EXT2/3 安装,扩展:

[root@NEWLFS mnt]#lvcreate -L 2G -n lv_opt lvm_vg
  Logical volume "lv_opt" created
分出一块2G名字为lv_opt的逻辑卷

[root@NEWLFS mnt]#mke2fs -j /dev/lvm_vg/lv_opt
[code:1]mke2fs 1.35 (28-Feb-2004)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
262144 inodes, 524288 blocks
26214 blocks (5.00%) reserved for the super user
First data block=0
16 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912

Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 35 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.[/code:1]
创建ext3文件系统
[root@NEWLFS mnt]#mkdir lvm_opt
[root@NEWLFS mnt]#mount -t ext3 /dev/lvm_vg/lv_opt lvm_opt/
创建挂载点,挂载上。
[root@NEWLFS mnt]#df
[code:1]Filesystem            Size  Used Avail Use% Mounted
..............
/dev/mapper/lvm_vg-lv_home
                      3.0G   33M  3.0G   2% /mnt/lvm_home
/dev/mapper/lvm_vg-lv_opt
                      2.0G   33M  1.9G   2% /mnt/lvm_opt[/code:1]

[root@NEWLFS mnt]#lvextend -L +1G /dev/lvm_vg/lv_opt
  Extending logical volume lv_opt to 3.00 GB
  Logical volume lv_opt successfully resized
为lv_opt 增加一个G的空间。

[root@NEWLFS mnt]#umount lvm_opt/
调整ext2/3文件系统 需要先卸载,然后调整,不象ReiserFS可以不用卸载。

[root@NEWLFS mnt]#resize2fs /dev/lvm_vg/lv_opt
resize2fs 1.35 (28-Feb-2004)
Please run 'e2fsck -f /dev/lvm_vg/lv_opt' first.
提示先运行e2fsck -f 那就检查下吧
resize2fs -f 参数可以不用e2fsck,检查下也是好的。

[root@NEWLFS mnt]#e2fsck -f /dev/lvm_vg/lv_opt
[code:1]e2fsck 1.35 (28-Feb-2004)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/lvm_vg/lv_opt: 11/262144 files (0.0% non-contiguous), 16443/524288 blocks
[root@NEWLFS mnt]#resize2fs /dev/lvm_vg/lv_opt
resize2fs 1.35 (28-Feb-2004)
Resizing the filesystem on /dev/lvm_vg/lv_opt to 786432 (4k) blocks.
The filesystem on /dev/lvm_vg/lv_opt is now 786432 blocks long.[/code:1]
成功将lv_opt调整成3G,重新mount 看看吧 !

[root@NEWLFS mnt]#mount -t ext3 /dev/lvm_vg/lv_opt lvm_opt/
[root@NEWLFS mnt]#df
[code:1]Filesystem            Size  Used Avail Use% Mounted on
.............
/dev/mapper/lvm_vg-lv_home
                      3.0G   33M  3.0G   2% /mnt/lvm_home
/dev/mapper/lvm_vg-lv_opt
                      3.0G   33M  2.9G   2% /mnt/lvm_opt
[root@NEWLFS mnt]#[/code:1]
OK啦。 LVM真是方便 ^_^

再来看看如何减小分区大小:

注意: 减小逻辑卷大小之前,应该先减小文件系统的大小,否则可能会导致数据丢失


ReiserFS :
[root@NEWLFS mnt]#umount lvm_home/
首先卸载ReiserFS文件系统。

[root@NEWLFS mnt]#resize_reiserfs -s-1G /dev/lvm_vg/lv_home
[code:1]resize_reiserfs 3.6.19 (2003 www.namesys.com)

You are running BETA version of reiserfs shrinker.
This version is only for testing or VERY CAREFUL use.
Backup of you data is recommended.

Do you want to continue? [y/N]:y
Processing the tree: 0%....20%....40%....60%....80%....100%    left 0, 0 /sec

nodes processed (moved):
int        0 (0),
leaves     1 (0),
unfm       0 (0),
total      1 (0).

check for used blocks in truncated region

ReiserFS report:
blocksize             4096
block count           524288 (786432)
free blocks           516061 (778197)
bitmap block count    16 (24)

Syncing..done

resize_reiserfs: Resizing finished successfully.[/code:1]

先减小文件系统的大小, -s-1G 减去1个G

[root@NEWLFS mnt]#lvreduce -L -1G /dev/lvm_vg/lv_home
WARNING: Reducing active logical volume to 2.00 GB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce lv_home? [y/n]: y
  Reducing logical volume lv_home to 2.00 GB
  Logical volume lv_home successfully resized
然后减小LV大小, -L -1G 减去1个G 与文件系统保持一致。

[root@NEWLFS mnt]#mount -t reiserfs /dev/lvm_vg/lv_home lvm_home/
[root@NEWLFS mnt]#df
[code:1]Filesystem            Size  Used Avail Use% Mounted on
/dev/md0              5.4G  2.8G  2.7G  51% /
/dev/hda1             6.4G  4.0G  2.5G  62% /mnt/C
/dev/hda6              25G   22G  3.6G  86% /mnt/E
/dev/hda7             9.7G  3.7G  5.6G  40% /mnt/lfs
/dev/mapper/lvm_vg-lv_opt
                      3.0G   33M  2.9G   2% /mnt/lvm_opt
/dev/mapper/lvm_vg-lv_home
                      2.0G   33M  2.0G   2% /mnt/lvm_home[/code:1]

OK,成功减少了一个G,从上面输出可以看出,减小要比增大危险一些
所以应该尽量避免减小分区大小,以及做重要数据的备份,有备无患嘛

EXT2/3:

在LVM1中可以通过e2fsadm这个程序,方便的减小一个ext2/3的大小。
而LVM2中这个程序不可用。
所以在LVM2中减小EXT2/3大小时麻烦一些,因为必须要知道减少后卷的块数。

[root@NEWLFS ~]#umount /mnt/lvm_opt/
首先卸载文件系统
[root@NEWLFS ~]#mke2fs -n /dev/lvm_vg/lv_opt
[code:1]mke2fs 1.35 (28-Feb-2004)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
262144 inodes, 786432 blocks
26214 blocks (5.00%) reserved for the super user
First data block=0
16 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912
[root@NEWLFS ~]#[/code:1]
因为必须知道减少后卷的块数,所以通过mke2fs -n 列出块大小

注意: -n 参数不会使mke2fs真的创建文件系统,而只是列出文件系统的信息。

千万不要少了-n 否则数据就全没了。。

块大小是4096(4kb) 当前有786432个blocks 现在打算减小一个G的空间。
1G占用的blocks一共是262144个,所以减少后的blocks应该是524288个。

减小FS大小:
[root@NEWLFS ~]#resize2fs /dev/lvm_vg/lv_opt 524288
resize2fs 1.35 (28-Feb-2004)
Resizing the filesystem on /dev/lvm_vg/lv_var to 524288 (1k) blocks.
The filesystem on /dev/lvm_vg/lv_var is now 524288 blocks long.
减少LV大小:
[root@NEWLFS mnt]#lvreduce -L -1G /dev/lvm_vg/lv_var
  WARNING: Reducing active logical volume to 2.00 GB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce lv_var? [y/n]: y
  Reducing logical volume lv_var to 2.00 GB
  Logical volume lv_var successfully resized
ok,成功缩小了1G,再重新mount上吧。

[root@NEWLFS mnt]#mount /dev/lvm_vg/lv_var lvm_var/
[root@NEWLFS mnt]#df
..........
/dev/mapper/lvm_vg-lv_var
                      2.0G   33M  1.9G   2% /mnt/lvm_var
[root@NEWLFS mnt]#

下面再来看看如何删除LV,VG :


删除LV:
[root@NEWLFS mnt]#umount /dev/lvm_vg/lv_opt
必须先关闭LV才可以删除它。
[root@NEWLFS mnt]#lvremove /dev/lvm_vg/lv_opt
Do you really want to remove active logical volume "lv_opt"? [y/n]: y
  Logical volume "lv_opt" successfully removed
[root@NEWLFS mnt]
使用lvremove命令删除一个逻辑卷,这里删除了lv_opt.

删除VG:
首先必须确保VG中没有任何逻辑卷存在,才可以删除一个VG。
我已经使用lvremove 删除了lv_usr lv_home。
[root@NEWLFS mnt]#lvdisplay
[root@NEWLFS mnt]#
没有任何输出,说明已经没有lv了。

[root@NEWLFS mnt]#vgchange -a n lvm_vg
  0 logical volume(s) in volume group "lvm_vg" now active
使用vgchange -a n 关闭了lvm_vg,然后才可以删除它。

[root@NEWLFS mnt]#vgremove lvm_vg
  Volume group "lvm_vg" successfully removed
干掉了 ....世界清静了 ^_^

[root@NEWLFS mnt]#vgdisplay
[root@NEWLFS mnt]#                    
没有回显,说明已经没有任何VG了。

向VG中添加/删除PV :

上面已经提到了,VG可以由多个PV组成(hda1,hda3,hda5....)
可以使不相邻的分区,结合在一起使用。(和线性RAID同样的作用)

来看看如何向VG中添加PV:

因为我没有多余的物理设备来演示,所以用到了loop设备。
首先我通过
[root@NEWLFS ~]#dd if=/dev/zero of=/root/lvm bs=4096 count=32768
在/root目录下创建了一个128M的文件(/root/lvm)
然后用losetup 命令挂在了/dev/loop0上,这样我的loop0就象/dev/hdaX一样
是一个可用的块设备了。loop设备真是不错,用来做实验很好,比如试试reiserfs
raid,LVM.....练习好了,再在真实分区上实践。

看看我是怎么使用的
[root@NEWLFS ~]#losetup /dev/loop0 lvm
将刚刚建立的lvm文件挂在了/dev/loop0中,这样loop0可以象其他物理设备可以使用了。
初始化loop0 为PV:
[root@NEWLFS ~]#pvcreate /dev/loop0
  Physical volume "/dev/loop0" successfully created
[root@NEWLFS ~]#

使用vgextend命令将/dev/loop0添加到lvm_vg中:
[root@NEWLFS ~]#vgextend lvm_vg /dev/loop0
  Volume group "lvm_vg" successfully extended
[root@NEWLFS ~]#
成功的将/dev/loop0加入到了lvm_vg中。下面就可以创建LV啦。
[root@NEWLFS ~]#lvcreate -L 128M -n loop_lv lvm_vg /dev/loop0
  Insufficient allocatable logical extents (31) for logical volume loop_lv: 32 required
加上/dev/loop0表示指定这个LV只在/dev/loop0中,可能因为LE自身占用空间,所以无法分配128M
[root@NEWLFS ~]#lvcreate -L 100M -n loop_lv lvm_vg /dev/loop0
  Logical volume "loop_lv" created
[root@NEWLFS ~]#
100M就可以成功创建了,可以看出,loop_lv这个LV完全在/dev/loop0上。

删除PV:

必须确保要删除的PV中没有被任何LV使用
使用 pvdisplay /dev/loop0 查看 (假设loop0是要删除的pv)

[root@NEWLFS ~]#pvdisplay /dev/loop0
[code:1] --- Physical volume ---
  PV Name               /dev/loop0
  VG Name               lvm_vg
  PV Size               124.00 MB / not usable 0
  Allocatable           yes
  PE Size (KByte)       4096
  Total PE              31
  Free PE               31 ---->FreePE=TotalPE
  Allocated PE          0------>占用的PE为0 说明loop0上没有lv
  PV UUID               K38G8y-G6b7-81O0-SFz5-HZii-Rp6t-sHq4ou
[root@NEWLFS ~]#[/code:1]

如果仍然有LV使用该物理卷,可以通过 pvmove 命令转移到另一个PV上,pvmove使用方法请参考相关文档。
然后使用vgreduce命令 删除PV :

[root@NEWLFS ~]#vgreduce lvm_vg /dev/loop0
  Removed "/dev/loop0" from volume group "lvm_vg"
[root@NEWLFS ~]#
成功将/dev/loop0从lvm_vg中删除,很简单吧 ^_^                  

系统启动时自动加载LVM分区:

修改/etc/fstab 加入LVM分区 以及挂载点,FS类型等。。。。
[code:1]
/dev/lvm_vg/lv_home /mnt/lvm_home reiserfs defaults 0 0
/dev/lvm_vg/lv_opt  /mnt/lvm_opt  ext3     defaults 0 0[/code:1]

然后需要在系统启动脚本中加入激活LVM的命令
并且必须在挂载/etc/fstab中的文件系统之前激活LVM,不然怎么挂载阿。^_^
我写在了/etc/rc.d/init.d/mountfs这个脚本中,它的作用是
在fsck检查各个分区后,将/分区及其他分区重新挂载成read-write的

/sbin/vgscan  -------->需要加入的两行
/sbin/vgchange -a y


mountfs脚本主要内容是:(传递start参数)

[code:1]echo "Remounting root file system in read-write mode..."
mount -n -o remount,rw /
echo "Recording existing mounts in /etc/mtab..."
                > /etc/mtab
                mount -f / || failed=1
                mount -f /proc || failed=1
                if grep -q '[[:space:]]sysfs' /proc/mounts ; then
                        mount -f /sys || failed=1
                fi
echo "Mounting remaining file systems..."
                ##############LVM##############
                /sbin/vgscan  #------->在挂载其他文件系统之前
                /sbin/vgchange -a y #---->就激活了LVM,随后就挂载上啦
                mount -a -O no_netdev #--->依照/etc/fstab挂载FS[/code:1]

这样系统启动时,就会激活LVM,并自动挂载上。

一篇关于LVM的文章中说,将这两条命令加在了检查文件系统脚本中,但是我加在那里
不成功,可能因为在checkfs时,系统是read-only的,而vgchange -a y
需要写入数据却无法写入,所以不行.

udev服务先于checkfs启动,并且通过mount -n -t ramfs ramfs /dev
将/dev挂载成ramfs,完全在内存中活动,无论根分区是否可写,/dev都是可写的。
莫非vgchange -a y 还要向其他位置写入数据?有待研究

在其他的发行版中,如Red Hat,Mandrake中,检查根文件系统,依照/etc/fstab
挂载各个文件系统,开启SWAP分区...等等,这些都是通过/etc/rc.d/rc.sysinit完成的
而在LFS中则是将这个脚本 分成了若干的小脚本,然后逐一的运行它们。
个人认为这样可以更直观的了解系统的启动过程,方便修改。
所以在其他发行版中,激活lvm,就要写到/etc/rc.d/rc.sysinit中
并且必须要在挂载/etc/fstab中文件系统之前激活。还要注意激活时,系统是rw的。

最后我又在mountfs中添加了关闭VG的语句,这样可以
在系统关机/重启的时候自动关闭VG。

/sbin/vgchange -a n ------>添加这句

当系统关机/重启时,mountfs会依照/etc/fstab卸载所有的文件系统:
mountfs 脚本内容 : (传递stop参数)

[code:1]echo "Unmounting all other currently mounted file systems..."
umount -a -d -r -t noramfs
/sbin/vgchange -a n # --->加在了这里[/code:1]

在卸载LV卷后,才可以关闭VG,开始我加在了umount上面一行就不行。提示仍有LV在使用。
其他发行版中,关闭VG要比激活VG容易多啦。只要加在halt/reboot这个服务脚本里就可以。
其实只要卸载文件系统后的服务脚本都可以,随你喜欢了。  :D
回复

使用道具 举报

发表于 2005-2-15 19:56:42 | 显示全部楼层
6692975,好样的。
回复

使用道具 举报

 楼主| 发表于 2005-2-15 20:16:30 | 显示全部楼层
谢谢各位大侠支持,小弟不胜感激!

记得看ext2文档时有写到VFS,好象它是linux最底层的文件系统吧?
不太了解
回复

使用道具 举报

发表于 2005-2-15 20:37:36 | 显示全部楼层
好像不是,还没到物理层。
说错了不要打我哦
回复

使用道具 举报

发表于 2005-2-15 22:15:57 | 显示全部楼层
VFS虚拟文件系统
回复

使用道具 举报

发表于 2005-2-15 22:19:30 | 显示全部楼层
虚拟文件系统
蓝森林 http://www.lslnet.com 2001年5月20日 21:16

作 者: difeijing

Richard Gooch <[email protected]>
23-APR-1999
翻译:difeijing <[email protected]>

本文档中的惯例用法 <section>
==================
文档中的每一节标题的右边都有一个字符串"<section>"。
每个小节都会有个"<subsection>"在右边。
这些字符串是为了在文档中查询更容易而设的。

注意:本文档的最新更新可在下面找到:
http://www.atnf.csiro.au/~rgooch/linux/docs/vfs.txt


它到底是什么? <section>
=============
Virtual File System(或者被称为Virtual Filesystem Switch)是Linux内核中的一个软件层,用于给用户空间的程序提供文件系统接口。它也提供了内核中的一个抽象功能,允许不同的文件系统共存。


它的工作方式的概览 <section>
==================
在这一节里,在讲解细节问题之前,我会简单扼要的介绍一下VFS是如何工作的。首先,介绍一下当用户程序打开或者操作文件时发生了些什么,然后看看一个文件系统是如何被支持的。

打开一个文件 <subsection>
------------
VFS实现了open(2)系统调用。路径参数被VFS用来在目录入口缓存(dentry cache or "dcache")。这提供了一个将路径名转化为特定的dentry的一个快的查找机制。

一个单独的dentry通常包含一个指向i节点(inode)的指针。i节点存在于磁盘驱动器上,它可以是一个规则文件,目录,FIFO文件,等等。Dentry存在于RAM中,并且永远不会被存到磁盘上:它们仅仅为了提高系统性能而存在。i节点存在于磁盘上,当需要时被拷入内存中,之后对它的任何改变将被写回磁盘。存在于RAM中的i节点就是VFS的i节点,dentry所包含的指针指向的就是它。

dcache是你的整个文件空间的观察点。跟Linus不同,我们中的大多数人不可能有足够的RAM空间来放我们的文件空间的所有文件的目录入口缓存(dentry),所以我们的dcache会有缺少的项。为了将路径名转换为一个dentry,VFS不得不采取创建dentry的方式,并在创建dentry时将指针指向相应的i节点。这是通过对i节点的查找完成的。

为了查找一个文件的i节点(通常从磁盘上读),VFS需要调用该文件的父目录的lookup()方法,此方法是特定的文件系统所设置的。后面对此将会有更详尽的描述。

一旦VFS得到了所需要的dentry(同时也得到了相应的i节点),我们就能够对文件做想要的操作:打开文件,或者用stat(2)来看 i节点中的数据。stat(2)的操作非常简单:在VFS得到dentry之后,它取得inode中的一些数据并将其中的一部分送回用户空间。打开一个文件需要其它的操作:分配一个struct file(定义于linux/fs.h,这是内核中的文件描述)结构。新分配的struct file结构被指向dentry的指针和对文件进行操作的函数集合所初始化,这些都是从i节点中得到的。通过这种方式,特定的文件系统实现才能起作用。

文件结构(struct file)被放在进程的文件描述符表中。

读,写和关闭文件(或者其它的VFS操作)是通过使用用户空间的文件描述符找到相应的文件结构(struct file),然后调用所需要的方法函数来实现的。

当文件处于打开状态时,系统保持相应的dentry为"open"状态(正在使用),这表示相应的i节点在被使用。


注册和安装一个文件系统 <subsection>
----------------------
如果你想在内核中支持一种新的文件系统的话,你所需要做的仅仅是调用函数register_filesystem().你向内核中传递一个描述文件系统实现的结构(struct filesystem), 此结构将被加入到内核的支持文件系统表中去。你可以运行下面的命令:
% cat /proc/filesystems
这样可以看到你的系统支持哪些文件系统。

当一个mount请求出现时,VFS将会为特定的文件系统调用相应的方法。安装点的dentry结构将会被改为指向新文件系统的根i节点。

现在是看看细节的时候了,nice to look!


struct file_system_type <section>
=======================
此结构描述了文件系统。在内核2.1.99中,此结构的定义如下:
(注:在2.2的内核中,此结构也没有变化)
struct file_system_type {
const char *name;
int fs_flags;
struct super_block *(*read_super) (struct super_block *, void *, int);
struct file_system_type * next;
};

其中各个域的意义:
name:文件系统的类型名称,如"vfat","ext2",等等。
fs_flags:变量标志,如FS_REQUIRES_DEV, FS_NO_DCACHE,等等.
read_super:当此种文件系统的一个新的实例要被安装时,此方法会被调用。
next:被内部的VFS实现所使用,你只需要将其初试化为NULL。

函数read_super具有以下的参数:
struct super_block *sb:超级块结构。此结构的一部分被VFS初始化,余下的部分必须被函数read_super初始化。
void * data:任意的安装选项,通常是ASCII的字符串。
int silent:表示当出现错误时是否保持安静。(不报警?)

read_super方法必须确定指定的块设备是否包含了一个所支持的文件系统。当成功时返回超级块结构的指针,错误时返回NULL。

read_super方法填充进超级块结构(struct super_block)的最有用的域是"s_op"域。这是一个指向struct super_operations的指针,此结构描述了文件系统实现的下一层细节。

struct super_operations <section>
=======================
此结构描述了VFS对文件系统的超级块所能进行的操作。
在内核2.1.99中,此结构的定义如下:
(注:在2.2的内核中,此结构已经有了改变)
struct super_operations {
void (*read_inode) (struct inode *);
void (*write_inode) (struct inode *);
void (*put_inode) (struct inode *);
void (*delete_inode) (struct inode *);
int (*notify_change) (struct dentry *, struct iattr *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*statfs) (struct super_block *, struct statfs *, int);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
};

除非特别提出,所有的方法都在未加锁的情况下被调用,这意味着大多数方法都可以安全的被阻塞。所有的方法都仅仅在进程空间被调用(例如,在中断处理程序和底半部中不能调用它们)

read_inode:从一个文件系统中读取一个特定的i节点时调用此方法。i节点中的域"i_ino"被VFS初始化为指向所读的i节点,其余的域被此方法所填充。

write_inode:当VFS需要向磁盘上的一个i节点写时调用。

put_inode:当VFS的i节点被从i节点缓冲池移走时被调用。此方法是可选的。

delete_inode:当VFS想删除一个i节点时调用次方法。

notify_change:当VFS的i节点的属性被改变时调用。若此域为NULL则VFS会调用rite_inode.此方法调用时需要锁住内核。
put_super:当VFS要释放超级块时调用(umount一个文件系统).此方法调用时需要锁住内核。

write_super:当VFS超级块需要被写入磁盘时被调用。此方法为可选的。

statfs:当VFS需要得到文件系统的统计数据时调用。此方法调用时需要锁住内核。

remount_fs:当文件系统被重新安装时调用。此方法调用时需要锁住内核。

clear_inode:当VFS清除i节点时调用。可选项。

以上方法中,read_inode需要填充"i_op"域,此域为一个指向struct inode_operations结构的指针,它描述了能够对一个单独的i节点所能进行的操作。


struct inode_operations <section>
=======================
此结构描述了VFS能够对文件系统的一个i节点所能进行的操作。
在内核2.1.99中,此结构的定义如下:
(注:在2.2的内核中,此结构已经有了少许改变)
struct inode_operations {
struct file_operations * default_file_ops;
int (*create) (struct inode *,struct dentry *,int);
int (*lookup) (struct inode *,struct dentry *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
int (*mkdir) (struct inode *,struct dentry *,int);
int (*rmdir) (struct inode *,struct dentry *);
int (*mknod) (struct inode *,struct dentry *,int,int);
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
int (*readlink) (struct dentry *, char *,int);
struct dentry * (*follow_link) (struct dentry *, struct dentry *);
int (*readpage) (struct file *, struct page *);
int (*writepage) (struct file *, struct page *);
int (*bmap) (struct inode *,int);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
int (*smap) (struct inode *,int);
int (*updatepage) (struct file *, struct page *, const char *,
unsigned long, unsigned int, int);
int (*revalidate) (struct dentry *);
};

default_file_ops:这是一个指向struct file_operations的指针,包含了对一个打开的文件所能进行的操作。

create:被open(2)和creat(2)所调用,仅仅在你要支持普通文件时才需要。参数中的dentry不应该包含有i节点的指针(即应该为一个negative dentry)。这里你可能需要对传入的dentry和i节点调用函数d_instantiate.

lookup:当VFS要在一个父目录中查找一个i节点时调用。待查找的文件名在dentry中。此方法必须调用d_add函数把找到的 i节点插入到dentry中,i节点的"i_count"域要加一。若指定的i节点不存在的话,一个NULL的i节点指针将被插入到dentry中去(这种情况的dentry被称为negative dentry)。Returning an error code from this routine must only be done on a real error, otherwise creating inodes with system calls like create(2), mknod(2), mkdir(2) and so on will fail.If you wish to overload the dentry methods then you should initialise the "d_dop" field in the dentry; this is a pointer to a struct "dentry_operations".This method is called with the directory semaphore held。

link:被link(2)所调用。仅在你需要支持hard link时才需要它。跟create方法相同的原因,你可能在此方法中也需要调用d_instantiate()函数来验证。

unlink:被unlink(2)所调用。仅在你要支持对i节点的删除时才需要它。

symlink:被symlink(2)调用。仅在需要支持符号链接时才需要它。通上面两处,你需要对传入的参数进行验证,要调用d_instantiate()函数。

mkdir:被mkdir(2)调用。仅在你要支持建立子目录时才需要它。同上,你需要调用d_instantiate()函数进行验证。

rmdir:被rmdir(2)所调用。仅在你要支持对子目录的删除时才需要它。

mknod:被mknod(2)所调用,用于建立一个设备i节点,或者FIFO,或socket.仅当你需要支持对这些类型的i节点的建立时才需要此方法。同上面几个,你可能也需要调用_instantiate来验证参数。

readlink:被readlink(2)调用。仅当你要支持对符号链接的读取才需要它。

follow_link:被VFS调用,用以从一个符号链接找到相应的i节点。仅当你需要支持符号链接时才需要此方法。


struct file_operations <section>
======================
结构file_operations包含了VFS对一个已打开文件的操作。
在内核2.1.99中,此结构的定义如下:
(注:在2.2的内核中,此结构已经有了少许改变)
struct file_operations {
/*在VFS需要移动文件位置指针时被调用 */
loff_t (*llseek) (struct file *, loff_t, int);
/* 被read系统调用所使用 */
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
/* 被write系统调用所使用 */
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *);
int (*fasync) (struct file *, int);
int (*check_media_change) (kdev_t dev);
int (*revalidate) (kdev_t dev);
int (*lock) (struct file *, int, struct file_lock *);
};

llseek:当VFS需要移动文件指针的位置时调用。

read:被read(2)所调用。

write:被write(2)所调用。

readdir:当VFS需要读取目录中的内容时被调用。

poll: called by the VFS when a process wants to check if there is activity on this file and (optionally) go to sleep until there is activity.
(注:这里我怎么想都翻不好,所以就把原文放在这里了,poll就是相当于select的东西)

ioctl:被ioctl(2)所调用。

mmap:被mmap(2)所调用。

open:当VFS要打开一个i节点时调用它。当VFS打开一个文件时,它建立一个新的struct file结构,并用i节点中的"default_file_ops"来初始化其中的f_op域,然后对新分配的文件结构调用open方法。你可以认为 open方法实际上属于struct inode_operations。I think it's done the way it is because it makes filesystems simpler to implement.open方法是一个很好的初始化文件结构中的"private_data"域的的地方。

release:当没有对被打开文件的引用时调用此方法。

fsync:被fsync(2)所调用。

fasync:当用fcntl(2)激活一个文件的异步模式时此方法被调用。

这些文件操作是由i节点所在的特定文件系统所实现的。当打开一个设备节点时(字符或块设备特殊文件),大多数文件系统会调用VFS中的特定支持例程,由此来找到所需要的设备驱动信息;

这些支持例程用设备驱动程序的方法来代替文件系统的文件操作,然后继续对文件调用新的open方法。这就是为什么当你打开文件系统上的一个设备特殊文件时,最后被调用的却是设备驱动程序的open方法。另外,devfs(Device Filesystem)有一个从设备节点到设备驱动程序的更直接的方式(这是非官方的内核补丁)


struct dentry_operations <section>
========================
This describes how a filesystem can overload the standard dentry
operations.Dentries和dcache是属于VFS和单个文件系统实现的,设备驱动与此无关。
在内核2.1.99中,此结构的定义如下:
(注:在2.2的内核中,此结构没有改变)
struct dentry_operations {
int (*d_revalidate)(struct dentry *);
int (*d_hash) (struct dentry *, struct qstr *);
int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
void (*d_delete)(struct dentry *);
void (*d_release)(struct dentry *);
void (*d_iput)(struct dentry *, struct inode *);
};

d_revalidate:当VFS要使一个dentry重新生效时被调用。

d_hash:当VFS向哈希表中加入一个dentry时被调用。

d_compare:当指向一个dentry的最后的引用被去除时此方法被调用,因为这意味这没有人在使用此dentry;当然,此dentry仍然有效,并且仍然在dcache中。

d_release: 当一个dentry被清除时调用此方法。

d_iput:当一个dentry释放它的i节点时(在dentry被清除之前)此方法被调用。The default when this is NULL is that the VFS calls iput(). If you define this method, you must call iput() yourself.

每个dentry都有一个指向其父目录dentry的指针,一个子dentry的哈希列表。子dentry基本上就是目录中的文件。

dget:为一个已经存在的dentry打开一个新的句柄(这仅仅增加引用计数)

dput:关闭一个dentry的句柄(减少引用计数).如果引用计数减少为0,d_delete方法将会被调用;并且,如果此 dentry仍然在其父目录的哈希列表中的话,此dentry将被放置于一个未被使用的列表中。将dentry放置于未使用表中意味着当系统需要更多的 RAM时,将会遍历未使用的dentry的列表,并回收其内存空间。假如当detry的引用计数为0时,它已经没有在父目录的哈希表中的话,在 d_delete方法被调用之后系统就会回收起内存空间。

d_drop: 此方法将一个dentry从其父目录的哈希列表中去掉。如果被去掉的dentry的引用计数降为0的话,系统会马上调用d_put来去掉此dentry.

d_delete:删除一个dentry.如果没有别的对此dentry的打开引用的话,此dentry会变成一个negative dentry(d_iput方法会被调用);如果有别的对此dentry的引用的话,将会调用d_drop.

d_add:向父目录的哈希列表中加入一个dentry,然后调用d_instantiate().

d_instantiate:把一个dentry加入别名哈希列表中,并更新其d_inode域为所给的i节点。i节点中的i_count 域加一。假如i节点的指针为NULL,此dentry就被称为"negative dentry".此函数通常在为一个已存在的negative dentry建立i节点时被调用。


注:第一次做翻译,可能有很多地方做得不好,还希望大家多批评指正。我以前看过很多前辈的翻译文章,从中获益匪浅,也很感激这些前辈们的无私奉献。现在自己能看懂一些东西了,也希望自己能为别人尽一份力,正好我的毕业设计又跟这个有点关系,于是就有了这篇译文,不过水平太差,大家不要扔鸡蛋番茄。有些地方我觉得实在翻不好,就把原文放上去了,实在是能力有限。如果有什么错误或者疏漏的话,请mail: [email protected].希望能对别人有帮助而不是误导。
回复

使用道具 举报

发表于 2005-2-15 22:45:01 | 显示全部楼层
公社的服务器什么时候好的? 好久都访问不了, lvm类似于win下面的动态卷, 对于做服务器的朋友很有用, 特别是碰到类似于cvs这种分区, 如果开发程序到一半因为cvs root分区不够大,身为网管的你肯定很头大的.
回复

使用道具 举报

发表于 2005-2-15 22:51:32 | 显示全部楼层
[quote:f021c2bfd6="linky_fan"]公社的服务器什么时候好的? 好久都访问不了, lvm类似于win下面的动态卷, 对于做服务器的朋友很有用, 特别是碰到类似于cvs这种分区, 如果开发程序到一半因为cvs root分区不够大,身为网管的你肯定很头大的. [/quote]

估计7点左右,我有一个链接是这里的今天早上上的时候发现突然能用了!不过当时还访问不了主页!
回复

使用道具 举报

发表于 2005-2-18 20:24:17 | 显示全部楼层
估计7点左右,我有一个链接是这里的今天早上上的时候发现突然能用了!不过当时还访问不了主页!

发现公社的服务器也喜欢过节(大家一块休息哈)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-5-23 23:30 , Processed in 0.202308 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表