diff options
author | Sage Weil <sage@newdream.net> | 2008-06-10 10:07:39 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:03 -0400 |
commit | 6bf13c0cc833bf5ba013d6aa60379484bf48c4e6 (patch) | |
tree | ae2b54a1a26a89fece49f6b6d6dff8448efab542 /fs/btrfs/file.c | |
parent | eba12c7bfcb4855fc757357e5e5b0b9a474499ba (diff) |
Btrfs: transaction ioctls
These ioctls let a user application hold a transaction open while it
performs a series of operations. A final ioctl does a sync on the fs
(closing the current transaction). This is the main requirement for
Ceph's OSD to be able to keep the data it's storing in a btrfs volume
consistent, and AFAICS it works just fine. The application would do
something like
fd = ::open("some/file", O_RDONLY);
::ioctl(fd, BTRFS_IOC_TRANS_START);
/* do a bunch of stuff */
::ioctl(fd, BTRFS_IOC_TRANS_END);
or just
::close(fd);
And to ensure it commits to disk,
::ioctl(fd, BTRFS_IOC_SYNC);
When a transaction is held open, the trans_handle is attached to the
struct file (via private_data) so that it will get cleaned up if the
process dies unexpectedly. A held transaction is also ended on fsync() to
avoid a deadlock.
A misbehaving application could also deliberately hold a transaction open,
effectively locking up the FS, so it may make sense to restrict something
like this to root or something.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c4fa4664a456..73c6d085bd90 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -978,9 +978,11 @@ out_nolock: | |||
978 | return num_written ? num_written : err; | 978 | return num_written ? num_written : err; |
979 | } | 979 | } |
980 | 980 | ||
981 | static int btrfs_release_file (struct inode * inode, struct file * filp) | 981 | int btrfs_release_file(struct inode * inode, struct file * filp) |
982 | { | 982 | { |
983 | btrfs_del_ordered_inode(inode); | 983 | btrfs_del_ordered_inode(inode); |
984 | if (filp->private_data) | ||
985 | btrfs_ioctl_trans_end(filp); | ||
984 | return 0; | 986 | return 0; |
985 | } | 987 | } |
986 | 988 | ||
@@ -1011,6 +1013,9 @@ static int btrfs_sync_file(struct file *file, | |||
1011 | /* | 1013 | /* |
1012 | * ok we haven't committed the transaction yet, lets do a commit | 1014 | * ok we haven't committed the transaction yet, lets do a commit |
1013 | */ | 1015 | */ |
1016 | if (file->private_data) | ||
1017 | btrfs_ioctl_trans_end(file); | ||
1018 | |||
1014 | trans = btrfs_start_transaction(root, 1); | 1019 | trans = btrfs_start_transaction(root, 1); |
1015 | if (!trans) { | 1020 | if (!trans) { |
1016 | ret = -ENOMEM; | 1021 | ret = -ENOMEM; |