On Wed, Nov 09, 2011 at 10:01:13AM +0900, dima wrote:
> Just for the record - I could find a solution thanks to the btrfs wiki
> being online again. In Gotchas it says
>
> mount -o nodatacow also disables compression
>
> and indeed it does. Remounting with this option and re-saving the file
> makes it uncompressed. However, I could not find how to remount the
> filesystem afterwards without nodatacow.
I saw this mentioned on irc today (that nodatacow diasables
compression). There is a way how to turn off compression on a file --
with help of the NOCOW _file_ attribute, ie. you don't have to remount.
* create the file, compression enabled
* set NOCOW (with the attached single-purpose nocow.c utility)
* btrfs fi defrag the_file
Make sure you have enough free space for the uncompressed file size. You
can compare the extent layout before and after the defrag with
"filefrag -v" .
I did a test first, here's what I saw with a ~60M file (filled with
zeros, suitable for compression):
# filefrag -v zerofile2
Filesystem type is: 9123683e
File size of zerofile2 is 69927424 (17073 blocks, blocksize 4096)
ext logical physical expected length flags
0 0 2700 32
1 32 2942 2731 32
2 64 2943 2973 32
3 96 2944 2974 32
4 128 2945 2975 32
...
533 17039 2641 2671 32
534 17071 2643 2672 2 eof
zerofile2: 535 extents found
# btrfs fi defrag zerofile2
# filefrag -v zerofile2
Filesystem type is: 9123683e
File size of zerofile2 is 69927424 (17073 blocks, blocksize 4096)
ext logical physical expected length flags
0 0 20992 2107
1 2107 23552 23098 1581
2 3688 16400 25132 1185
3 4873 12410 17584 889
4 5762 14762 13298 667
5 6429 15881 15428 500
6 6929 17585 16380 751
7 7680 23099 18335 375
8 8055 25133 23473 376
9 8431 3072 25508 2160
10 10591 5632 5231 1620
11 12211 8192 7251 2431
12 14642 18432 10622 2431 eof
zerofile2: 13 extents found
david
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/types.h>
#include <stdio.h>
#include <errno.h>
#ifndef FS_IOC_SETFLAGS
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
#warning defining SETFLAGS locally
#endif
#ifndef FS_IOC_GETFLAGS
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
#warning defining GETFLAGS locally
#endif
#ifndef FS_NOCOW_FL
#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
#endif
int main(int argc, char **argv)
{
int fd;
int r;
long flags;
if (argc < 2) {
printf("usage: %s file\n", argv[0]);
exit(1);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1) {
perror("open()");
return 1;
}
printf("GETFLAGS ioctl 0x%x\n", FS_IOC_GETFLAGS);
printf("SETFLAGS ioctl 0x%x\n", FS_IOC_SETFLAGS);
r = ioctl(fd, FS_IOC_GETFLAGS, &flags);
if (r == -1) {
perror("ioctl(GETFLAGS)");
return 1;
} else {
printf("file flags: 0x%lx\n", flags);
}
printf("Set NOCOW flag for %s\n", argv[1]);
flags |= FS_NOCOW_FL;
r = ioctl(fd, FS_IOC_SETFLAGS, &flags);
printf("ioctl returned: %d\n", r);
if (r == -1) {
perror("ioctl()");
return 1;
}
return 0;
}