1

I have a disk with some filesystem known by the Linux kernel. I need to get the physical block numbers for all blocks that are currently free on this filesystem. How can I do that?

Vanwaril
  • 7,380
  • 6
  • 33
  • 47
Karatheodory
  • 895
  • 10
  • 16

5 Answers5

2

Getting a free-block count:

In-kernel method:

Look at the .statfs superblock hook that filesystems implement. They return a kstatfs object which has a f_bfree parameter, a count of the free blocks. You should be able to call into this.

From userspace:

The df command is the simplest (which of course causes the kernel to call statfs - where else would it get the information? :)

Edit: Your original question conveyed getting just the free block count.

Getting block locations:

Getting the location of every free block and not just the total number is impossible in a filesystem-independent way with the current structure of the kernel (and it will probably remain this way). The VFS doesn't impose any common structure on how the filesystem maintains its bitmap; bitmaps are kept track of in the filesystem-dependent part of the superblock.

So, if you want a solution that works across all filesystems, you are out of luck. If you know what the filesystems might be and its a small number, you can look at userspace fsck code for each of those and add functions to write out a bitmap in a format you expect, or you can modify the .statfs hooks to write out the bitmap.

Your method to allocate a large file that allocates all remaining free blocks doesn't sound like a very good idea at all, especially if there are journals involved. It also won't work for an active filesystem with files being written and deleted as you do this.

Vanwaril
  • 7,380
  • 6
  • 33
  • 47
  • It isn't matter for me, from kernel- or userspace. I think that if there is some function that gives me physical block numbers, it must be located in kernel, but it is only my suggestion :) – Karatheodory May 03 '12 at 09:37
  • Thank you for answer! It seems that I need to go to the lower level... :) – Karatheodory May 11 '12 at 07:14
2

This depends on the filesystem - there is no unified interface, and some filesystems such as JFFS don't really have a concept of a free block. Moreover, if the filesystem is mounted, any information you get can be out of date instantly. Expect to have to read poorly documented filesystem internal code. However, you don't necessarily have to do this in the kernel. If you're interested in getting ext[234] free-space bitmaps, for example, look at the bitmap functions in libext2fs. In general, if there's a userspace fsck, you can probably exploit its code to get the information you want.

What do you need this for, anyway?

bdonlan
  • 224,562
  • 31
  • 268
  • 324
  • I need to write some data into filesystem without damaging or modifying it. Anyway, it seems that it is possible only by using low-level drivers. Thank you for your answer! – Karatheodory May 11 '12 at 07:14
1

Afraid statfs-like functions can give me only count of free fs blocks, but not their positions.

The simpliest way I've found to get the positions of free blocks is to create a file that fills (or reserves only with fallocate() call) all the space available, get the block map using FIBMAP ioctl and delete the file. But doing this way isn't exactly what I want for some reasons.

Another way is to get into the lower level of concrete file system and get free space bitmap from it's driver. It is a good way for me, but it must be implemented for each file system dependently, and it is not good :)

Maybe there is some vfs function I can't find for that or some fs ioctl that can help in that case?

Thank you all for your answers anyway!

Karatheodory
  • 895
  • 10
  • 16
  • Without modifying your file system, you could use `FIBEMAP` / `FIBMAP` `ioctl()` to get the block information about each individual file, to collect all the reserved blocks (block ranges). The free blocks would be the complement of this set of blocks. This is apparently heavy undertaking if your file system has many files. Also you would need to find way to do it in kernel space. – FooF May 04 '12 at 05:31
  • 2
    @Foof, that approach will incorrectly report blocks used for internal FS structures (such as the journal) as free. – bdonlan May 04 '12 at 06:25
-1

You could go some old style C, fork and then execl a program called "stat" in unix. You could pipe that output to a file and then use some stringstream to interpret it and find number of free blocks. (this would involve taking the number of total IO blocks and subtracting the number of used IO blocks.

Im not sure if there is an easier way then this. Here is some pseudo code:

main() {
    fork()
    if child{
        execl(stat / %B >> output.txt)
    }
    if parent {
        wait until output.txt is populated
        read in data with stringstream
        calculate number of free blocks
    }
}

hope that helps.

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
-1

Capturing stdout from a system() command optimally

A syscall might be what you are looking for, just make sure that popen is standard on linux first. I also forgot to mention that you should do something like :

FILE* test = popen("df","r");

Since df tells you the number of free blocks on the system.

Community
  • 1
  • 1
Jason Zhu
  • 2,194
  • 3
  • 23
  • 27