This is once again based on 2ebc3464781ad24474abcbd2274e6254689853b5 (Dan Rosenberg July 19 2010) The delta between this and the previous ioctl#21 kernel patch I posted is that this one defines the flags field in the arguments structure, and has a comment about the intended semantics of it, and tests for the low bit to the effect that if the flags field is set to 1 the ioctl returns immediately; also if it is set >1 that is an EINVAL because this version of the kernel doesn''t know that flag, and it is better to safely full-stop instead of ignoring what might be an important flag. Or is it a better practice to ignore unexpected fields in such things? I think the proposed flag semantics as described in the introduction to the latest revision of the prog-side code might make it okay to ignore unexpected fields instead of refusing. The scenario where it matters is, running a newer, future ioctl21 invoker that knows about some future flag, against an old (such as current, after applying this patch) kernel that doesn''t. Fail or ignore? Or, do I revise it again to have two flags, one to ignore the one defined completion test, and the other to specify ignore (0) or fail (1) semantics for unrecognized flag bits? Then I''d have to add a command line arg for that, possibly "--no-forward-compat" which would set the fail-on-unrecognized-flag-bit flag. My crystal ball might need a little adjustment, I don''t know. ---------- Forwarded message ---------- Date: Thu, Oct 14, 2010 at 8:58 AM Subject: added flags to cleaner-wait structure kernel-side To: davidnicol@gmail.com 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..ffc86a8 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1212,6 +1212,65 @@ 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); + + /* the bicwa flags field is intended to hold bits + that will be set to 1 to disable a cleanliness + test. Currently there is only one test, but + when there are more (or other things, like + reprioritizing the cleaner thread because something + is waiting on it, although that happens already + because the waiting thing has yielded, so that + isn''t really a hot to-do item) this function + will of course get modified to implement them. */ + + if (bicwa->flags > 0x01) /* the highest flag we know about */ + { + err = -EINVAL; + goto done_with_bicwa; + } + + if (bicwa->ms > 0) + { + remainingjiffies = wait_event_interruptible_timeout( + root->fs_info->cleaner_notification_registration, + /* && together multiple FLAG OR TEST sequences + when there are more than one */ + ( bicwa->flags & 0x01 ? 1 : + 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) + ); + }; + + done_with_bicwa: + kfree(bicwa); + return err; + +} + + static noinline int btrfs_ioctl_snap_destroy(struct file *file, void __user *arg) { @@ -2003,6 +2062,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..18ff143 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h @@ -138,6 +138,11 @@ struct btrfs_ioctl_space_args { struct btrfs_ioctl_space_info spaces[0]; }; +struct btrfs_ioctl_cleaner_wait_args{ + unsigned long ms; + unsigned long flags; +}; + #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 +183,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 -- l''égalité des droits pour les ambidextres -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html