From patchwork Tue Sep 15 09:02:03 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yang Dongsheng X-Patchwork-Id: 7182771 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 07310BEEC1 for ; Tue, 15 Sep 2015 09:37:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0C29320529 for ; Tue, 15 Sep 2015 09:37:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E524220647 for ; Tue, 15 Sep 2015 09:37:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754595AbbIOJhm (ORCPT ); Tue, 15 Sep 2015 05:37:42 -0400 Received: from cn.fujitsu.com ([59.151.112.132]:53515 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1754134AbbIOJJI (ORCPT ); Tue, 15 Sep 2015 05:09:08 -0400 X-IronPort-AV: E=Sophos;i="5.15,520,1432569600"; d="scan'208";a="100730363" Received: from unknown (HELO edo.cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 15 Sep 2015 17:11:58 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (localhost.localdomain [127.0.0.1]) by edo.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id t8F98pPj008013; Tue, 15 Sep 2015 17:08:51 +0800 Received: from yds-PC.g08.fujitsu.local (10.167.226.66) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.181.6; Tue, 15 Sep 2015 17:09:06 +0800 From: Dongsheng Yang To: , , , CC: , , Dongsheng Yang Subject: [PATCH v3 08/39] fs: introduce a __lookup_dev for internal using Date: Tue, 15 Sep 2015 17:02:03 +0800 Message-ID: <1442307754-13233-9-git-send-email-yangds.fnst@cn.fujitsu.com> X-Mailer: git-send-email 1.8.4.2 In-Reply-To: <1442307754-13233-1-git-send-email-yangds.fnst@cn.fujitsu.com> References: <1442307754-13233-1-git-send-email-yangds.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.226.66] 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.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, 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 This commit introduce a file of fs/dev.c at first. This is a internal file shared by block_dev and char_dev. There is only one function in it __lookup_dev which will be wrapped to be lookup_bdev and loopup_cdev. We will put more code in this file which is shared by block_dev and char_dev. Signed-off-by: Dongsheng Yang Reviewed-by: Jan Kara --- fs/Makefile | 2 +- fs/block_dev.c | 26 ++------------------ fs/dev.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/internal.h | 14 +++++++++++ 4 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 fs/dev.c diff --git a/fs/Makefile b/fs/Makefile index cb20e4b..87756f0 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -5,7 +5,7 @@ # Rewritten to use lists instead of if-statements. # -obj-y := open.o read_write.o file_table.o super.o \ +obj-y := open.o read_write.o file_table.o super.o dev.o\ char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ ioctl.o readdir.o select.o dcache.o inode.o \ attr.o bad_inode.o file.o filesystems.o namespace.o \ diff --git a/fs/block_dev.c b/fs/block_dev.c index 1982437..05cf2ea 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -665,7 +665,7 @@ void bdput(struct block_device *bdev) EXPORT_SYMBOL(bdput); -static struct block_device *bd_acquire(struct inode *inode) +struct block_device *bd_acquire(struct inode *inode) { struct block_device *bdev; @@ -1713,34 +1713,12 @@ EXPORT_SYMBOL(ioctl_by_bdev); struct block_device *lookup_bdev(const char *pathname) { struct block_device *bdev; - struct inode *inode; - struct path path; int error; - if (!pathname || !*pathname) - return ERR_PTR(-EINVAL); - - error = kern_path(pathname, LOOKUP_FOLLOW, &path); + error = __lookup_dev(pathname, NULL, &bdev); if (error) return ERR_PTR(error); - - inode = d_backing_inode(path.dentry); - error = -ENOTBLK; - if (!S_ISBLK(inode->i_mode)) - goto fail; - error = -EACCES; - if (path.mnt->mnt_flags & MNT_NODEV) - goto fail; - error = -ENOMEM; - bdev = bd_acquire(inode); - if (!bdev) - goto fail; -out: - path_put(&path); return bdev; -fail: - bdev = ERR_PTR(error); - goto out; } EXPORT_SYMBOL(lookup_bdev); diff --git a/fs/dev.c b/fs/dev.c new file mode 100644 index 0000000..5356a47 --- /dev/null +++ b/fs/dev.c @@ -0,0 +1,77 @@ +/* + * This file contains some functions shared by block_dev and char_dev + */ +#include +#include +#include + +#include "internal.h" + +/** + * __lookup_dev - lookup a block_device or cdev by name + * @pathname: special file representing the device + * @cdevp: cdev would be returned by cdevp + * @bdevp: block_device would be returned by bdevp + * + * Get a reference to the block_deivce or cdev at @pathname in + * the current namespace if possible and return it. + */ +int __lookup_dev(const char *pathname, struct cdev **cdevp, + struct block_device **bdevp) +{ + struct inode *inode; + struct path path; + int error = 0; + + if (!pathname || !*pathname) + return -EINVAL; + + error = kern_path(pathname, LOOKUP_FOLLOW, &path); + if (error) + return error; + + inode = d_backing_inode(path.dentry); + + /** + * We need at least one of bdevp and cdevp to be NULL, + * but cdevp and bdevp can not be both NULL. + */ + error = -EINVAL; + if (!(cdevp || bdevp) || (cdevp && bdevp)) + goto out; + + if (cdevp) { + if (!S_ISCHR(inode->i_mode)) { + error = -EINVAL; + goto out; + } + } else { + if (!S_ISBLK(inode->i_mode)) { + error = -ENOTBLK; + goto out; + } + } + error = -EACCES; + if (path.mnt->mnt_flags & MNT_NODEV) + goto out; + error = -ENXIO; + if (S_ISCHR(inode->i_mode)) { + struct cdev *cdev; + + cdev = cd_acquire(inode); + if (!cdev) + goto out; + *cdevp = cdev; + } else { + struct block_device *bdev; + + bdev = bd_acquire(inode); + if (!bdev) + goto out; + *bdevp = bdev; + } + error = 0; +out: + path_put(&path); + return error; +} diff --git a/fs/internal.h b/fs/internal.h index 4d5af58..337b29c 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -17,6 +17,12 @@ struct mount; struct shrink_control; /* + * dev.c + */ +extern int __lookup_dev(const char *pathname, struct cdev **cdevp, + struct block_device **bdevp); + +/* * block_dev.c */ #ifdef CONFIG_BLOCK @@ -24,6 +30,8 @@ extern void __init bdev_cache_init(void); extern int __sync_blockdev(struct block_device *bdev, int wait); +extern struct block_device *bd_acquire(struct inode *inode); + #else static inline void bdev_cache_init(void) { @@ -33,6 +41,11 @@ static inline int __sync_blockdev(struct block_device *bdev, int wait) { return 0; } + +static struct block_device *bd_acquire(struct inode *inode) +{ + return NULL; +} #endif /* @@ -44,6 +57,7 @@ extern void guard_bio_eod(int rw, struct bio *bio); * char_dev.c */ extern void __init chrdev_init(void); +extern struct cdev *cd_acquire(struct inode *inode); /* * namei.c