LINUX.ORG.RU
решено ФорумTalks

Про фрагментацию файлов на ФС, FreeBSD и iZEN'а


0

0

В недавней теме про дефрагментатор ext4 iZEN начал доказывать, что FreeBSD'шная UFS2 не подвержена фрагментации. Т.е. как-бы вообще. Я решил попробовать доказать обратное путём экспериментирования со свежескачанным LiveCD Frenzy (основан на FreeBSD 8.0). В результате эксперимента мне удалось выяснить, что FreeBSD'шный fsck заместо степени фрагментации показывает непонятно что...

Для начала надо определиться, что же такое фрагментация. (Далее идёт описание моего понимания этого термина, если что-то не так - поправьте меня). Допустим есть три файла - 1, 2 и 3, каждый из них имеет длину 10. При отсутствии фрагментации на блочном устройстве они должны быть расположены так: 111111111122222222223333333333. Если фрагментация имеет место, то может получиться что-то вроде: 123123123123123123123123123123. В худшем случае части файлов будут не только перепутаны между собой, но ещё и расположены в обратном порядке. Я думаю не надо объяснять почему это плохо - при последовательном чтении файла получается непоследовательное чтение блочного устройства. Задача дефрагментатора - расположить части файлов последовательно и в правильном порядке, т.е. сделать 123123123123123123123123123123 -> 111111111122222222223333333333. Надеюсь я правильно написал?

А теперь про эксперименты над Frenzy.

[root@frenzy ~]# uname -a
FreeBSD frenzy 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Thu Jan  7 11:59:02 UTC 2010     root@frenzy.home.local:/buildscripts/frenzybuild/build/buildscripts/frenzybuild/src/sys/FRENZY  i386
Сначала создаём блочное устройство на 128МБ и на нём ФС:
[root@frenzy ~]# dd if=/dev/zero of=fsimage bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes transferred in 1.333509 secs (100650038 bytes/sec)

[root@frenzy ~]# mdconfig -a -t vnode -f fsimage
md3

[root@frenzy ~]# newfs /dev/md3
/dev/md3: 128.0MB (262144 sectors) block size 16384, fragment size 2048
	using 4 cylinder groups of 32.02MB, 2049 blks, 4160 inodes.
super-block backups (for fsck -b #) at:
 160, 65728, 131296, 196864

[root@frenzy ~]# mkdir ufs2

[root@frenzy ~]# mount /dev/md3 ufs2

[root@frenzy ~]# fsck -n -t ufs md3 | grep fragmentation
2 files, 2 used, 63349 free (21 frags, 7916 blocks, 0.0% fragmentation)
Далее создаём кучу мелких файлов
[root@frenzy ~]# for ((i=0; i<1000; i++)); do dd if=/dev/zero of=/root/ufs2/test$i bs=1k count=120; done
... вывод пропущен ...

[root@frenzy ~]# df -h | grep ufs
/dev/md3                        124M    117M   -3.4M   103%    /root/ufs2

[root@frenzy ~]# fsck -n -t ufs md3 | grep fragmentation
1002 files, 60009 used, 3342 free (998 frags, 293 blocks, 1.6% fragmentation)
Сразу же вопрос: откуда взялись 1.6% фрагментации? Ну да ладно. Далее удаляем каждый десятый мелкий файл и на его место дозаписываем один большой («fragmented»):
[root@frenzy ~]# rm ufs2/test*0

[root@frenzy ~]# df -h | grep ufs2
/dev/md3                        124M    105M    8.3M    93%    /root/ufs2

[root@frenzy ~]# fsck -n -t ufs md3 | grep fragmentation
902 files, 54009 used, 9342 free (1206 frags, 1017 blocks, 1.9% fragmentation)

[root@frenzy ~]# cat /dev/zero >>ufs2/fragmented

/root/ufs2: write failed, filesystem is full
cat: stdout: No space left on device

[root@frenzy ~]# fsck -n -t ufs md3 | grep fragmentation
903 files, 61697 used, 1654 free (1206 frags, 56 blocks, 1.9% fragmentation)

[root@frenzy ~]# rm ufs2/test*1

[root@frenzy ~]# cat /dev/zero >>ufs2/fragmented

/root/ufs2: write failed, filesystem is full
cat: stdout: No space left on device

[root@frenzy ~]# fsck -n -t ufs md3 | grep fragmentation
803 files, 55697 used, 7654 free (982 frags, 834 blocks, 1.6% fragmentation)
И так далее, пока на разделе не останется один большой файл fragmented, занимающий всё место. По идее, если

  • UFS2 не обладает телепатией и не могла изначально расположить мелкие файлы так, чтобы при их непоследовательном удалении место на блочном устройстве освобождалось последовательно
  • UFS2 в фоне не перемещает части существующих файлов, т.е. не делает фоновую дефрагментацию

, то куски файла на блочном устройстве должны быть расположены не последовательно, т.е. он должен быть фрагментирован. Но что же мы видим:

[root@frenzy ~]# fsck -n -t ufs md3 | grep fragmentation
3 files, 63025 used, 326 free (14 frags, 39 blocks, 0.0% fragmentation)
Ага, щас, 0% =).

А теперь вопрос: чем же смотреть фрагментацию во FreeBSD? Под линуксом с помощью утилиты filefrag можно посмотреть на сколько частей разбило файл.

Deleted

> чем же смотреть фрагментацию во FreeBSD

В этой недооси наверное только hexdump.

PolarFox ★★★★★ ()

Не понимаю к чему все эти напряги? В наш век гигабайтных дешевых SSD вопросы фрагментации FS попросту не актуальны.

bibi ()

жжешь. Постораюс не уснуть до ответа изена

dk- ()

> UFS2

они теперь на ZFS дрочат.

isden ★★★★★ ()

Ну если мыслить логически...
Что делать файловой системе если захочешь дописать файл 2? Двигать файл 3? А если после третьего идет 4, его тоже двигать?
Поэтому фрагментация неизбежна.

hibou ★★★★★ ()
Ответ на: комментарий от hibou

Поэтому фрагментация неизбежна.

Попробуй доказать это iZEN'у =).

Deleted ()
Ответ на: комментарий от isden

iZEN дрочит на всё, что есть в бзде, но отсутствует в линуксе.

xetf ★★ ()

Тонко! Прозреваю, что Изя сейчас судорожно пытается нагуглить контраргументы

kranky ★★★★★ ()
Ответ на: комментарий от kranky

Тонко! Прозреваю, что Изя сейчас судорожно пытается нагуглить контраргументы

Т.е. версии, что Изя таки парится в бане с друзьями под пивко или там сидит в ресторане с красивой женщиной или на худой конец пошел в поход в горы - они начисто отметаются? А зря. Ибо Изи тут вроде как не наблюдается, а вот оппоненты - тут как тут.

bibi ()
Ответ на: комментарий от bibi

s/Изя таки парится в бане с друзьями под пивко или там сидит в ресторане с красивой женщиной/Изя таки парится в бане с красивой женщиной/

se ★★ ()

Неужели на лоре еще остались люди, воспринимающие iZEN'а всерьез?

Он же в компах и всех связанных с ними темах полный ноль.

nnz ★★★★ ()
Ответ на: комментарий от se

s/Изя таки парится в бане с друзьями под пивко или там сидит в ресторане с красивой женщиной/Изя таки парится в бане с красивой женщиной/

А вот кстати и Изя легок на помине. Вечер добрый.

bibi ()
Ответ на: комментарий от bibi

>Т.е. версии, что Изя таки парится в бане с друзьями под пивко или там сидит в ресторане с красивой женщиной или на худой конец пошел в поход в горы - они начисто отметаются? А зря. Ибо Изи тут вроде как не наблюдается, а вот оппоненты - тут как тут.

Скорее его родители за плохое поведение к компу не пускают :)

nnz ★★★★ ()
Ответ на: комментарий от bibi

лет 8 администрирую FreeBSD(в самых разных ипостасях).
с проблемами фрагментации сталкиваться не доводилось. наверное плохо администрирую?

se ★★ ()

А ты sync делал? Может быть просто всё кешируется.
Кроме того, ты fsck делал на примонтированной системе, а это неправильно.

Xenius ★★★★★ ()
Ответ на: комментарий от se

Толсто

>лет 8 администрирую FreeBSD(в самых разных ипостасях).

с проблемами фрагментации сталкиваться не доводилось. наверное плохо администрирую?


Наоборот, хорошо.

Своевременный (периодический) запуск defrag.exe полностью снимает проблему фрагментации во FreeBSD :)

nnz ★★★★ ()
Ответ на: комментарий от se

>лет 8 администрирую FreeBSD(в самых разных ипостасях). с проблемами фрагментации сталкиваться не доводилось. наверное плохо администрирую?

Ну похоже на то...

vasya_pupkin ★★★★★ ()

> Ага, щас, 0% =).

Ничего удивительного.

Маленькие файлы записывались во фрагменты блоков последовательно. Потом их часть удалили и на свободное место записались большие файлы. При этом операционка перед записью больших файлов растянула блоки до 16 раз, уничтожив часть свободных inode'ов. При последующем удалении больших файлов и попытке записи на освободившееся место мелких файлов система скажет, что нету свободных inode'ов. Фрагментация действительно минимальна.
Финиш!

iZEN ★★★★★ ()
Ответ на: комментарий от iZEN

а мы думали, что ты в бане с женщиной.. :)

mono ★★★★★ ()
Ответ на: комментарий от iZEN

Ничего удивительного.

Маленькие файлы записывались во фрагменты блоков последовательно. Потом их часть удалили и на свободное место записались большие файлы. При этом операционка перед записью больших файлов растянула блоки до 16 раз, уничтожив часть свободных inode'ов. При последующем удалении больших файлов и попытке записи на освободившееся место мелких файлов система скажет, что нету свободных inode'ов. Фрагментация действительно минимальна.

Финиш!

А теперь прочитай первый пост.

Deleted ()
Ответ на: комментарий от se

с проблемами фрагментации сталкиваться не доводилось. наверное плохо администрирую?

Ты тоже сейчас будешь утверждать, что UFS2 не подвержена фрагментации?

Deleted ()
Ответ на: комментарий от Xenius

> А ты sync делал? Может быть просто всё кешируется.

У него ничего не кэшируется — Soft Updates не задействуются без ключа "-U" при форматировании ФС.

Кроме того, ты fsck делал на примонтированной системе, а это неправильно.


Не надо думать, что если в FreeBSD запустить fsck на примонтированной системе, то она разрушится, как в Linux. Очень опасно недооценивать UFS2 в плане технологического «отставания» от линуксовых ФС. fsck на UFS2 на самом деле работает со снапшотом «грязной» ФС.

iZEN ★★★★★ ()
Ответ на: комментарий от mono

>а мы думали, что ты в бане с женщиной.. :)


С женщиной с аватары. Если это вообще женщина.

ShTH ()
Ответ на: комментарий от iZEN

Не надо думать, что если в FreeBSD запустить fsck на примонтированной системе, то она разрушится, как в Linux. Очень опасно недооценивать UFS2 в плане технологического «отставания» от линуксовых ФС. fsck на UFS2 на самом деле работает со снапшотом «грязной» ФС.

Я просто представил сколько должен сожрать памяти fsck для хранения снапшота при проверке примонтированной ФС с активно изменяющимся содержимым... Впрочем это тема для отдельного эксперимента =).

Deleted ()

>[root@frenzy ~]# fsck -n -t ufs md3 | grep fragmentation

В бздне настолько тупой fsck, что ему надо указывать тип файловой системы?

ttnl ★★★★★ ()
Ответ на: комментарий от Deleted

Я просто представил сколько должен сожрать памяти fsck для хранения снапшота при проверке примонтированной ФС с активно изменяющимся содержимым...

Разработчики пишут, что примерно 64МБ на 1ТБ разделе, если не злоупотреблять мелкими файлами.

iZEN ★★★★★ ()
Ответ на: комментарий от Deleted

Глянь в исходники: /usr/src/sbin/fsck_ffs/main.c

Фрагментация рассчитывается так:

printf("(%ju frags, %ju blocks, %.1f%% fragmentation)\n", 
       (uintmax_t)n_ffree, (uintmax_t)n_bfree, 
       n_ffree * 100.0 / sblock.fs_dsize);

или так:

printf("(%lld frags, %lld blocks, %.1f%% fragmentation)\n", 
          (long long)sblock.fs_cstotal.cs_nffree, 
          (long long)sblock.fs_cstotal.cs_nbfree, 
          sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize);

iZEN ★★★★★ ()
Ответ на: комментарий от vasya_pupkin

>Ну похоже на то...

ну можно поиграться с размерами block/frag size если заранее известно, что это бекапный хост, на котором дампы по 70-140gb
к примеру так - newfs -O 2 -U -b 65536 -f 8192

а если это машина под проект, то кроме как 4 x raptor в raid10 ничего с этим не сделаешь.
какая-то фрагментация будет всегда.

кстати именно ufs пытается снизить её за счет группирования цилиндров.
к примеру, у mironov_ivan получилось 4 группы по 32.02mb

se ★★ ()
Ответ на: комментарий от se

> кстати именно ufs пытается снизить её за счет группирования цилиндров.
к примеру, у mironov_ivan получилось 4 группы по 32.02mb

Интересно, на разделе такого же размера сколько будет групп блоков у ext2?

iZEN ★★★★★ ()
Ответ на: комментарий от bibi

>В наш век гигабайтных дешевых SSD

Пока нету терабайтных дешёвых SSD - вопрос фрагментации актуален :)

KRoN73 ★★★★★ ()
Ответ на: комментарий от Deleted

>Попробуй доказать это iZEN'у =).

Бесполезно. У него мощный входной фильтр на логику :)

KRoN73 ★★★★★ ()
Ответ на: комментарий от KRoN73

+1. $150 за 40 гиг с нормальными статсами, назвать «дешевым» как-то пока с трудом можно

mrdeath ★★★★★ ()
Ответ на: комментарий от iZEN

Фрагментация рассчитывается так:

Если я правильно понял содержимое исходников и информацию об UFS2, которую удалось нагуглить, то блоки ФС ещё дополнительно разбиваются на несколько фрагментов, чтобы в один блок влезло несколько файлов. Так вот, похоже процент фрагментации, который выдаёт fsck, просто обозначает количество блоков, в которых расположено сразу несколько файлов. Т.е. то, что называется фрагментацией во FreeBSD, и то, что называется фрагментацией во всём остальном мире, - это абсолютно разные вещи.

Deleted ()

Сделал на коленке небольшую утилиту, которая показывает ту самую фрагментацию, о которой я писал в первом посте:

#include <stdio.h>
#include <stdlib.h>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <linux/fs.h>

static void die(const char *message)
{
	fprintf(stderr, "ERROR: %s\n", message);
	exit(EXIT_FAILURE);
}

static void printGroup(int n, int start, int end)
{
	if (start != end)
		printf("Group of blocks #%d: %d - %d (%d)\n",
				n, start, end, end - start + 1);
	else
		printf("Single block #%d: %d", n, start);
}

int main(int argc, char **argv) {
	int	fd;
	int	num_blocks = 0, old_block = -2, block;
	int	num_groups = 0, group_start = -1;
	int	num_reverse_groups = 0;
	double	fragmentation = 0.0;

	if (argc != 2) {
		fprintf(stderr, "Usage:\n\t%s filename\n", argv[0]);
		die("No file name in command line.");
	}

	fd = open(argv[1], 0, O_RDONLY);
	if (fd == -1)
		die("open() error.");

	for (int i = 0; ; ++i) {
		block = i;
		if (ioctl(fd, FIBMAP, &block) == -1)
			die("ioctl() error.");
		if (!block)
			break;

		++num_blocks;

		if (block != old_block + 1) {
			if (group_start < 0) {
				group_start = block;
			} else {
				printGroup(num_groups, group_start, old_block);
				group_start = block;
			}

			++num_groups;

			if (old_block > block)
				++num_reverse_groups;
		}

		old_block = block;
	}
	if (group_start >= 0)
		printGroup(num_groups, group_start, old_block);

	printf("Total number of blocks: %d\n", num_blocks);
	printf("Total number of groups: %d\n", num_groups);
	printf("Total number of groups in reverse order: %d\n", num_reverse_groups);

	if (num_blocks > 1)
		fragmentation = ((double) (num_groups - 1)) / ((double) (num_blocks - 1)) * 100.0;
	else
		fragmentation = 0.0;
	printf("Fragmentation: %f%%\n", fragmentation);

	if (close(fd) == -1)
		die("close() error.");

	return 0;
}
$ gcc -Wall -Wextra -std=c99 -pedantic -o showfrag showfrag.c
Естественно, т.к. у меня пока нет полноценной FreeBSD с компилятором, то и утилита пока только под Linux. Вчерем попробую портировать на FreeBSD, но это получится только если там есть ioctl FIBMAP или что-то аналогичное.

Вот пример работы (в сравнении с выводом filefrag и e4defrag):

$ sudo ./showfrag ../frenzy-1.2-reincarnation-en-release.iso 
Group of blocks #1: 29931712 - 29932735 (1024)
Group of blocks #2: 29920256 - 29921279 (1024)
Group of blocks #3: 34019328 - 34037759 (18432)
Group of blocks #4: 39837696 - 39839743 (2048)
Group of blocks #5: 39972864 - 39976959 (4096)
Group of blocks #6: 39983104 - 39989247 (6144)
Group of blocks #7: 40001536 - 40003583 (2048)
Group of blocks #8: 39993344 - 40001535 (8192)
Group of blocks #9: 40218624 - 40220671 (2048)
Group of blocks #10: 40232960 - 40239103 (6144)
Group of blocks #11: 40261632 - 40263679 (2048)
Group of blocks #12: 40273920 - 40304639 (30720)
Group of blocks #13: 40329216 - 40330289 (1074)
Total number of blocks: 85042
Total number of groups: 13
Total number of groups in reverse order: 2
Fragmentation: 0.014111%

$ sudo filefrag ../frenzy-1.2-reincarnation-en-release.iso 
../frenzy-1.2-reincarnation-en-release.iso: 13 extents found

$ sudo ./e2fsprogs/misc/e4defrag -c ../frenzy-1.2-reincarnation-en-release.iso 
<File>                                         now/best          ratio
../frenzy-1.2-reincarnation-en-release.iso
                                                13/1             0.01%

 Total/best extents				13/1
 Fragmentation ratio				0.01%
 Fragmentation score				0.11
 [0-30 no problem: 31-55 a little bit fragmented: 55- needs defrag]
 This file(../frenzy-1.2-reincarnation-en-release.iso) does not need defragmentation.
 Done.

Deleted ()
Ответ на: комментарий от Deleted

Естественно, т.к. у меня пока нет полноценной FreeBSD с компилятором, то и утилита пока только под Linux. Вчерем попробую портировать на FreeBSD, но это получится только если там есть ioctl FIBMAP или что-то аналогичное.

В общем, FIBMAP в FreeBSD отсутствует. Ничего аналогичного за пол часа гуглинга найти не удалось. Так что остаётся один вариант - разобраться в структурах UFS2 и читать прямо с блочного устройства. Узнал интересные факты:

  • Читать с блочных устройств можно только кусками, кратными размеру блока. Иначе read выдаст ошибку и в errno будет EINVAL. Причём в man 2 read об это не написано и багрепорт об этом висит с 2005-го года.
  • Судя по всему, драйвер ФС и утилиты кладут на порядок байт. Так что ФС созданная на системе с одним порядком байт не прочитается на системе с другим порядком байт =).
Deleted ()
Ответ на: комментарий от Deleted

> Читать с блочных устройств можно только кусками, кратными размеру блока.

Я об этом не раз писал в треде о дефрагментаторе Ext4, раскрывая суть работы UFS2, но KRoN73 это пропускал мимо ушей.

Судя по всему, драйвер ФС и утилиты кладут на порядок байт. Так что ФС созданная на системе с одним порядком байт не прочитается на системе с другим порядком байт =).


Ну так это известно уже давно. Только ZFS может распознавать правильный порядок байт. Однако и она взводит только лишь флаг о порядке, не препринимая никаких действий по переписыванию уже записанных данных == преобразование последовательности байтов выполняет на лету, когда это требуется.

iZEN ★★★★★ ()
Ответ на: комментарий от iZEN

Читать с блочных устройств можно только кусками, кратными размеру блока.

Я об этом не раз писал в треде о дефрагментаторе Ext4, раскрывая суть работы UFS2, но KRoN73 это пропускал мимо ушей.

Это не имеет никакого отношения ни к фрагментации, ни даже к работе ФС. Просто при необходимости считать N байт с произвольной позиции блочного устройства вместо простого lseek + read нужно городить ещё велосипед.

P.S. И всё-таки у FreeBSD есть как минимум 1 плюс: по умолчанию off_t 64х-разрядный =).

Deleted ()

>А теперь вопрос: чем же смотреть фрагментацию во FreeBSD? Под линуксом с помощью утилиты filefrag можно посмотреть на сколько частей разбило файл.

видимо фрагментацией называют сколько разрывов имеет файл. В данном случае - ни одного.

Можно сказать, что этот случай исключение, так как чрезвычайно редко бывает такое, что файл фрагментирован сам собой.

dikiy ★★☆☆☆ ()
Ответ на: комментарий от bibi

>> s/Изя таки парится в бане с друзьями под пивко или там сидит в ресторане с красивой женщиной/Изя таки парится в бане с красивой женщиной/

А вот кстати и Изя легок на помине. Вечер добрый.

OMFG! Растроение личности. Изя, зватит дрючить виртуалов, если аргументов нет вообще 6)

dikiy ★★☆☆☆ ()
Ответ на: комментарий от Deleted

>В общем, FIBMAP в FreeBSD отсутствует. Ничего аналогичного за пол часа гуглинга найти не удалось. Так что остаётся один вариант - разобраться в структурах UFS2 и читать прямо с блочного устройства. Узнал интересные факты:

Записывай в качестве большого файла просто последователность из нулей и единий. Допустим 20МБ 0xA0, а потом 20МБ 0x0F. Ну или в этом духе.

dikiy ★★☆☆☆ ()
Ответ на: комментарий от dikiy

> Записывай в качестве большого файла просто последователность из нулей и единий. Допустим 20МБ 0xA0, а потом 20МБ 0x0F. Ну или в этом духе.

ФС для больших файлов выставляет больший размер блока (максимум в 16 раз больше стандартного). Файлы будут писаться по возможности внутри одной группы цилиндров и в смежные группы цилиндров. Так что тут опять «опачки» — фрагментированности файлов на уровне блоков добиться очень трудно.

iZEN ★★★★★ ()
Ответ на: комментарий от iZEN

>> Записывай в качестве большого файла просто последователность из нулей и единий. Допустим 20МБ 0xA0, а потом 20МБ 0x0F. Ну или в этом духе.

ФС для больших файлов выставляет больший размер блока (максимум в 16 раз больше стандартного). Файлы будут писаться по возможности внутри одной группы цилиндров и в смежные группы цилиндров. Так что тут опять «опачки» — фрагментированности файлов на уровне блоков добиться очень трудно.

Дык какая разница, на каком уровне фрагментированность?

dikiy ★★☆☆☆ ()
Ответ на: комментарий от dikiy

> какая разница, на каком уровне фрагментированность?

Большая.

Операционка работает с блочными устройствами транзакциями пересылаемых данных, кратными размеру блока. Для маленьких блоков будет несколько транзакций. Для больших блоков — транзакций меньше. Это влияет на общую пропускную способность интерфейса диск-память.

Фрагментированность на уровне фрагментов блоков не влияют на количество считанных в память блоков, так как вся обработка фрагментов (склеивание из них файла) осуществляется в памяти == блочное устройство лишний раз не дёргается.

iZEN ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.