diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 31aa4ba06fce..0f14697becef 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3336,6 +3336,61 @@ out_fput: | |||
3336 | return ret; | 3336 | return ret; |
3337 | } | 3337 | } |
3338 | 3338 | ||
3339 | /* | ||
3340 | * there are many ways the trans_start and trans_end ioctls can lead | ||
3341 | * to deadlocks. They should only be used by applications that | ||
3342 | * basically own the machine, and have a very in depth understanding | ||
3343 | * of all the possible deadlocks and enospc problems. | ||
3344 | */ | ||
3345 | long btrfs_ioctl_trans_start(struct file *file) | ||
3346 | { | ||
3347 | struct inode *inode = fdentry(file)->d_inode; | ||
3348 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
3349 | struct btrfs_trans_handle *trans; | ||
3350 | int ret = 0; | ||
3351 | |||
3352 | mutex_lock(&root->fs_info->fs_mutex); | ||
3353 | if (file->private_data) { | ||
3354 | ret = -EINPROGRESS; | ||
3355 | goto out; | ||
3356 | } | ||
3357 | trans = btrfs_start_transaction(root, 0); | ||
3358 | if (trans) | ||
3359 | file->private_data = trans; | ||
3360 | else | ||
3361 | ret = -ENOMEM; | ||
3362 | /*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/ | ||
3363 | out: | ||
3364 | mutex_unlock(&root->fs_info->fs_mutex); | ||
3365 | return ret; | ||
3366 | } | ||
3367 | |||
3368 | /* | ||
3369 | * there are many ways the trans_start and trans_end ioctls can lead | ||
3370 | * to deadlocks. They should only be used by applications that | ||
3371 | * basically own the machine, and have a very in depth understanding | ||
3372 | * of all the possible deadlocks and enospc problems. | ||
3373 | */ | ||
3374 | long btrfs_ioctl_trans_end(struct file *file) | ||
3375 | { | ||
3376 | struct inode *inode = fdentry(file)->d_inode; | ||
3377 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
3378 | struct btrfs_trans_handle *trans; | ||
3379 | int ret = 0; | ||
3380 | |||
3381 | mutex_lock(&root->fs_info->fs_mutex); | ||
3382 | trans = file->private_data; | ||
3383 | if (!trans) { | ||
3384 | ret = -EINVAL; | ||
3385 | goto out; | ||
3386 | } | ||
3387 | btrfs_end_transaction(trans, root); | ||
3388 | file->private_data = 0; | ||
3389 | out: | ||
3390 | mutex_unlock(&root->fs_info->fs_mutex); | ||
3391 | return ret; | ||
3392 | } | ||
3393 | |||
3339 | long btrfs_ioctl(struct file *file, unsigned int | 3394 | long btrfs_ioctl(struct file *file, unsigned int |
3340 | cmd, unsigned long arg) | 3395 | cmd, unsigned long arg) |
3341 | { | 3396 | { |
@@ -3356,6 +3411,13 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3356 | return btrfs_balance(root->fs_info->dev_root); | 3411 | return btrfs_balance(root->fs_info->dev_root); |
3357 | case BTRFS_IOC_CLONE: | 3412 | case BTRFS_IOC_CLONE: |
3358 | return btrfs_ioctl_clone(file, arg); | 3413 | return btrfs_ioctl_clone(file, arg); |
3414 | case BTRFS_IOC_TRANS_START: | ||
3415 | return btrfs_ioctl_trans_start(file); | ||
3416 | case BTRFS_IOC_TRANS_END: | ||
3417 | return btrfs_ioctl_trans_end(file); | ||
3418 | case BTRFS_IOC_SYNC: | ||
3419 | btrfs_sync_fs(file->f_dentry->d_sb, 1); | ||
3420 | return 0; | ||
3359 | } | 3421 | } |
3360 | 3422 | ||
3361 | return -ENOTTY; | 3423 | return -ENOTTY; |
@@ -3679,6 +3741,7 @@ static struct file_operations btrfs_dir_file_operations = { | |||
3679 | #ifdef CONFIG_COMPAT | 3741 | #ifdef CONFIG_COMPAT |
3680 | .compat_ioctl = btrfs_ioctl, | 3742 | .compat_ioctl = btrfs_ioctl, |
3681 | #endif | 3743 | #endif |
3744 | .release = btrfs_release_file, | ||
3682 | }; | 3745 | }; |
3683 | 3746 | ||
3684 | static struct extent_io_ops btrfs_extent_io_ops = { | 3747 | static struct extent_io_ops btrfs_extent_io_ops = { |