1

I have a file that's being constantly held open and continuously modified by another process. This process is continuously seeking to different parts of the file and writing new blocks. I'd like to be able to make a copy of that file but as a snapshot of the file at a single instance of time.

What I don't want to happen is that I copy the first block of bytes, the file changes and then I copy the second block including the newly modified bytes.

Can Linux help me out here?

2
  • It would be best if the program modifying the file had some support for momentarily pausing. Like various filesystems and databases have (fsfreeze(), FLUSH TABLES WITH READ LOCK and whatever there is)
    – ilkkachu
    Commented May 24, 2022 at 13:31
  • Hey billpg, I've extended my answer with a few words on consistency. Commented May 25, 2022 at 14:19

2 Answers 2

1

You would need to pause the writing process before copying.

In majority of cases, the writer process will have some backup capability. Take a close look at the documentation of the process which updates the file.

For more detailed help we need to know which process does the file writing. It is possible that someone knows that application and knows how to do backup in a proper way.

If no backup functionality is built in, you can try to pause the writer process by using kill with SIGSTOP/SIGCONT signals. If each logical update is a single action, then fine. But if your writer process can do a two writes as on logical update (for example update data, and update indexing section of the file), then you would have a risk of pausing process between such to writes.

0

Can Linux help me out here?

Yes. But not in the way you probably hoped it would.

So, file systems on Linux generally follow the semantics that a change to a file that is read (in whichever way) should be reflected instantly as possible in all readers of that file. Notice how that is at odds with what you want.

What you can very well do is tell your filesystem or block device layer to make a snapshot, and here the semantics are different, namely, demanding consistency at the point of snapshotting.

So, you need to have either

  • a file system that supports snapshots, or
  • a block device sublayer that supports snapshots.

Consistency

As doneal very correctly points out: None of this helps you if a snapshot is taken while a single "unit of consistency" (i.e., a search and write that leads to another consistent file state, probably what you consider a "change of datum" from an application view) is ongoing.

The things below both assume you're taking a snapshot at an instant that no write is currently ongoing. What they avoid the copy not being the exact same as the file was at the instant of starting the copy. If you make a snapshot in the middle of writing 8 kB of data, your snapshot contains 4 kB of new, and 4 kB of old data in the 8 kB chunk of data you meant to overwrite. That's what I'd call "data inconsistency".

This does infact mean that there's no help: your operating system cannot bring a file into a consistent state if you don't have a logical way of ensuring consistency for your file.

If you need that, you will have to look into how "proper" database systems ensure that a database is not in an unrecoverably broken state when a storage device suddenly is removed from the system.

Your file can't do that. You yourself can never guarantee consistency if you do not restrict snapshot points in time to happen only when there's no unfinished write! To achieve that, on any storage medium or operating system, you will have to change your file architecture.

The most common way to do that is implement a strictly ordered mechanism of 1. writing the change, including position, length and data to be done to the main file to a log at the end of the file (or another file), with a trailing checksum that allows you to check whether that happened completely. And, only after that has been fully completed, write the change to the main file. 3. occasionally, you need to go back and clean up the successfully committed log entries.

When you now do a snapshot while writing to the main data file, the data in the log doesn't agree with the data in the main data. You can replay the write from the log, and be back in a consistent state. If you do your snapshot while writing to the log, you can notice when reading the lock that the checksum of the log entry is not correct, and hence, that log entry cannot be complete, and hence, the main data is yet unaffected by what the log entry describes. You delete the broken log entry from the snapshotted log.

Filesystem snapshots

To the best of my knowledge, under Linux, only the btrfs and openZFS file systems support snapshots. Btrfs is part of the linux kernel, so that's probably easiest to work with.

In btrfs, your file system (say, a filesystem that is mounted on /srv/data) can have subvolumes. You can either access these as subdirectories or separately mount them.

A btrfs snapshot is just a subvolume that is identical to the current volume. That's "easy" for btrfs to implement, because that is a copy-on-write file system: normally, whenever you modify a file, a copy of the affected storage block is made, with the modified data inside. Then, the file metadata is updated: A file's content is just the data in a list of blocks, and if you change something in, say, the 4. block, then the fourth entry in that list is replaced with a reference to the "freshly copied and modified" block. This comes at very low overhead, as storage devices work in blocks, anyways - you can never read a single byte, you read a block, and writing a single byte and a block takes the same time. So, read, modify, write to a different position is as expensive as modification in-place.

Now, when a snapshot is made, all that happens is that any modifications to the file metadata after the snapshot will go to a separate data structure. So, basically, the snapshot and the currently "active" working view of the file system 100% share the data for everything that has not changed, but things that have changed are there twice: once in the modified version, and once as it were at the time of the snapshot.

So, put your file on a btrfs subvolume, make a snapshot, mount that snapshot: you got your file "frozen" in time.

Block Device Mapper Snapshots

These basically work with any modern Linux filesystem. In the world where these are common, XFS is a popular file system choice (but any file system should do).

LVM is the linux volume manager. That basically means it's a part of the kernel that you can give one or many block devices ("physical volumes"), tell it to assemble these to a "volume group", and from the accumulated storage pool then create "logical volumes".

A special case of these are "thin volumes", which basically means that you say "OK, I have 512 GB of storage in my volume group. I want to make a logical volume that I can format with a file system. I want that to be TB, maybe, eventually (if my customer actually uses these, for example), but for now, I don't even have that much space (new SSD hasn't even been ordered yet, but you also don't need all these 1 TB yet)". LVM will then create a volume that looks

16
  • Even with snapshots you could get inconsistent data. If the write is in two steps, e.g. metadata and then data, you could get caught where one is written and the other is pending.
    – doneal24
    Commented May 24, 2022 at 13:25
  • @doneal24 that's not the case for modern journalling file systems. Order and consistency against partial writes is part of the very filesystem design. Commented May 24, 2022 at 14:54
  • A journaling file system makes sure that all writes to the disk are complete before a snapshot is made. But if I update the metadata in a file, take a snapshot, and then update the data, the file system has no way to know that the database is now inconsistent. Journaling is only going to help if the metadata and data updates are in an atomic operation.
    – doneal24
    Commented May 24, 2022 at 14:58
  • hm, a journalling file system does remedy inconsistency if the write was interrupted at any point; I don't think it's usual to make a difference for metadata and payload data there (I'm sure you can configure the hell out of that, though!) Commented May 24, 2022 at 15:03
  • well, but that's an excellent illustration: Journalling file systems are essentially WAL databases (and as far as I know for both metadata and file contents), and that leads to a state of consistency being reachable if power was lost / a snapshot was taken at any time, there's no "windows of uncertainty". Commented May 24, 2022 at 15:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .