From patchwork Sat Mar 10 18:18:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andiry Xu X-Patchwork-Id: 10273989 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DF15A605D2 for ; Sat, 10 Mar 2018 18:22:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CD75E29106 for ; Sat, 10 Mar 2018 18:22:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C1B5A29735; Sat, 10 Mar 2018 18:22:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_NONE,T_DKIM_INVALID autolearn=no version=3.3.1 Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 535AF296E5 for ; Sat, 10 Mar 2018 18:22:02 +0000 (UTC) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 876652264D226; Sat, 10 Mar 2018 10:15:31 -0800 (PST) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:400e:c00::244; helo=mail-pf0-x244.google.com; envelope-from=jix024@eng.ucsd.edu; receiver=linux-nvdimm@lists.01.org Received: from mail-pf0-x244.google.com (mail-pf0-x244.google.com [IPv6:2607:f8b0:400e:c00::244]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id CDC262258AF0B for ; Sat, 10 Mar 2018 10:15:29 -0800 (PST) Received: by mail-pf0-x244.google.com with SMTP id z10so2608032pfh.13 for ; Sat, 10 Mar 2018 10:21:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=eng.ucsd.edu; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yd+84+j3iEoEam5TkIADwdGgMrtQ2QxxG+sExNSVx/Q=; b=a1TjKQ2shuxsnPCghv98paTB2VAEIxwojPuG7DBipFT7uOVOcAu94nQ1ejBHSYV8Sv O6sGatmWwxxLsSyTEYpButVWnM0m+6qEKZ/57Z19u8S2Rt/fFI2lQmcZaC2ogMZ+vZ55 zPeySfs/eNwP+l8XLZl9NpXbK3z7LKZ/RVKIY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=yd+84+j3iEoEam5TkIADwdGgMrtQ2QxxG+sExNSVx/Q=; b=nTkbL+UWKrlOzcBo2Ji2K/ixoyC249iECH1rv9HAa3KBbdY0E7o81sq2eBKW0q/HVM 5gBBEL+ebmopDl3CztvSxlXvd3qnlhjVZBn3rNK6pBuXB9AE7qz4SZjGwZcx6b5jRfVc 51y3elm87y9uZTHPH5wqgRBHFy0XKMO0D9NhuIabwrDoZYS7G0xeKy6OAaZjf3TxSk2l eZPHUVy0CKT8CpY4cEC3FbG9R4GTMy3h6PRbnI9KWe7ta1jgjtMasWv1VwqTKFLXyPxL gSE9mEbbEDuDE5yYX96iF7Xfbsv/EF8qvROns+IjU8d6OMEis2f1tWdNKYZsFb6cZONA k57A== X-Gm-Message-State: AElRT7GEvnINs1J0B/UNfZpg/poiMJyP4XMqDSr0ZjK4ntDt18WPgIPt 8gNr84L9Au9oyJInBR8OTnWAjA== X-Google-Smtp-Source: AG47ELvnRxhRLakMrDKlTPiYzoenCyFU3bRSSBQ+B4WIa3eCXIjbJmvCScswx8w3pYXtBlyEWT0dgw== X-Received: by 10.98.147.156 with SMTP id r28mr2691177pfk.204.1520706108217; Sat, 10 Mar 2018 10:21:48 -0800 (PST) Received: from brienza-desktop.8.8.4.4 (andxu.ucsd.edu. [132.239.17.134]) by smtp.gmail.com with ESMTPSA id h80sm9210167pfj.181.2018.03.10.10.21.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 10 Mar 2018 10:21:47 -0800 (PST) From: Andiry Xu To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvdimm@lists.01.org Subject: [RFC v2 76/83] Ioctl support. Date: Sat, 10 Mar 2018 10:18:57 -0800 Message-Id: <1520705944-6723-77-git-send-email-jix024@eng.ucsd.edu> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520705944-6723-1-git-send-email-jix024@eng.ucsd.edu> References: <1520705944-6723-1-git-send-email-jix024@eng.ucsd.edu> X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: coughlan@redhat.com, miklos@szeredi.hu, Andiry Xu , david@fromorbit.com, jack@suse.com, swanson@cs.ucsd.edu, swhiteho@redhat.com, andiry.xu@gmail.com MIME-Version: 1.0 Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Virus-Scanned: ClamAV using ClamSMTP From: Andiry Xu NOVA appends link change entry to the inode log to implement SETFLAGS and SETVERSION. Signed-off-by: Andiry Xu --- fs/nova/Makefile | 4 +- fs/nova/dir.c | 4 ++ fs/nova/file.c | 4 ++ fs/nova/inode.h | 2 + fs/nova/ioctl.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/nova/nova.h | 7 +++ 6 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 fs/nova/ioctl.c diff --git a/fs/nova/Makefile b/fs/nova/Makefile index 7bf6403..87e56c6 100644 --- a/fs/nova/Makefile +++ b/fs/nova/Makefile @@ -4,5 +4,5 @@ obj-$(CONFIG_NOVA_FS) += nova.o -nova-y := balloc.o bbuild.o dax.o dir.o file.o inode.o journal.o log.o namei.o\ - rebuild.o stats.o super.o symlink.o +nova-y := balloc.o bbuild.o dax.o dir.o file.o inode.o ioctl.o journal.o\ + log.o namei.o rebuild.o stats.o super.o symlink.o diff --git a/fs/nova/dir.c b/fs/nova/dir.c index 47ee9ad..3694d9d 100644 --- a/fs/nova/dir.c +++ b/fs/nova/dir.c @@ -513,4 +513,8 @@ const struct file_operations nova_dir_operations = { .read = generic_read_dir, .iterate = nova_readdir, .fsync = noop_fsync, + .unlocked_ioctl = nova_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = nova_compat_ioctl, +#endif }; diff --git a/fs/nova/file.c b/fs/nova/file.c index 7e90415..2b70b9d 100644 --- a/fs/nova/file.c +++ b/fs/nova/file.c @@ -714,7 +714,11 @@ const struct file_operations nova_dax_file_operations = { .open = nova_open, .fsync = nova_fsync, .flush = nova_flush, + .unlocked_ioctl = nova_ioctl, .fallocate = nova_fallocate, +#ifdef CONFIG_COMPAT + .compat_ioctl = nova_compat_ioctl, +#endif }; const struct inode_operations nova_file_inode_operations = { diff --git a/fs/nova/inode.h b/fs/nova/inode.h index 693aa90..086a7cb 100644 --- a/fs/nova/inode.h +++ b/fs/nova/inode.h @@ -264,6 +264,8 @@ int nova_delete_file_tree(struct super_block *sb, struct nova_inode_info_header *sih, unsigned long start_blocknr, unsigned long last_blocknr, bool delete_nvmm, bool delete_dead, u64 epoch_id); +extern void nova_set_inode_flags(struct inode *inode, struct nova_inode *pi, + unsigned int flags); unsigned long nova_find_region(struct inode *inode, loff_t *offset, int hole); extern void nova_evict_inode(struct inode *inode); extern int nova_write_inode(struct inode *inode, struct writeback_control *wbc); diff --git a/fs/nova/ioctl.c b/fs/nova/ioctl.c new file mode 100644 index 0000000..2509371 --- /dev/null +++ b/fs/nova/ioctl.c @@ -0,0 +1,184 @@ +/* + * BRIEF DESCRIPTION + * + * Ioctl operations. + * + * Copyright 2015-2016 Regents of the University of California, + * UCSD Non-Volatile Systems Lab, Andiry Xu + * Copyright 2012-2013 Intel Corporation + * Copyright 2010-2011 Marco Stornelli + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include "nova.h" +#include "inode.h" + +long nova_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct address_space *mapping = filp->f_mapping; + struct inode *inode = mapping->host; + struct nova_inode_info *si = NOVA_I(inode); + struct nova_inode_info_header *sih = &si->header; + struct nova_inode *pi; + struct super_block *sb = inode->i_sb; + struct nova_inode_update update; + unsigned int flags; + int ret; + + pi = nova_get_inode(sb, inode); + if (!pi) + return -EACCES; + + switch (cmd) { + case FS_IOC_GETFLAGS: + flags = (sih->i_flags) & NOVA_FL_USER_VISIBLE; + return put_user(flags, (int __user *)arg); + case FS_IOC_SETFLAGS: { + unsigned int oldflags; + u64 old_linkc = 0; + u64 epoch_id; + + ret = mnt_want_write_file(filp); + if (ret) + return ret; + + if (!inode_owner_or_capable(inode)) { + ret = -EPERM; + goto flags_out; + } + + if (get_user(flags, (int __user *)arg)) { + ret = -EFAULT; + goto flags_out; + } + + inode_lock(inode); + sih_lock(sih); + oldflags = le32_to_cpu(pi->i_flags); + + if ((flags ^ oldflags) & + (FS_APPEND_FL | FS_IMMUTABLE_FL)) { + if (!capable(CAP_LINUX_IMMUTABLE)) { + inode_unlock(inode); + ret = -EPERM; + goto flags_out_unlock; + } + } + + if (!S_ISDIR(inode->i_mode)) + flags &= ~FS_DIRSYNC_FL; + + epoch_id = nova_get_epoch_id(sb); + flags = flags & FS_FL_USER_MODIFIABLE; + flags |= oldflags & ~FS_FL_USER_MODIFIABLE; + inode->i_ctime = current_time(inode); + nova_set_inode_flags(inode, pi, flags); + sih->i_flags = flags; + + update.tail = 0; + ret = nova_append_link_change_entry(sb, pi, inode, + &update, &old_linkc, epoch_id); + if (!ret) { + nova_update_inode(sb, inode, pi, &update); + nova_invalidate_link_change_entry(sb, old_linkc); + } + sih->trans_id++; +flags_out_unlock: + sih_unlock(sih); + inode_unlock(inode); +flags_out: + mnt_drop_write_file(filp); + return ret; + } + case FS_IOC_GETVERSION: + return put_user(inode->i_generation, (int __user *)arg); + case FS_IOC_SETVERSION: { + u64 old_linkc = 0; + u64 epoch_id; + __u32 generation; + + if (!inode_owner_or_capable(inode)) + return -EPERM; + ret = mnt_want_write_file(filp); + if (ret) + return ret; + if (get_user(generation, (int __user *)arg)) { + ret = -EFAULT; + goto setversion_out; + } + + epoch_id = nova_get_epoch_id(sb); + inode_lock(inode); + sih_lock(sih); + inode->i_ctime = current_time(inode); + inode->i_generation = generation; + + update.tail = 0; + ret = nova_append_link_change_entry(sb, pi, inode, + &update, &old_linkc, epoch_id); + if (!ret) { + nova_update_inode(sb, inode, pi, &update); + nova_invalidate_link_change_entry(sb, old_linkc); + } + sih->trans_id++; + sih_unlock(sih); + inode_unlock(inode); +setversion_out: + mnt_drop_write_file(filp); + return ret; + } + case NOVA_PRINT_TIMING: { + nova_print_timing_stats(sb); + return 0; + } + case NOVA_CLEAR_STATS: { + nova_clear_stats(sb); + return 0; + } + case NOVA_PRINT_LOG: { + nova_print_inode_log(sb, inode); + return 0; + } + case NOVA_PRINT_LOG_PAGES: { + nova_print_inode_log_pages(sb, inode); + return 0; + } + case NOVA_PRINT_FREE_LISTS: { + nova_print_free_lists(sb); + return 0; + } + default: + return -ENOTTY; + } +} + +#ifdef CONFIG_COMPAT +long nova_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case FS_IOC32_GETFLAGS: + cmd = FS_IOC_GETFLAGS; + break; + case FS_IOC32_SETFLAGS: + cmd = FS_IOC_SETFLAGS; + break; + case FS_IOC32_GETVERSION: + cmd = FS_IOC_GETVERSION; + break; + case FS_IOC32_SETVERSION: + cmd = FS_IOC_SETVERSION; + break; + default: + return -ENOIOCTLCMD; + } + return nova_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif diff --git a/fs/nova/nova.h b/fs/nova/nova.h index d209cfc..ab9153e 100644 --- a/fs/nova/nova.h +++ b/fs/nova/nova.h @@ -515,6 +515,13 @@ int nova_remove_dentry(struct dentry *dentry, int dec_link, extern const struct file_operations nova_dax_file_operations; extern const struct inode_operations nova_file_inode_operations; +/* ioctl.c */ +extern long nova_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +extern long nova_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); +#endif + /* namei.c */ extern const struct inode_operations nova_dir_inode_operations; extern const struct inode_operations nova_special_inode_operations;