From patchwork Tue May 5 20:02:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Axboe X-Patchwork-Id: 6342651 Return-Path: X-Original-To: patchwork-linux-fsdevel@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 CE4B79F32B for ; Tue, 5 May 2015 20:04:46 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8268E2021F for ; Tue, 5 May 2015 20:04:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 666C520117 for ; Tue, 5 May 2015 20:04:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1030883AbbEEUDR (ORCPT ); Tue, 5 May 2015 16:03:17 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:39339 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933036AbbEEUDI (ORCPT ); Tue, 5 May 2015 16:03:08 -0400 Received: from pps.filterd (m0044008 [127.0.0.1]) by mx0a-00082601.pphosted.com (8.14.5/8.14.5) with SMTP id t45K0dnC005831; Tue, 5 May 2015 13:03:06 -0700 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=G8Clrw5tLc64kErjnNh74eBVKdek/e9L7WzPaZxq73o=; b=Ewx5oYHor0R6kN91EdlOfUxtUtKn+DVUvHWXvoF2NJT6eE8j6WCbGHz1KEKPwVB5QX4U yDopBrJrxht+ZDtebEDvtnnMF5nrDrBORg5WelTqPX/2pTr2g1I07bvOS7xk0x1BkQ4Y GA6nVZUq1JRE1royfCHGxX+Cx7ax/pJwXqk= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 1u73a806ey-1 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT); Tue, 05 May 2015 13:03:06 -0700 Received: from localhost.localdomain (192.168.54.13) by mail.thefacebook.com (192.168.16.22) with Microsoft SMTP Server (TLS) id 14.3.195.1; Tue, 5 May 2015 13:03:04 -0700 From: Jens Axboe To: , CC: , , Jens Axboe Subject: [PATCH 2/7] Add support for per-file/inode stream ID Date: Tue, 5 May 2015 14:02:56 -0600 Message-ID: <1430856181-19568-3-git-send-email-axboe@fb.com> X-Mailer: git-send-email 2.4.0.rc2.1.g3d6bc9a In-Reply-To: <1430856181-19568-1-git-send-email-axboe@fb.com> References: <1430856181-19568-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:5.14.151, 1.0.33, 0.0.0000 definitions=2015-05-05_06:2015-05-05, 2015-05-05, 1970-01-01 signatures=0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=unavailable 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 Writing on flash devices can be much more efficient, if we can inform the device what kind of data can be grouped together. If the device is able to group data together with similar lifetimes, then it can be more efficient in garbage collection. This, in turn, leads to lower write amplification, which is a win on both device wear and performance. Add a new fadvise hint, POSIX_FADV_STREAMID, which sets the file and inode streamid. The file streamid is used if we have the file available at the time of the write (O_DIRECT), we use the inode streamid if not (buffered writeback). The fadvise hint uses the 'offset' field to specify a stream ID. A second POSIX_FADV_FILE_STREAMID sets only the stream ID on the file, not the inode. Signed-off-by: Jens Axboe --- fs/inode.c | 1 + fs/open.c | 1 + include/linux/fs.h | 22 ++++++++++++++++++++++ include/uapi/linux/fadvise.h | 3 +++ mm/fadvise.c | 25 +++++++++++++++++++++++++ 5 files changed, 52 insertions(+) diff --git a/fs/inode.c b/fs/inode.c index ea37cd17b53f..3ee74315c05b 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -149,6 +149,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_blocks = 0; inode->i_bytes = 0; inode->i_generation = 0; + inode->i_streamid = 0; inode->i_pipe = NULL; inode->i_bdev = NULL; inode->i_cdev = NULL; diff --git a/fs/open.c b/fs/open.c index 98e5a52dc68c..5d266ef89f4e 100644 --- a/fs/open.c +++ b/fs/open.c @@ -747,6 +747,7 @@ static int do_dentry_open(struct file *f, f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); + f->f_streamid = 0; return 0; diff --git a/include/linux/fs.h b/include/linux/fs.h index 35ec87e490b1..84a70e25bb35 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -648,6 +648,7 @@ struct inode { #ifdef CONFIG_IMA atomic_t i_readcount; /* struct files open RO */ #endif + unsigned int i_streamid; const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ struct file_lock_context *i_flctx; struct address_space i_data; @@ -668,6 +669,14 @@ struct inode { void *i_private; /* fs or device private pointer */ }; +static inline unsigned int inode_streamid(struct inode *inode) +{ + if (inode) + return inode->i_streamid; + + return 0; +} + static inline int inode_unhashed(struct inode *inode) { return hlist_unhashed(&inode->i_hash); @@ -839,6 +848,7 @@ struct file { * Must not be taken from IRQ context. */ spinlock_t f_lock; + unsigned int f_streamid; atomic_long_t f_count; unsigned int f_flags; fmode_t f_mode; @@ -870,6 +880,18 @@ struct file_handle { unsigned char f_handle[0]; }; +/* + * If the file doesn't have a stream ID set, return the inode stream ID + * in case that has been set. + */ +static inline unsigned int file_streamid(struct file *f) +{ + if (f->f_streamid) + return f->f_streamid; + + return inode_streamid(f->f_inode); +} + static inline struct file *get_file(struct file *f) { atomic_long_inc(&f->f_count); diff --git a/include/uapi/linux/fadvise.h b/include/uapi/linux/fadvise.h index e8e747139b9a..e6e561db7f88 100644 --- a/include/uapi/linux/fadvise.h +++ b/include/uapi/linux/fadvise.h @@ -18,4 +18,7 @@ #define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ #endif +#define POSIX_FADV_STREAMID 8 /* associate stream ID with file+inode */ +#define POSIX_FADV_FILE_STREAMID 9 /* associate stream ID with file */ + #endif /* FADVISE_H_INCLUDED */ diff --git a/mm/fadvise.c b/mm/fadvise.c index 4a3907cf79f8..a56e81840040 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c @@ -60,6 +60,8 @@ SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice) case POSIX_FADV_WILLNEED: case POSIX_FADV_NOREUSE: case POSIX_FADV_DONTNEED: + case POSIX_FADV_STREAMID: + case POSIX_FADV_FILE_STREAMID: /* no bad return value, but ignore advice */ break; default: @@ -144,6 +146,29 @@ SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice) } } break; + case POSIX_FADV_STREAMID: + case POSIX_FADV_FILE_STREAMID: + /* + * streamid is stored in offset... we don't limit or check + * if the device supports streams, or if it does, if the + * stream nr is within the limits. 1 is the lowest valid + * stream id, 0 is "don't care/know". + */ + if (offset != (unsigned int) offset) { + ret = -EINVAL; + break; + } + /* + * FILE_STREAMID stores only in the file, STREAMID stores + * the stream hint in both the file and the inode. + */ + f.file->f_streamid = offset; + if (advice == POSIX_FADV_STREAMID) { + spin_lock(&inode->i_lock); + inode->i_streamid = offset; + spin_unlock(&inode->i_lock); + } + break; default: ret = -EINVAL; }