From patchwork Sun Jan 16 20:52:39 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Nicol X-Patchwork-Id: 482721 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0GKrP0h000497 for ; Sun, 16 Jan 2011 20:53:25 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753900Ab1APUxW (ORCPT ); Sun, 16 Jan 2011 15:53:22 -0500 Received: from mail-iy0-f174.google.com ([209.85.210.174]:59123 "EHLO mail-iy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753666Ab1APUxV convert rfc822-to-8bit (ORCPT ); Sun, 16 Jan 2011 15:53:21 -0500 Received: by iyj18 with SMTP id 18so4071173iyj.19 for ; Sun, 16 Jan 2011 12:53:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:from:date:message-id:subject:to :content-type:content-transfer-encoding; bh=Xt4dyPkor4Hpo+3Z09Qd6qjp0X9X7si1POpa9cLHN8I=; b=BHdAzhs2L4QOQ8El7eIfOYrzdlo7cIWw94j2FnHS8sU1XtUTmhYPIxFpv+u9LLF2au ZsePhYtWGUnHsXlrljE7ifoqMJqQ1rN5USuF0xv77A7Ywwejl4VY9nBsMM6V9NNoauVx a42g0cmIHMfdxR2eQwY2ZKd4EaWh68GI4Syhw= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:from:date:message-id:subject:to:content-type :content-transfer-encoding; b=bZaBNL+TsW3of8E2Am0B/zARME+Bo+VgOnZIhSk8tR6ff2uX7XgwX5vKzyHo3yr+TL j5xTR7nlUmGJK79uHPv29Z068cN8NMVVP8oBThK4ZVMxPnGIE7wnG6wJGk0mfMkazkvB ZWBcgfQaU6wz9Y37wUYll1EnCnWDFLFX47KJY= Received: by 10.231.31.4 with SMTP id w4mr3284298ibc.140.1295211200577; Sun, 16 Jan 2011 12:53:20 -0800 (PST) MIME-Version: 1.0 Received: by 10.231.206.148 with HTTP; Sun, 16 Jan 2011 12:52:39 -0800 (PST) From: David Nicol Date: Sun, 16 Jan 2011 14:52:39 -0600 Message-ID: Subject: ioctl #21 kernel patch that (1) actually works, to wait for dead_roots cleaning and (2) provides framework for adding facility for user-space waiting for anything else deferred To: BTRFS MAILING LIST , "chris.mason" Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Sun, 16 Jan 2011 20:53:25 +0000 (UTC) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 29c2009..250f2f1 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -895,6 +895,8 @@ struct btrfs_fs_info { struct list_head trans_list; struct list_head hashers; struct list_head dead_roots; + atomic_t dead_roots_cleaners ; + 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..d2741c5 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1450,7 +1450,9 @@ static int cleaner_kthread(void *arg) if (!(root->fs_info->sb->s_flags & MS_RDONLY) && mutex_trylock(&root->fs_info->cleaner_mutex)) { btrfs_run_delayed_iputs(root); + wake_up_all(&root->fs_info->cleaner_notification_registration); btrfs_clean_old_snapshots(root); + wake_up_all(&root->fs_info->cleaner_notification_registration); mutex_unlock(&root->fs_info->cleaner_mutex); } @@ -1581,6 +1583,8 @@ 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); + atomic_set(&fs_info->dead_roots_cleaners,0); + 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); @@ -2393,7 +2397,9 @@ int btrfs_commit_super(struct btrfs_root *root) mutex_lock(&root->fs_info->cleaner_mutex); btrfs_run_delayed_iputs(root); + wake_up_all(&root->fs_info->cleaner_notification_registration); btrfs_clean_old_snapshots(root); + wake_up_all(&root->fs_info->cleaner_notification_registration); mutex_unlock(&root->fs_info->cleaner_mutex); /* wait until ongoing cleanup work done */ diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 9254b3d..b669f19 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1212,6 +1212,66 @@ 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; + + /* flag bit 0x04 means, error on unknown flag. + the highest possible valid flag value at this rev is 0x07. */ + if (((bicwa->flags & 4) == 4) &&( bicwa->flags > 7) ){ + kfree(bicwa); + return err; + }; + +#define BICW_TEST ( \ + /* flag bit 0x01: suppress wait for dead_roots */ \ + (bicwa->flags & 1 == 1 || ( list_empty(&root->fs_info->dead_roots)) \ + && ( atomic_read(&root->fs_info->dead_roots_cleaners) == 0 )) \ + \ + /* flag bit 0x02: wait for delayed iputs */ \ + && (bicwa->flags & 2 == 0 || list_empty(&root->fs_info->delayed_iputs)) \ + \ + /* 0x04 is consumed earlier */ \ + /* add the next one at 0x08 */ \ +) + + if (bicwa->ms > 0) + { + unsigned long millisecs = bicwa->ms; + remainingjiffies = wait_event_interruptible_timeout( + root->fs_info->cleaner_notification_registration, + BICW_TEST, msecs_to_jiffies(millisecs) + ); + 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, + BICW_TEST + ); + }; + + kfree(bicwa); + return err; + +#undef BICWATEST +} + + static noinline int btrfs_ioctl_snap_destroy(struct file *file, void __user *arg) { @@ -2003,6 +2063,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..9af8530 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{ + __u32 ms; + __u32 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 diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 66e4c66..1e3909d 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1205,6 +1205,7 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root) LIST_HEAD(list); struct btrfs_fs_info *fs_info = root->fs_info; + atomic_inc(&fs_info->dead_roots_cleaners); mutex_lock(&fs_info->trans_mutex); list_splice_init(&fs_info->dead_roots, &list); mutex_unlock(&fs_info->trans_mutex); @@ -1219,5 +1220,6 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root) else btrfs_drop_snapshot(root, NULL, 1); } + atomic_dec(&fs_info->dead_roots_cleaners); return 0; }