From patchwork Thu May 5 18:26:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enke Chen X-Patchwork-Id: 9026561 Return-Path: X-Original-To: patchwork-linux-nfs@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 0518B9F30C for ; Thu, 5 May 2016 18:35:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D5DF6203E3 for ; Thu, 5 May 2016 18:35:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 90D9F203C3 for ; Thu, 5 May 2016 18:35:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755633AbcEESfm (ORCPT ); Thu, 5 May 2016 14:35:42 -0400 Received: from alln-iport-7.cisco.com ([173.37.142.94]:40911 "EHLO alln-iport-7.cisco.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754441AbcEESfm (ORCPT ); Thu, 5 May 2016 14:35:42 -0400 X-Greylist: delayed 568 seconds by postgrey-1.27 at vger.kernel.org; Thu, 05 May 2016 14:35:41 EDT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cisco.com; i=@cisco.com; l=7627; q=dns/txt; s=iport; t=1462473341; x=1463682941; h=subject:references:to:cc:from:message-id:date: mime-version:in-reply-to:content-transfer-encoding; bh=qM320Rx9oMwNeY0XpVtqy7EaP8yYC5VyZ4K/hPsZsfw=; b=bWnDCVR22P033farPbnU/vi93C0LcthNczQcAAY7eZZCeghShKGwQURE 7vlpr66M7Cg0F2tXH5dNCiAVN7vThxBOi/Y8OY5EOxGx9QP54oPz4y7d/ QoyGJ5+sdlaYavJLPd6SfFDYFCUVmXBd/5WvXZI2gI8wuelrb+mCzSACE w=; X-IronPort-AV: E=Sophos;i="5.24,583,1454976000"; d="scan'208";a="270034360" Received: from rcdn-core-9.cisco.com ([173.37.93.145]) by alln-iport-7.cisco.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 May 2016 18:26:12 +0000 Received: from [10.154.161.148] ([10.154.161.148]) by rcdn-core-9.cisco.com (8.14.5/8.14.5) with ESMTP id u45IQBbT026839; Thu, 5 May 2016 18:26:11 GMT Subject: [PATCH] VFS: pass the flag setting by fcntl() to vfs References: To: Alexander Viro , Jeff Layton , "J. Bruce Fields" , Trond Myklebust , Anna Schumaker Cc: linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, Enke Chen From: Enke Chen X-Forwarded-Message-Id: Message-ID: Date: Thu, 5 May 2016 11:26:11 -0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:45.0) Gecko/20100101 Thunderbird/45.0 MIME-Version: 1.0 In-Reply-To: Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-16.6 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY, USER_IN_DEF_DKIM_WL 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 VFS: pass the flag setting by fcntl() to vfs Several flags such as O_NONBLOCK are set using the fcntl() system call. Currently the flags are validated in setfl() by the vfs using the "check_flags" operation, but the eventual setting is not passed to the vfs. We have an application that uses the vfs/fuse and the flag O_NONBLOCK is critical for the application. This patch extends the "check_flags" function so that the flags are passed to the vfs layer for setting in addition to validating. More specifically: o add additional parameters to "check_flags", one for the file pointer, and one for setting. Also change the "flags" parameter from "int" to "unsigned int" to make it consistent with "filp->f_flags". o in setfl() pass the flags to vfs for setting once the flags are set correctly in the kernel. o use the "check_flags" operation in ioctl_fionbio() also for ioctl(fd, FIONOIO, &on). o make necessary adjustments to several files in fs/nfs (NFS is the only module using "check_flags"). Signed-off-by: Enke Chen Version: 4.6.0_rc6_next_20160503 Documentation/filesystems/Locking | 2 +- Documentation/filesystems/vfs.txt | 2 +- fs/fcntl.c | 10 +++++++++- fs/ioctl.c | 9 +++++++++ fs/nfs/dir.c | 2 +- fs/nfs/file.c | 7 +++++-- fs/nfs/internal.h | 2 +- fs/nfs/nfs4file.c | 2 +- include/linux/fs.h | 2 +- 9 files changed, 29 insertions(+), 9 deletions(-) --- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 75eea7c..c1cf807 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -452,7 +452,7 @@ prototypes: loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - int (*check_flags)(int); + int (*check_flags)(unsigned int, struct file *, int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index c61a223..193ee19 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -822,7 +822,7 @@ struct file_operations { int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - int (*check_flags)(int); + int (*check_flags)(unsigned int, struct file *, int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); diff --git a/fs/fcntl.c b/fs/fcntl.c index 350a2c8..5582dc8 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -32,6 +32,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg) { struct inode * inode = file_inode(filp); + unsigned int flags; int error = 0; /* @@ -59,7 +60,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg) } if (filp->f_op->check_flags) - error = filp->f_op->check_flags(arg); + error = filp->f_op->check_flags(arg, filp, 0); if (error) return error; @@ -75,8 +76,15 @@ static int setfl(int fd, struct file * filp, unsigned long arg) } spin_lock(&filp->f_lock); filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); + flags = filp->f_flags; spin_unlock(&filp->f_lock); + /* + * Pass the flags to VFS for setting. + */ + if (filp->f_op->check_flags) + error = filp->f_op->check_flags(flags, filp, 1); + out: return error; } diff --git a/fs/ioctl.c b/fs/ioctl.c index 116a333..de06d93 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -496,6 +496,7 @@ static int file_ioctl(struct file *filp, unsigned int cmd, static int ioctl_fionbio(struct file *filp, int __user *argp) { unsigned int flag; + unsigned int setfl; int on, error; error = get_user(on, argp); @@ -512,7 +513,15 @@ static int ioctl_fionbio(struct file *filp, int __user *argp) filp->f_flags |= flag; else filp->f_flags &= ~flag; + setfl = filp->f_flags; spin_unlock(&filp->f_lock); + + /* + * Do the same as in fcntl(). + */ + if (filp->f_op->check_flags) + error = filp->f_op->check_flags(setfl, filp, 1); + return error; } diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index aaf7bd0..e16de49 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1495,7 +1495,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, dfprintk(VFS, "NFS: atomic_open(%s/%lu), %pd\n", dir->i_sb->s_id, dir->i_ino, dentry); - err = nfs_check_flags(open_flags); + err = nfs_check_flags(open_flags, file, 0); if (err) return err; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 717a8d6..d049929 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -48,8 +48,11 @@ static const struct vm_operations_struct nfs_file_vm_ops; # define IS_SWAPFILE(inode) (0) #endif -int nfs_check_flags(int flags) +int nfs_check_flags(unsigned int flags, struct file *filp, int setting) { + if (setting) + return 0; + if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT)) return -EINVAL; @@ -68,7 +71,7 @@ nfs_file_open(struct inode *inode, struct file *filp) dprintk("NFS: open file(%pD2)\n", filp); nfs_inc_stats(inode, NFSIOS_VFSOPEN); - res = nfs_check_flags(filp->f_flags); + res = nfs_check_flags(filp->f_flags, filp, 0); if (res) return res; diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index f1d1d2c..0916d99 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -368,7 +368,7 @@ ssize_t nfs_file_write(struct kiocb *, struct iov_iter *); int nfs_file_release(struct inode *, struct file *); int nfs_lock(struct file *, int, struct file_lock *); int nfs_flock(struct file *, int, struct file_lock *); -int nfs_check_flags(int); +int nfs_check_flags(unsigned int, struct file *, int); /* inode.c */ extern struct workqueue_struct *nfsiod_workqueue; diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index d039051..7ae0d15 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -44,7 +44,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) dprintk("NFS: open file(%pd2)\n", dentry); - err = nfs_check_flags(openflags); + err = nfs_check_flags(openflags, filp, 0); if (err) return err; diff --git a/include/linux/fs.h b/include/linux/fs.h index d61cd08..fdc9cc9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1717,7 +1717,7 @@ struct file_operations { int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - int (*check_flags)(int); + int (*check_flags)(unsigned int, struct file *, int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);