UBIFS文件系统简介:

无排序区块图像文件系统(UnsortedBlock Image File System, UBIFS)是用于固态硬盘存储设备上,并与LogFS相互竞争,作为JFFS2的后继文件系统之一。真正开始开发于2007年,并于2008年10月第一次加入稳定版本于Linux核心2.6.27版。UBIFS最早在2006年由IBMNokia的工程师Thomas
Gleixner,ArtemBityutskiy所设计,专门为了解决MTD(MemoryTechnology Device)设备所遇到的瓶颈。由于Nand Flash容量的暴涨,YAFFS等皆无法再去控制Nand Flash的空间。UBIFS通过子系统UBI处理与MTD
device之间的动作。与JFFS2一样,UBIFS建构于MTD device之上,因而与一般的block
device不兼容。JFFS2运行在MTD设备之上,而UBIFS则只能工作于UBIvolume之上。也可以说,UBIFS涉及了三个子系统:

1.      MTD 子系统, 提供对flash芯片的访问接口,MTD子系统提供了MTD device的概念,比如/dev/mtdx,MTD可以认为是raw flash

2.      UBIsubsystem,为flash device提供了wear-leveling和 volume management功能; UBI工作在MTD设备之上,提供了UBI volume;UBI是MTD设备的高层次表示,对上层屏蔽了一些MTD不得不处理的问题,比如wearing以及坏块管理

3.      UBIFS文件系统,工作于UBI之上,必须在Device Drivers中选择支持MTD

以下是UBIFS的一些特点:

Ø     可扩展性:UBIFS对flash 尺寸有着很好的扩展性; 也就是说mount时间,内存消耗以及I/O速度都不依赖与flash 尺寸(对于内存消耗并不是完全准确的,但是依赖性非常的低);UBIFS可以很好的适应GB flashes;  当然UBI本身还有扩展性的问题,无论如何
UBI/UBIFS都比JFFS2的可扩展性好,此外如果UBI成为瓶颈,还可以通过升级UBI而不需改变UBIFS

Ø     快速mount:不像JFFS2,UBIFS在mount阶段不需要扫描整个文件系统,UBIFS mount介质的时间只是毫秒级,时间不依赖与flash的尺寸;然而UBI的初始化时间是依赖flash的尺寸的,因此必须把这个时间考虑在内

Ø     write-back支持:回写或者叫延迟写更准确些吧,同JFFS2的write-through(立即写入内存)相比可以显著的提高文件系统的吞吐量。

Ø     异常unmount适应度:UBIFS是一个日志文件系统可以容忍突然掉电以及unclean重启; UBIFS 通过replay 日志来恢复uncleanunmount,在这种情况下replay会消耗一些时间,因此mount时间会稍微增加,但是replay过程并不会扫描整个flash介质,所以UBIFS的mount时间大概在几分之一秒。

Ø     快速I/O - 即使我们disablewrite-back(可以在unmount时使用-o syncmount选项), UBIFS的性能仍然接近JFFS2;记住,JFFS2的同步I/O是非常惊人的,因为JFFS2不需要在flash上维护indexing data结构, 所以就没有因此而带来的负担; 而UBIFS恰恰是有index数据的。 UBIFS之所以够快是因为UBIFS提交日志的方式:不是把数据从一个地方移动到另外一个位置,而只是把数据的地址加到文件系统的index,然后选择不同的eraseblock作为新的日志块,此外还有multi-headed日志方式等技巧。

Ø     on-the_flightcompression -
存储在flash介质上的数据是压缩的;同时也可以灵活的针对单个文件来打开关闭压缩; 例如,可能需要针对某个特定的文件打开压缩,或者可能缺省方式下支持压缩,但是对多媒体文件则关闭压缩。

Ø     可恢复性 - UBIFS可以从index破坏后恢复; UBIFS中的每一片信息都有一个header来描述,因此可以通过扫描这个flash介质来重构文件系统,这点和JFFS2非常类似;想像一下,如果你擦出了FAT文件系统的FAT表,那么对于FAT FS是致命的错误,但是如果擦除UBIFS的index,你人然可以重构文件系统,当然这需要一个特定的用户空间程序来做这个恢复

Ø     完整性 - UBIFS通过写checksum到flash 介质上来保证数据的完整性,UBIFS不会无视损坏文件数据或meta-data;缺省的情况,UBIFS仅仅检查meta-data的CRC,但是你可以通过mount选项,强制进行data CRC的检查

UBIFS文件系统制作过程:

1,添加内核支持(linux-3.8.0):

Device Drivers  --->

<*> Memory Technology Device (MTD) support  --->

<*>   Enable UBI - Unsorted block images  --->

--- Enable UBI - Unsorted block images

(4096) UBI wear-leveling threshold

(1)   Maximum expected bad eraseblock count per 1024 eraseblocks

[ ]   UBI Fastmap (Experimental feature)

< >   MTD devices emulation driver (gluebi)

File systems  --->

[*] Miscellaneous filesystems  --->

<*>   UBIFS file system support

[*]     Advanced compression options

[*]       LZO compression support

[*]       ZLIB compression support

make编译即可

2,制作文件UBIFS文件系统镜像

mkfs.ubifs工具制作的文件系统映像,在uboot中烧录这种映像文件的方式过于复杂,既要使uboot支持nandflash分区,又要在uboot中激活这个分区,并通过ubi write命令烧录这个映像。为便于移植,需要用到 mkfs.ubifs,ubinize工具,它的作用是将mkfs.ubifs制作的映像转换为可以直接用nand
write命令烧录的映像文件。

由于制作mkfs.jffs2和mkfs.ubifs工具,会同时生成ubinize工具,自己就是按照脚本制作的工具和生成UBIFS文件系统镜像。

(1)制作mkfs.jffs2和mkfs.ubifs工具的链接:http://blog.csdn.net/fulinus/article/details/8860836

(2)生成UBIFS的脚本:

注意两点:

mkfs.ubifs工具需要明确的参数:

m:页大小,如上:2K

x: 镜像压缩格式,可选 LZO

e:逻辑可擦除块大小

c: 最多逻辑可擦除数目

r(或d):指定根文件目录树

o:指定生产文件名

ubinize工具需要明确的参数:

需要指定一个配置文件,格式如下:

[ubifs-volume]

mode=ubi

image=filename //文件名称,即mkfs.ubifs文件制作生产文件

vol_id=0

vol_size= filesize //文件大小,按实际情况来定

vol_type=dynamic

vol_name=rootfs

vol_flags=autoresize

vol_alignment=1

m: 页大小,2k

p: 物理块擦除大小

s:一般和页大小一样 2k

v:头部大小,一般是512

o: 指定输出文件

mkfs.ubifs和ubinize用法参考链接:

http://wenku.baidu.com/link?url=ZjS_qifTxWr68prdj780aT6yFp0rD8IbZGFvbT0ASwUhZbvdQBBzyIGTp_d5bbJx5IAb4TJX4CDmdUJ26mRwn2hij7G58X-WHPZVYCpR1MG

UBIFS文件系统介绍:

http://wenku.baidu.com/view/eebeacd9a58da0116c174991.html

制作脚本:

[zhouguangfeng@localhost ubifs]$ vim build_ubifs.sh

#!/bin/sh

CPU=zhou

rootfs_dir=../rootfs //指定根文件目录,根据根文件目录树而定

partition_sizeM=40

image_name=rootfs_${CPU}.ubifs





if [ ! -d $rootfs_dir ] ; then

    echo "Miss rootfs source code tree \"$rootfs_dir\" exit..."

    exit;

fi

#Default setting by UBIFS

sub_page_size=512

vid_head_offset=512





#-m, minimum I/O unit size, it's 2K(the Page size) on K9F2G08, refer to "UBI: smallest flash I/O unit:    2048" 

page_size_in_bytes=2048

#echo "Page size [$page_size_in_bytes] bytes."





#It's 64 pages per block on K9F2G08

pages_per_block=64

block_size_in_bytes=`expr $page_size_in_bytes \* $pages_per_block`

#echo "[$pages_per_block] pages per block and [$block_size_in_bytes] bytes"





#It's 2048 blocks on K9F2G08

blocks_per_device=2048

#echo "Blocks per device  [$blocks_per_device]"





#-e, logical erase block size, fixed on K9F2G08, refer to u-boot information "UBI: logical eraseblock size:  129024 bytes"

# logical erase block size is physical erase block size minus 1 page for UBI

logical_pages_per_block=`expr $pages_per_block - 1`

logical_erase_block_size=`expr $page_size_in_bytes \* $logical_pages_per_block`

#echo "Logical erase block size:  [$logical_erase_block_size] bytes."

#The rootfs partition size in bytes

partition_size_in_bytes=`expr $partition_sizeM \* 1024 \* 1024`

partition_physical_blocks=`expr $partition_size_in_bytes / $block_size_in_bytes`

#echo "Partition size [$partition_size_in_bytes] bytes and [$partition_physical_blocks] blocks."





#Logical blocks on a partition = physical blocks on a partitiion - reserved for wear level 

patition_logical_blocks=`expr $partition_physical_blocks - $wear_level_reserved_blocks`

#echo "Logical blocks in a partition [$patition_logical_blocks]"





#File-system volume = Logical blocks in a partition * Logical erase block size

fs_vol_size=`expr $patition_logical_blocks \* $logical_erase_block_size`

#echo "File-system volume [$fs_vol_size] bytes."





config_file=rootfs_ubinize.cfg

image_tmp=ubifs-${CPU}.img

set -x

echo ""

echo "Generating $image_name file by mkfs.ubifs..."

/usr/bin/mkfs.ubifs -x lzo -m $page_size_in_bytes -e $logical_erase_block_size -c $patition_logical_blocks -r

$rootfs_dir -o $image_tmp

set +x





echo

echo "Generating configuration file..."

echo "[ubifs-volume]" > $config_file

echo "mode=ubi" >> $config_file

echo "image=$image_tmp" >> $config_file

echo "vol_id=0" >> $config_file

echo "vol_size=$fs_vol_size" >> $config_file

echo "vol_type=dynamic" >> $config_file

echo "vol_name=rootfs" >> $config_file

echo "vol_flags=autoresize" >> $config_file

echo "vol_alignment=1" >> $config_file

echo

set -x

/usr/bin/ubinize -o $image_name -m $page_size_in_bytes -p $block_size_in_bytes -s $sub_page_size  -O    $vid_head_offset

$config_file



rm -f $image_tmp $config_file

cp $image_name /tftp

set +x

[zhouguangfeng@localhost ubifs]$ sh build_ubifs.sh

[zhouguangfeng@localhost ubifs]$ ls

build_ubifs.sh  rootfs_zhou.ubifs

[zhouguangfeng@localhost ubifs]$ OK!

使用的linux服务器已经开启tftp,ip为192.168.1.3,最后脚本直接将镜像文件拷贝到/tftp目录下,并在uboot下设置serverip为192.168.1.3。

3,在uboot添加对UBIFS的支持

nandflash分区如下:

Creating 9 MTDpartitions on "NAND":

0x000000000000-0x000000100000: "mtdblock0_u-Boot 1MB "

0x000000100000-0x000001000000 : "mtdbolck1_kernel 15MB"

0x000001000000-0x000002400000: "mtdbolck2_ramdisk 20MB"

0x000002400000-0x000003800000: "mtdblock3_cramfs 20MB"

0x000003800000-0x000006000000: "mtdblock4_jffs2 40MB"

0x000006000000-0x000008800000: "mtdblock5_yaffs2 40MB"

0x000008800000-0x00000b000000: "mtdblock6_ubifs 40MB"

0x00000b000000-0x00000d800000: "mtdblock7_apps 40MB"

0x00000d800000-0x000010000000: "mtdblock8_data 40MB"

其中kernel和UBIFS镜像文件系统烧写的地址一定要与分区对应,分区mtdbolck1放置内核和分区mtdblock6放置UBIFS,偏移分别为100000和8800000

[ s3c2440@zhou ]# set serverip
192.168.1.3

[ s3c2440@zhou ]#
2800000;nand write 30008000  800000'

[ s3c2440@zhou ]# set bootargs_ubifs 'console=ttyS0,115200 mem=64Mubi.mtd=6 root=ubi0:rootfs rootwait rootfstype=ubifs rw'

[ s3c2440@zhou ]# set bootargs  'console=ttyS0,115200 mem=64Mubi.mtd=6 root=ubi0:rootfs rootwait rootfstype=ubifs rw'

[ s3c2440@zhou ]# set bootcmd_rootfs 'nand read 30008000 100000 800000;bootm 30008000'

[ s3c2440@zhou ]# set bootcmd 'run bootcmd_rootfs'

[ s3c2440@zhou ]# save                  

Saving Environment to NAND...

Erasing Nand...

Erasing at 0x60000 -- 100% complete.

Writing to Nand... done

[ s3c2440@zhou ]# pri

cpu=s3c2440

bbl=tftp 30008000 u-boot-$cpu.bin;nand erase 0 100000;nand write 30008000 0 $filesize

norbbl=erase bank 1; tftp 30008000 u-boot-$cpu.bin;cp.b 30008000 0 $filesize

blx=tftp 30008000 linuxrom-$cpu.bin;nand erase 100000 F00000;nand write 30008000 100000 $filesize

bcramfs=tftp 30800000 cramfs-$cpu.rootfs;nand erase 2400000 1400000;nand write 30800000 2400000 $filesize

tb=tftp 30008000 linuxrom-$cpu.bin;bootm 30008000 

bootargs_initamfs=console=ttyS0,115200 mem=64M rw loglevel=7

bootargs_ramdisk=console=ttyS0,115200 root=/dev/ram0 initrd=0x30800000,16M init=/linuxrc mem=64M rw loglevel=7

bootargs_cramfs=console=ttyS0,115200 root=/dev/mtdblock3 rootfstype=cramfs init=/linuxrc mem=64M noinitrd        loglevel=7

bootargs_jffs2=console=ttyS0,115200 root=/dev/mtdblock4 rootfstype=jffs2 init=/linuxrc mem=64M rw noinitrd         loglevel=7

mtdparts=mtdparts=nand0:1m(uboot),15m(kernel),20m(ramdisk),20m(cramfs),20m(jffs2),20m(yaffs2),20m(ubifs),-(users)

baudrate=115200

ethaddr=08:08:11:18:12:27

ethact=dm9000

bootdelay=1

bkr=tftp 30008000 linuxrom-s3c2440_zhou.bin;nand erase 100000 800000;nand write 30008000 100000 800000

bootargs_ubifs=console=ttyS0,115200 mem=64M ubi.mtd=6 root=ubi0:rootfs rootwait rootfstype=ubifs rw

bootcmd_rootfs=nand read 30008000 100000 800000;bootm 30008000

bubifs=tftp 30008000 rootfs_zhou.ubifs;nand erase 8800000 2800000;nand write 30008000 8800000 800000

brdfs=tftp 30008000 ramdisk_zhou.gz;nand erase 1000000 1400000;nand write 30008000 1000000 800000

bootcmd_ramdisk=nand read 30008000 100000 800000;nand read 30800000 1000000 800000;bootm 30008000

bootcmd=run bootcmd_rootfs

bootargs_nfs=noinitrd console=ttyS0,115200 init=/linuxrc mem=64M loglevel=7 root=/dev/nfs rw nfsroot=192.168.1.3:/opt/ ip=192.168.1.224:192.168.1.3:192.168.1.1:255.255.255.0:localhost.com:eth0:off

filesize=2F8910

fileaddr=30008000

gatewayip=192.168.1.1

netmask=255.255.255.0

serverip=192.168.1.3

bootargs=console=ttyS0,115200 mem=64M ubi.mtd=6 root=ubi0:rootfs rootwait rootfstype=ubifs rw

ipaddr=192.168.1.220

stdin=serial

stdout=serial

stderr=serial





Environment size: 2076/131068 bytes

[ s3c2440@zhou ]# run bkr

dm9000 i/o: 0x20000300, id: 0x90000a46 

DM9000: running in 16 bit mode

MAC: 08:08:11:18:12:27

operating at 100M full duplex mode

Using dm9000 device

TFTP from server 192.168.1.3; our IP address is 192.168.1.220

Filename 'linuxrom-s3c2440_zhou.bin'.

Load address: 0x30008000

Loading: #################################################################

         #################################################################

         #################################################################

         ###############################

done

Bytes transferred = 3304240 (326b30 hex)





NAND erase: device 0 offset 0x100000, size 0x800000

Erasing at 0x8e0000 -- 100% complete.

OK





NAND write: device 0 offset 0x100000, size 0x800000

 8388608 bytes written: OK

[ s3c2440@zhou ]# run bubifs 

dm9000 i/o: 0x20000300, id: 0x90000a46 

DM9000: running in 16 bit mode

MAC: 08:08:11:18:12:27

operating at 100M full duplex mode

Using dm9000 device

TFTP from server 192.168.1.3; our IP address is 192.168.1.220

Filename 'rootfs_zhou.ubifs'.

Load address: 0x30008000

Loading: #################################################################

         #################################################################

         #################################################################

         ######################################

done

Bytes transferred = 3407872 (340000 hex)





NAND erase: device 0 offset 0x8800000, size 0x2800000

Skipping bad block at  0x09c60000                                          

Erasing at 0xafe0000 -- 100% complete.

OK





NAND write: device 0 offset 0x8800000, size 0x800000

 8388608 bytes written: OK

[ s3c2440@zhou ]#    boot

NAND read: device 0 offset 0x100000, size 0x800000

 8388608 bytes read: OK

## Booting kernel from Legacy Image at 30008000 ...

   Image Name:   Linux Kernel

   Created:      2014-08-22  11:27:56 UTC

   Image Type:   ARM Linux Kernel Image (uncompressed)

   Data Size:    3304176 Bytes = 3.2 MiB

   Load Address: 30008000

   Entry Point:  30008040

   Verifying Checksum ... OK

   XIP Kernel Image ... OK

OK

OS entry point: 30008040

Image entry point=30008040





Starting kernel ...

......

UBI: attaching mtd6 to ubi0

UBI: scanning is finished

UBI: attached mtd6 (name "mtdblock6_ubifs 40MB", size 40 MiB) to ubi0

UBI: PEB size: 131072 bytes (128 KiB), LEB size: 129024 bytes

UBI: min./max. I/O unit sizes: 2048/2048, sub-page size 512

UBI: VID header offset: 512 (aligned 512), data offset: 2048

UBI: good PEBs: 319, bad PEBs: 1, corrupted PEBs: 0

UBI: user volume: 1, internal volumes: 1, max. volumes count: 128

UBI: max/mean erase counter: 2/0, WL threshold: 4096, image sequence number: 1940096911

UBI: available PEBs: 0, total reserved PEBs: 319, PEBs reserved for bad PEB handling: 1

UBI: background thread "ubi_bgt0d" started, PID 501

s3c-rtc s3c2410-rtc: setting system clock to 2014-08-22 20:58:16 UTC (1408741096)

ALSA device list:

  No soundcards found.

UBIFS: background thread "ubifs_bgt0_0" started, PID 503

usb 1-1: new full-speed USB device number 2 using s3c2410-ohci

UBIFS: mounted UBI device 0, volume 0, name "rootfs"(null)

UBIFS: LEB size: 129024 bytes (126 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes

UBIFS: FS size: 37416960 bytes (35 MiB, 290 LEBs), journal size 5160960 bytes (4 MiB, 40 LEBs)

UBIFS: reserved for root: 0 bytes (0 KiB)

UBIFS: media format: w4/r0 (latest is w4/r0), UUID 8F308069-E353-4739-8E3A-5CB1967E7A24, small LPT model

VFS: Mounted root (ubifs filesystem) on device 0:11.

devtmpfs: mounted

Freeing init memory: 156K

usb 1-1: New USB device found, idVendor=05e3, idProduct=0606

usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0

usb 1-1: Product: USB Hub 2.0

hub 1-1:1.0: USB hub found

hub 1-1:1.0: 4 ports detected

dm9000 dm9000 eth0: link down

dm9000 dm9000 eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1

Copyright (C) 2014 zhouguangfeng<zhouguangfeg91@gmail.com>

root login: root

Password: 

[root@root /]# OK

内核移植和文件系统制作(4):UBIFS根文件系统制作总结的更多相关文章

  1. 一步一步制作yaffs/yaffs2根文件系统(一)---储备好基础知识再打

    开发环境:Ubuntu 12.04 开发板:mini2440  256M NandFlash   64M SDRAM 交叉编译器:arm-linux-gcc 4.4.3点此可下载 BusyBox版本: ...

  2. 制作ramdisk-u.img根文件系统

    具体步骤如下:1.解压内核源码树解压linux-2.6.29-mini2440-20090708.tgz到自己的工作目录,会生成一个友善之臂修改过的并且有几个mini2440默认配置文件的内核源码目录 ...

  3. 一步一步制作yaffs/yaffs2根文件系统(七)---真挚地道歉以及纠正前边出现的错误!

    接上一节http://blog.csdn.net/mybelief321/article/details/10040939 说实话,我当时写这个系列的博文的时候,感觉对BusyBox算是有点了解,直到 ...

  4. 一步一步制作yaffs/yaffs2根文件系统(四)---构建etc、dev等剩余目录

    开发环境:Ubuntu 12.04 开发板:mini2440  256M NandFlash   64M SDRAM 交叉编译器:arm-linux-gcc 4.4.3点此可下载 BusyBox版本: ...

  5. 一步一步制作yaffs/yaffs2根文件系统(二)---安装BusyBox,构造/bin、/sbin、/usr、linuxr

    开发环境:Ubuntu 12.04 开发板:mini2440  256M NandFlash   64M SDRAM 交叉编译器:arm-linux-gcc 4.4.3点此可下载 BusyBox版本: ...

  6. 一步一步制作yaffs/yaffs2根文件系统(三)---使用glibc库构造 /lib

    开发环境:Ubuntu 12.04 开发板:mini2440  256M NandFlash   64M SDRAM glibc库:点此下载 交叉编译器:arm-linux-gcc 4.4.3点此可下 ...

  7. 嵌入式 emmc 中 安装 烧录 内核 kernel,设备树 devicetree ,根文件系统 rootfs

    一般调试嵌入式开发板喜欢选择  利用 TFTP 传送  内核与 设备树,  利用 nfs 加载根文件系统. uboot 环境变量 设置如下: bootargs=root=/dev/nfs rw nfs ...

  8. 使用BusyBox制作嵌入式Linux根文件系统

    STEP 1:构建目录结构  创建根文件系统目录,主要包括以下目录/dev  /etc /lib  /usr  /var /proc /tmp /home /root /mnt /bin  /sbin ...

  9. Busybox制作ARM(iTOP4412) 根文件系统

    本记录来源与自身操作过程. 1.制作环境 PC环境:外部Winows8.1 内部则为vmware11+ubuntu12.04 嵌入式设备:iTOP4412 交叉工具:arm-none-linux-gn ...

随机推荐

  1. [Javascript] Functor Basic Intro

    Well, this stuff will be a little bit strange if you deal with it first time. Container Object: Just ...

  2. 记录javascript 验证字符串布尔类型 及url 参数获取

    /^true$/i.test("false");false/^true$/i.test("true");true //获取请求参数的值 function Req ...

  3. No Assistant Results

    由于修改一些文件名字等会导致这个不工作. "Organizer" / "Projects" / 选择你的项目.  "Delete" .

  4. Sqlserver添加或更新数据SQL

    Merge into [tableName] as t Using(select [@id] as tid) as t1 on t1.tid=t.id when matched then update ...

  5. iis错误记录

    1:iis错误 解决方法: 输入C:\Windows\Microsoft.NET\Framework\v4.0.30319>aspnet_regiis -i 这里由于我的是默认在Administ ...

  6. oracle 空间数据库说明

    转:http://blog.csdn.net/jing_xin/article/details/4355642 由于最近弄一些空间数据,所以找了些oracle空间数据库的一些知识.下面是汇总: Ora ...

  7. facebook-开发

    https://developers.facebook.com/docs/ios/getting-started?locale=zh_CN#prerequisites

  8. 关于VSTO调用Excel后进程无法退出的解决方案:

    VSTO的Excel对象模型提供了托管代码对Excel的操作.但是它的实现时通过RCW(Runtime Com Wrapper)实现的,所以无法完全按照托管代码的运行方式操作.COM的资源释放时通过引 ...

  9. react native之组织组件

    这些组件包括<TabView>,<NavigatorView>和<ListView>,他们实现了手机端最常用的交互和导航.你会发现这些组件在实际的项目中会非常有用. ...

  10. LoRaWAN协议(一)--架构解析

    LoRaWAN 分层 总体架构一共分为4部分: LoRaWAN从底层到最后用户拿到数据的通讯过程通讯大致可分为三段: MOTE <---> GW (MAC层) GW <---> ...