From patchwork Tue Jan 29 06:06:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Filipe Brandenburger X-Patchwork-Id: 2059401 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 27295E00D9 for ; Tue, 29 Jan 2013 06:06:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753860Ab3A2GGw (ORCPT ); Tue, 29 Jan 2013 01:06:52 -0500 Received: from mail-ob0-f202.google.com ([209.85.214.202]:55499 "EHLO mail-ob0-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753786Ab3A2GGt (ORCPT ); Tue, 29 Jan 2013 01:06:49 -0500 Received: by mail-ob0-f202.google.com with SMTP id lz20so15002obb.5 for ; Mon, 28 Jan 2013 22:06:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=VNU6cZ491FkKvjkchSGShEf6os5TLlF6SAS0mAwGBus=; b=VIpLhVgBnVFU8MGmwBOiSaB4szjJW7x49H6kGD3aODx/03ukAWtfvx1FdgmdVJk2hQ PkPHsfB68e58iQCF9Wn4vpydXIExEzGc0JEmDHz04MMqI40QrHVK0F85ZUSuVB8Rs4ME Meb4nxtIe03do/CChAQvhjusEdl+XgwXjBilPWIoN1JNF0xZXBglng25D6r/1HrwALu0 zoKfO7fEc0wSqUkbsogUqHxmLVoOZQ0zkUrC0bWdXGjgL+GC+EzK0HudejABbcQ27Ghz rWNgS2ITtM1h68M5bekh7OLxb13ToqgV0BcYq9p9FR5YHxRmaBIITUIF6SWS+tY5FAoS CFkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-gm-message-state; bh=VNU6cZ491FkKvjkchSGShEf6os5TLlF6SAS0mAwGBus=; b=H3eVIzadG3vYua4Zyb/3QzOPuHwslyoE9J35aDvl27N2LYFCmmpD+F+0kujCN2jVwJ /Z8IrmfSCtzRj22fmmHQ3Xp3iVpYiAKInatqC3E+IwbF6vuXBN4S3nJbVl7INPpaCse0 +Qp8RJQY3uMgZObIds/SeNpRSPIr+JdHWCngxBUfHTq/SNi3jnNQylfiRlho6JhnxNnV f5xVcrEjlWR/K2/IXscsctJ7jIFM8GiKts8FMS0t4LHTO8ZQCWwupf3opjd/g1lMN/2l MbaGNWR13kHPQ4Trd07uJPgRk9h+zuwjtPAeKCF8Bn5ulRD/kbd7N1O/DmJY2Qf+X3Ba ek8A== X-Received: by 10.42.68.134 with SMTP id x6mr317990ici.18.1359439608991; Mon, 28 Jan 2013 22:06:48 -0800 (PST) Received: from corp2gmr1-1.hot.corp.google.com (corp2gmr1-1.hot.corp.google.com [172.24.189.92]) by gmr-mx.google.com with ESMTPS id j19si114834iga.2.2013.01.28.22.06.48 (version=TLSv1.1 cipher=AES128-SHA bits=128/128); Mon, 28 Jan 2013 22:06:48 -0800 (PST) Received: from obelix.sbo.corp.google.com (obelix.sbo.corp.google.com [172.31.172.210]) by corp2gmr1-1.hot.corp.google.com (Postfix) with ESMTP id 5475231C25A; Mon, 28 Jan 2013 22:06:48 -0800 (PST) Received: by obelix.sbo.corp.google.com (Postfix, from userid 180819) id D33752016A6; Mon, 28 Jan 2013 22:06:47 -0800 (PST) From: Filipe Brandenburger To: linux-btrfs@vger.kernel.org Cc: Filipe Brandenburger Subject: [PATCH 3/3] Add support for Btrfs ioctls: BTRFS_IOC_SPACE_INFO (filesystem df) Date: Mon, 28 Jan 2013 22:06:38 -0800 Message-Id: <1359439598-4141-4-git-send-email-filbranden@google.com> X-Mailer: git-send-email 1.8.1 In-Reply-To: <1359439598-4141-1-git-send-email-filbranden@google.com> References: <1359439598-4141-1-git-send-email-filbranden@google.com> X-Gm-Message-State: ALoCoQltzoQCbUt17gvz9G1uT5UMeaxnUGSSxOHafNPTYE2vaDy9UHM0vD4MVD2iSp56pRlCZh20tZcATKGloWK/kpSbRPLGNyzDhg0kpFBntfGUF5327/rTL2BlBFrs4/pjM4lav2rj0bmMjA2UCpcCu1j4X+yk95w4h3LMMU8wZtKj4bl6U61bSYtONbpy4h0t/1XslBN9zVRfpjkhBR5bxLp9y8TrYA== Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This adds support for the BTRFS_IOC_SPACE_INFO (used by `btrfs filesystem df') by parsing the struct passed by userspace to the kernel and interpreting the output fields filled in by kernel code. TODO: Some constants are defined in the C file because they're not currently present in linux/btrfs.h, but they should be moved to that file in Btrfs source code so that they can be used by userspace programs that need those constants. Signed-off-by: Filipe Brandenburger --- btrfs.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/btrfs.c b/btrfs.c index a4895e4..799ae46 100644 --- a/btrfs.c +++ b/btrfs.c @@ -30,10 +30,130 @@ #ifdef HAVE_LINUX_BTRFS_H #include + +/* TODO: in btrfs source code, these are currently in ctree.h, must be moved to btrfs.h */ +#ifndef BTRFS_BLOCK_GROUP_DATA +#define BTRFS_BLOCK_GROUP_DATA (1ULL << 0) +#define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1) +#define BTRFS_BLOCK_GROUP_METADATA (1ULL << 2) +#define BTRFS_BLOCK_GROUP_RAID0 (1ULL << 3) +#define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4) +#define BTRFS_BLOCK_GROUP_DUP (1ULL << 5) +#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) +#endif /* BTRFS_BLOCK_GROUP_DATA */ + +static const struct xlat btrfs_space_info_flags[] = { + {BTRFS_BLOCK_GROUP_DATA, "BTRFS_BLOCK_GROUP_DATA"}, + {BTRFS_BLOCK_GROUP_SYSTEM, "BTRFS_BLOCK_GROUP_SYSTEM"}, + {BTRFS_BLOCK_GROUP_METADATA, "BTRFS_BLOCK_GROUP_METADATA"}, + {BTRFS_BLOCK_GROUP_RAID0, "BTRFS_BLOCK_GROUP_RAID0"}, + {BTRFS_BLOCK_GROUP_RAID1, "BTRFS_BLOCK_GROUP_RAID1"}, + {BTRFS_BLOCK_GROUP_DUP, "BTRFS_BLOCK_GROUP_DUP"}, + {BTRFS_BLOCK_GROUP_RAID10, "BTRFS_BLOCK_GROUP_RAID10"}, + {0, NULL} +}; + +static void +print_space_info(struct btrfs_ioctl_space_info *si) +{ + __u64 flags; + int first; + const struct xlat *xl; + + flags = si->flags; + tprintf("{flags=%#llx", flags); + first = 1; + for (xl = btrfs_space_info_flags; flags && xl->val; xl++) { + if (flags & xl->val) { + if (first) + tprints(" /* "); + else + tprints("|"); + first = 0; + tprints(xl->str); + flags &= ~xl->val; + } + } + if (!first) { + /* flags were expanded at least once */ + if (flags) + tprintf("|%#llx */", flags); + else + tprints(" */"); + } + tprintf(", total_bytes=%llu, used_bytes=%llu}", si->total_bytes, si->used_bytes); +} + +static void +print_space_args_out(struct tcb *tcp, long arg) +{ + struct btrfs_ioctl_space_args sa, *sa_ptr; + __u64 i, total; + int truncated; + long sa_size; + + if (syserror(tcp) || umove(tcp, arg, &sa) < 0) + return; + + total = sa.total_spaces; + tprintf(", total_spaces=%llu", total); + if (total > sa.space_slots) + total = sa.space_slots; + if (total <= 0) + return; + /* if total > 10 then truncate it */ + truncated = 0; + if (total > 10) { + total = 10; + truncated = 1; + } + + sa_size = sizeof(struct btrfs_ioctl_space_args) + total * sizeof(struct btrfs_ioctl_space_info); + sa_ptr = malloc(sa_size); + if (!sa_ptr) + return; + + if (umoven(tcp, arg, sa_size, (char *) sa_ptr) < 0) + goto out; + + tprints(", spaces={"); + for (i = 0L; i < total; i++) { + if (i) + tprints(", "); + tprintf("[%llu]=", i); + print_space_info(&sa_ptr->spaces[i]); + } + if (truncated) + tprints(", ..."); + tprints("}"); + +out: + free(sa_ptr); +} + #endif /* HAVE_LINUX_BTRFS_H */ int btrfs_ioctl(struct tcb *tcp, long code, long arg) { +#ifdef HAVE_LINUX_BTRFS_H + switch (code) { + case BTRFS_IOC_SPACE_INFO: + if (entering(tcp)) { + struct btrfs_ioctl_space_args sa; + if (umove(tcp, arg, &sa) < 0) + tprintf(", %#lx", arg); + else { + tprintf(", {space_slots=%llu", sa.space_slots); + } + } + if (exiting(tcp)) { + print_space_args_out(tcp, arg); + tprints("}"); + } + return 1; + } +#endif /* HAVE_LINUX_BTRFS_H */ + return 0; }