diff options
-rw-r--r-- | fs/btrfs/ioctl.c | 3 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 15 | ||||
-rw-r--r-- | fs/btrfs/tree-log.h | 2 |
3 files changed, 20 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 86249cf78897..ccb30ca9ebb2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include "props.h" | 59 | #include "props.h" |
60 | #include "sysfs.h" | 60 | #include "sysfs.h" |
61 | #include "qgroup.h" | 61 | #include "qgroup.h" |
62 | #include "tree-log.h" | ||
62 | 63 | ||
63 | #ifdef CONFIG_64BIT | 64 | #ifdef CONFIG_64BIT |
64 | /* If we have a 32-bit userspace and 64-bit kernel, then the UAPI | 65 | /* If we have a 32-bit userspace and 64-bit kernel, then the UAPI |
@@ -2521,6 +2522,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2521 | out_end_trans: | 2522 | out_end_trans: |
2522 | trans->block_rsv = NULL; | 2523 | trans->block_rsv = NULL; |
2523 | trans->bytes_reserved = 0; | 2524 | trans->bytes_reserved = 0; |
2525 | if (!err) | ||
2526 | btrfs_record_snapshot_destroy(trans, dir); | ||
2524 | ret = btrfs_end_transaction(trans, root); | 2527 | ret = btrfs_end_transaction(trans, root); |
2525 | if (ret && !err) | 2528 | if (ret && !err) |
2526 | err = ret; | 2529 | err = ret; |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 978c3a810893..43c6781af654 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -5498,6 +5498,21 @@ record: | |||
5498 | } | 5498 | } |
5499 | 5499 | ||
5500 | /* | 5500 | /* |
5501 | * Make sure that if someone attempts to fsync the parent directory of a deleted | ||
5502 | * snapshot, it ends up triggering a transaction commit. This is to guarantee | ||
5503 | * that after replaying the log tree of the parent directory's root we will not | ||
5504 | * see the snapshot anymore and at log replay time we will not see any log tree | ||
5505 | * corresponding to the deleted snapshot's root, which could lead to replaying | ||
5506 | * it after replaying the log tree of the parent directory (which would replay | ||
5507 | * the snapshot delete operation). | ||
5508 | */ | ||
5509 | void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans, | ||
5510 | struct inode *dir) | ||
5511 | { | ||
5512 | BTRFS_I(dir)->last_unlink_trans = trans->transid; | ||
5513 | } | ||
5514 | |||
5515 | /* | ||
5501 | * Call this after adding a new name for a file and it will properly | 5516 | * Call this after adding a new name for a file and it will properly |
5502 | * update the log to reflect the new name. | 5517 | * update the log to reflect the new name. |
5503 | * | 5518 | * |
diff --git a/fs/btrfs/tree-log.h b/fs/btrfs/tree-log.h index 6916a781ea02..a9f1b75d080d 100644 --- a/fs/btrfs/tree-log.h +++ b/fs/btrfs/tree-log.h | |||
@@ -79,6 +79,8 @@ int btrfs_pin_log_trans(struct btrfs_root *root); | |||
79 | void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans, | 79 | void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans, |
80 | struct inode *dir, struct inode *inode, | 80 | struct inode *dir, struct inode *inode, |
81 | int for_rename); | 81 | int for_rename); |
82 | void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans, | ||
83 | struct inode *dir); | ||
82 | int btrfs_log_new_name(struct btrfs_trans_handle *trans, | 84 | int btrfs_log_new_name(struct btrfs_trans_handle *trans, |
83 | struct inode *inode, struct inode *old_dir, | 85 | struct inode *inode, struct inode *old_dir, |
84 | struct dentry *parent); | 86 | struct dentry *parent); |