Written against the btrfs-unstable git tree, the attached patch
installs cleanly against the latest kernel (as of two weeks ago.)

The patches for btrfsctl and btrfs programs will be coming soon; I'm
adding support for ISO8061 duration strings instead of (or in addition
to) milliseconds and thinking about switching the order of the two
args to btrfsctl -C from (path(default=.), ms(default=0)) to timeout
then path, to keep it consistent with the other btrfsctl commands.
Currently -C is special-cased in the bottom half of my btrfsctl.c
because the path isn't the last argument.

Btrfsctl apparently allows several operations to be presented as one
set of command line arguments, sort of like find(1) does; would
someone who does that a lot please respond off-list to discuss the
ideal semantics of new commands?

Also, I can now privately send the progs patch to anyone who wants to
test it as-is, but I don't want to "publish" it until the interface
(what format the optional timeout is in) is frozen.
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index e9bf864..a350b75 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -895,6 +895,7 @@ struct btrfs_fs_info {
 	struct list_head trans_list;
 	struct list_head hashers;
 	struct list_head dead_roots;
+	wait_queue_head_t cleaner_notification_registration;
 	struct list_head caching_block_groups;
 
 	spinlock_t delayed_iput_lock;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 34f7c37..6a35257 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1451,6 +1451,7 @@ static int cleaner_kthread(void *arg)
 		    mutex_trylock(&root->fs_info->cleaner_mutex)) {
 			btrfs_run_delayed_iputs(root);
 			btrfs_clean_old_snapshots(root);
+			wake_up_all(&root->fs_info->cleaner_notification_registration);
 			mutex_unlock(&root->fs_info->cleaner_mutex);
 		}
 
@@ -1581,6 +1582,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 	INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
 	INIT_LIST_HEAD(&fs_info->trans_list);
 	INIT_LIST_HEAD(&fs_info->dead_roots);
+	init_waitqueue_head(&fs_info->cleaner_notification_registration);
 	INIT_LIST_HEAD(&fs_info->delayed_iputs);
 	INIT_LIST_HEAD(&fs_info->hashers);
 	INIT_LIST_HEAD(&fs_info->delalloc_inodes);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 9254b3d..9f5a525 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1212,6 +1212,46 @@ static noinline int btrfs_ioctl_ino_lookup(struct file *file,
 	return ret;
 }
 
+static int btrfs_ioctl_cleaner_wait(struct btrfs_root *root, void __user *arg)
+{
+        struct btrfs_ioctl_cleaner_wait_args *bicwa;
+        long remainingjiffies;
+        int err;
+
+	bicwa = memdup_user(arg, sizeof(*bicwa));
+	if (IS_ERR(bicwa))
+		return PTR_ERR(bicwa);
+
+        err = -EINVAL;
+
+        if (bicwa->ms > 0)
+	{
+            remainingjiffies = wait_event_interruptible_timeout(
+                 root->fs_info->cleaner_notification_registration,
+                 list_empty(&root->fs_info->dead_roots),
+                 msecs_to_jiffies(bicwa->ms)
+            );
+            if (remainingjiffies > 0)
+                  err = 0;
+            else if (remainingjiffies < 0 )
+                  err = -EAGAIN;
+            else
+                  err = -ETIME;
+        }
+	else
+	{
+            err = wait_event_interruptible(
+                 root->fs_info->cleaner_notification_registration,
+                 list_empty(&root->fs_info->dead_roots)
+            );
+        };
+
+	kfree(bicwa);
+        return err;
+
+}
+
+
 static noinline int btrfs_ioctl_snap_destroy(struct file *file,
 					     void __user *arg)
 {
@@ -2003,6 +2043,8 @@ long btrfs_ioctl(struct file *file, unsigned int
 		return btrfs_ioctl_snap_create(file, argp, 1);
 	case BTRFS_IOC_SNAP_DESTROY:
 		return btrfs_ioctl_snap_destroy(file, argp);
+	case BTRFS_IOC_CLEANER_WAIT:
+		return btrfs_ioctl_cleaner_wait(root, argp);
 	case BTRFS_IOC_DEFAULT_SUBVOL:
 		return btrfs_ioctl_default_subvol(file, argp);
 	case BTRFS_IOC_DEFRAG:
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index 424694a..cd15a50 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -138,6 +138,10 @@ struct btrfs_ioctl_space_args {
 	struct btrfs_ioctl_space_info spaces[0];
 };
 
+struct btrfs_ioctl_cleaner_wait_args{
+        unsigned long ms;
+};
+
 #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
 				   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -178,4 +182,6 @@ struct btrfs_ioctl_space_args {
 #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64)
 #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \
 				    struct btrfs_ioctl_space_args)
+#define BTRFS_IOC_CLEANER_WAIT _IOW(BTRFS_IOCTL_MAGIC, 21, \
+				    struct btrfs_ioctl_cleaner_wait_args)
 #endif

Reply via email to