From patchwork Fri Mar 4 16:10:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Axboe X-Patchwork-Id: 8505211 Return-Path: X-Original-To: patchwork-linux-block@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C40709F7CA for ; Fri, 4 Mar 2016 16:12:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A84552014A for ; Fri, 4 Mar 2016 16:12:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7B75B20166 for ; Fri, 4 Mar 2016 16:12:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759793AbcCDQLv (ORCPT ); Fri, 4 Mar 2016 11:11:51 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:60141 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759854AbcCDQLt (ORCPT ); Fri, 4 Mar 2016 11:11:49 -0500 Received: from pps.filterd (m0044012.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.15.0.59/8.15.0.59) with SMTP id u24G9RXC031370; Fri, 4 Mar 2016 08:11:45 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=VtJY5iYP7qcesYJHfHIyRpxGv7qoykUn4E0Y5rE/vOg=; b=LeTaAvws6hUe/k1XoysiMvsh9imBfSr689Sv/HBjNBEFCIFQjIdyIjFaXugAJxs1ALpm hS+xggmzhObuKtPpYaZYGIfSgByFY7ih6EIlF51tWrEHnsBJ8ULi/0k7WnfV6Ag6RbER x6ARYo9HITP1nAnflcpWYe+XwDXjdSzj/ws= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 21f6yj1f44-8 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT); Fri, 04 Mar 2016 08:11:45 -0800 Received: from localhost.localdomain (192.168.54.13) by mail.thefacebook.com (192.168.16.15) with Microsoft SMTP Server (TLS) id 14.3.248.2; Fri, 4 Mar 2016 08:11:02 -0800 From: Jens Axboe To: , CC: , , , Jens Axboe Subject: [PATCH 06/11] Add support for bdi tracking of stream ID Date: Fri, 4 Mar 2016 09:10:48 -0700 Message-ID: <1457107853-8689-7-git-send-email-axboe@fb.com> X-Mailer: git-send-email 2.4.1.168.g1ea28e1 In-Reply-To: <1457107853-8689-1-git-send-email-axboe@fb.com> References: <1457107853-8689-1-git-send-email-axboe@fb.com> MIME-Version: 1.0 X-Originating-IP: [192.168.54.13] X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-03-04_07:, , signatures=0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We can now allocate and free host assigned stream IDs through the backing device. Add support for a hook for virtual backing devices, that map to a bunch of real backing devices (btrfs, raid, etc). Signed-off-by: Jens Axboe --- fs/read_write.c | 35 ++++++++++++++++++-------- include/linux/backing-dev-defs.h | 7 ++++++ include/linux/backing-dev.h | 3 +++ include/linux/streamid.h | 4 +++ mm/backing-dev.c | 53 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 10 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index 6dcae3eb7b0f..7218d69b1763 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1674,7 +1674,8 @@ SYSCALL_DEFINE4(streamid, int, fd, int, cmd, unsigned int, flags, int, streamid) { struct inode *inode; - ssize_t ret = 0; + int alloc_id; + ssize_t ret; struct fd f; if (cmd != STREAMID_OPEN && cmd != STREAMID_CLOSE && @@ -1682,6 +1683,8 @@ SYSCALL_DEFINE4(streamid, int, fd, int, cmd, return -EINVAL; if (flags & ~(STREAMID_F_INODE | STREAMID_F_FILE)) return -EINVAL; + if (streamid > STREAMID_MAX) + return -EINVAL; f = fdget(fd); if (!f.file) @@ -1693,11 +1696,26 @@ SYSCALL_DEFINE4(streamid, int, fd, int, cmd, goto done; } + if (cmd == STREAMID_GET) { + ret = 0; + if (flags & STREAMID_F_FILE) + ret = f.file->f_streamid; + if (!ret && (flags & STREAMID_F_INODE)) + ret = inode_streamid(inode); + if (!(flags & (STREAMID_F_FILE | STREAMID_F_INODE))) + ret = file_streamid(f.file); + goto done; + } + + alloc_id = ret = bdi_streamid(f.file->f_mapping->host, cmd, streamid); + if (ret < 0) + goto done; + if (cmd == STREAMID_OPEN) { if (flags & STREAMID_F_FILE) { if (f.file->f_streamid) { ret = -EBUSY; - goto done; + goto error_close; } f.file->f_streamid = ret; } @@ -1708,6 +1726,8 @@ SYSCALL_DEFINE4(streamid, int, fd, int, cmd, else inode->i_streamid = ret; spin_unlock(&inode->i_lock); + if (ret < 0) + goto error_close; } } else if (cmd == STREAMID_CLOSE) { if (f.file->f_streamid == streamid) @@ -1717,17 +1737,12 @@ SYSCALL_DEFINE4(streamid, int, fd, int, cmd, inode->i_streamid = 0; spin_unlock(&inode->i_lock); } - } else if (cmd == STREAMID_GET) { - ret = 0; - if (flags & STREAMID_F_FILE) - ret = f.file->f_streamid; - if (!ret && (flags & STREAMID_F_INODE)) - ret = inode_streamid(inode); - if (!(flags & (STREAMID_F_FILE | STREAMID_F_INODE))) - ret = file_streamid(f.file); } done: fdput(f); return ret; +error_close: + bdi_streamid(f.file->f_mapping->host, STREAMID_CLOSE, alloc_id); + goto done; } diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h index 1b4d69f68c33..8c1914b15cd0 100644 --- a/include/linux/backing-dev-defs.h +++ b/include/linux/backing-dev-defs.h @@ -10,6 +10,7 @@ #include #include #include +#include struct page; struct device; @@ -30,6 +31,7 @@ enum wb_congested_state { }; typedef int (congested_fn)(void *, int); +typedef int (streamid_fn)(void *, unsigned int); enum wb_stat_item { WB_RECLAIMABLE, @@ -170,6 +172,11 @@ struct backing_dev_info { struct dentry *debug_dir; struct dentry *debug_stats; #endif + + struct ida stream_ids; + streamid_fn *streamid_open; + streamid_fn *streamid_close; + void *streamid_data; }; enum { diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index c82794f20110..b20e33b71071 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -514,4 +514,7 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi) (1 << WB_async_congested)); } +int bdi_streamid_open(struct backing_dev_info *bdi, unsigned int id); +int bdi_streamid_close(struct backing_dev_info *bdi, unsigned int id); + #endif /* _LINUX_BACKING_DEV_H */ diff --git a/include/linux/streamid.h b/include/linux/streamid.h index ea1f8e7eb8a5..c7ba4770a792 100644 --- a/include/linux/streamid.h +++ b/include/linux/streamid.h @@ -6,8 +6,12 @@ enum { STREAMID_CLOSE = 2, /* close stream */ STREAMID_GET = 3, /* get file/inode stream ID */ + STREAMID_MAX = 65535, + STREAMID_F_INODE = 1, /* set streamid on the inode */ STREAMID_F_FILE = 2, /* set streamid on the file */ }; +ssize_t bdi_streamid(struct inode *inode, int cmd, int streamid); + #endif diff --git a/mm/backing-dev.c b/mm/backing-dev.c index c554d173a65f..2ed97181ad49 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -10,6 +10,7 @@ #include #include #include +#include #include static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); @@ -809,6 +810,7 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent, bdi_debug_register(bdi, dev_name(dev)); set_bit(WB_registered, &bdi->wb.state); + ida_init(&bdi->stream_ids); spin_lock_bh(&bdi_lock); list_add_tail_rcu(&bdi->bdi_list, &bdi_list); @@ -843,6 +845,7 @@ void bdi_unregister(struct backing_dev_info *bdi) bdi_remove_from_list(bdi); wb_shutdown(&bdi->wb); cgwb_bdi_destroy(bdi); + ida_destroy(&bdi->stream_ids); if (bdi->dev) { bdi_debug_unregister(bdi); @@ -1014,6 +1017,56 @@ out: } EXPORT_SYMBOL(wait_iff_congested); +/* + * Get a new stream ID for backing device 'bdi'. If 'id' is zero, then get + * any new ID. If 'id' is non-zero, attempt to get that specific ID. If + * the bdi has a streamid_fn assigned, use that. + */ +int bdi_streamid_open(struct backing_dev_info *bdi, unsigned int id) +{ + if (bdi->streamid_open) + return bdi->streamid_open(bdi->streamid_data, id); + + if (id) + return ida_simple_get(&bdi->stream_ids, id, id + 1, GFP_NOIO); + + return ida_simple_get(&bdi->stream_ids, 1, STREAMID_MAX, GFP_NOIO); +} +EXPORT_SYMBOL(bdi_streamid_open); + +/* + * Close stream ID 'id' on bdi 'bdi'. + */ +int bdi_streamid_close(struct backing_dev_info *bdi, unsigned int id) +{ + if (bdi->streamid_close) + return bdi->streamid_close(bdi->streamid_data, id); + + /* + * If we don't have a specific open, free the ID we allocated + */ + if (!bdi->streamid_open) + return ida_simple_remove(&bdi->stream_ids, id); + + return 0; +} +EXPORT_SYMBOL(bdi_streamid_close); + +ssize_t bdi_streamid(struct inode *inode, int cmd, int streamid) +{ + struct backing_dev_info *bdi = inode_to_bdi(inode); + + if (bdi == &noop_backing_dev_info) + return -ENXIO; + + if (cmd == STREAMID_OPEN) + return bdi_streamid_open(bdi, streamid); + else if (cmd == STREAMID_CLOSE) + return bdi_streamid_close(bdi, streamid); + + return -EINVAL; +} + int pdflush_proc_obsolete(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) {