aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.cz>2013-02-09 18:38:06 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 12:59:51 -0500
commit210549ebe9047ae5a8cc47487203d3ee16a7749b (patch)
tree57c9c8123a46a1170abba0fc476ded82eac442ed /fs/btrfs
parentb069e0c3450ae388d7a9c94ded6d938a465de262 (diff)
btrfs: add cancellation points to defrag
The defrag operation can take very long, we want to have a way how to cancel it. The code checks for a pending signal at safe points in the defrag loops and returns EAGAIN. This means a user can press ^C after running 'btrfs fi defrag', woks for both defrag modes, files and root. Returning from the command was instant in my light tests, but may take longer depending on the aging factor of the filesystem. Signed-off-by: David Sterba <dsterba@suse.cz> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h7
-rw-r--r--fs/btrfs/ioctl.c6
-rw-r--r--fs/btrfs/transaction.c6
3 files changed, 19 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f1cc247f3178..14f01dc70ea6 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3786,4 +3786,11 @@ static inline int is_fstree(u64 rootid)
3786 return 1; 3786 return 1;
3787 return 0; 3787 return 0;
3788} 3788}
3789
3790static inline int btrfs_defrag_cancelled(struct btrfs_fs_info *fs_info)
3791{
3792 return signal_pending(current);
3793}
3794
3795
3789#endif 3796#endif
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 6d6314406e27..d02ec577f70f 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1202,6 +1202,12 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
1202 if (!(inode->i_sb->s_flags & MS_ACTIVE)) 1202 if (!(inode->i_sb->s_flags & MS_ACTIVE))
1203 break; 1203 break;
1204 1204
1205 if (btrfs_defrag_cancelled(root->fs_info)) {
1206 printk(KERN_DEBUG "btrfs: defrag_file cancelled\n");
1207 ret = -EAGAIN;
1208 break;
1209 }
1210
1205 if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, 1211 if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT,
1206 extent_thresh, &last_len, &skip, 1212 extent_thresh, &last_len, &skip,
1207 &defrag_end, range->flags & 1213 &defrag_end, range->flags &
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 60481a53e004..d574d830a1c4 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -984,6 +984,12 @@ int btrfs_defrag_root(struct btrfs_root *root)
984 984
985 if (btrfs_fs_closing(root->fs_info) || ret != -EAGAIN) 985 if (btrfs_fs_closing(root->fs_info) || ret != -EAGAIN)
986 break; 986 break;
987
988 if (btrfs_defrag_cancelled(root->fs_info)) {
989 printk(KERN_DEBUG "btrfs: defrag_root cancelled\n");
990 ret = -EAGAIN;
991 break;
992 }
987 } 993 }
988 root->defrag_running = 0; 994 root->defrag_running = 0;
989 return ret; 995 return ret;