From nobody Wed Feb 11 16:18:58 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D554C7EE26 for ; Mon, 8 May 2023 12:40:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234822AbjEHMkk (ORCPT ); Mon, 8 May 2023 08:40:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234784AbjEHMkb (ORCPT ); Mon, 8 May 2023 08:40:31 -0400 Received: from relayaws-01.paragon-software.com (relayaws-01.paragon-software.com [35.157.23.187]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ACB3237617; Mon, 8 May 2023 05:40:08 -0700 (PDT) Received: from relayfre-01.paragon-software.com (unknown [172.30.72.12]) by relayaws-01.paragon-software.com (Postfix) with ESMTPS id B0B3F21C4; Mon, 8 May 2023 12:35:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paragon-software.com; s=mail; t=1683549319; bh=RFF6P7EkHf1hkymDTWXlt6hRdRdlKehS3PqSyelc73s=; h=Date:Subject:From:To:CC:References:In-Reply-To; b=fUcsF5piYtEjDGuyLyMFDW/QqOGqHhyeGHsh/0+9PX5wKbUqoxcTrNs4k5Ji/KYoP iCdSbVJWgklXm7MY7EhQoCLd0Xsowoa3zuJf9688DK0n8nQasEa6C3AtNt7+zTadAn J/J21amew2bNGjOwBlYHCx8YMloXkZ3ek9s7BpzE= Received: from dlg2.mail.paragon-software.com (vdlg-exch-02.paragon-software.com [172.30.1.105]) by relayfre-01.paragon-software.com (Postfix) with ESMTPS id 5C46F2191; Mon, 8 May 2023 12:40:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paragon-software.com; s=mail; t=1683549606; bh=RFF6P7EkHf1hkymDTWXlt6hRdRdlKehS3PqSyelc73s=; h=Date:Subject:From:To:CC:References:In-Reply-To; b=uZVKbqli9+/XIjR++PSHIkbD1cAzkkdEVeAvvsj604rYOK9vnNGqCbgVQ+yTuwiEh bsOeSb7M83X+Yu6i8BvLGDuNeIf2cW3jr8wtyEi/jc2ZK73BIgHXfSWVqaDKn9H1Ui H6okkeg7NHGXAVuPRd5QlxxD/+sIzGXZNjkNpDyg= Received: from [192.168.211.146] (192.168.211.146) by vdlg-exch-02.paragon-software.com (172.30.1.105) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.7; Mon, 8 May 2023 15:40:05 +0300 Message-ID: <6de6e6ca-f5fb-42b1-9447-591f5c81a356@paragon-software.com> Date: Mon, 8 May 2023 16:40:05 +0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.10.1 Subject: [PATCH 10/10] fs/ntfs3: Add support /proc/fs/ntfs3//volinfo and /proc/fs/ntfs3//label Content-Language: en-US From: Konstantin Komarov To: CC: Linux Kernel Mailing List , References: In-Reply-To: Content-Type: text/plain; charset="utf-8"; format="flowed" Content-Transfer-Encoding: quoted-printable X-Originating-IP: [192.168.211.146] X-ClientProxiedBy: vobn-exch-01.paragon-software.com (172.30.72.13) To vdlg-exch-02.paragon-software.com (172.30.1.105) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Metafile /proc/fs/ntfs3//label allows to read/write current ntfs label. Signed-off-by: Konstantin Komarov --- =C2=A0fs/ntfs3/fsntfs.c=C2=A0 |=C2=A0 58 ++++++++++++++++++++ =C2=A0fs/ntfs3/ntfs_fs.h |=C2=A0=C2=A0 5 +- =C2=A0fs/ntfs3/super.c=C2=A0=C2=A0 | 134 +++++++++++++++++++++++++++++++++= ++++++++++++ =C2=A03 files changed, 195 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 1c05c088d1c6..33afee0f5559 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -9,6 +9,7 @@ =C2=A0#include =C2=A0#include =C2=A0#include +#include =C2=A0#include "debug.h" =C2=A0#include "ntfs.h" @@ -2619,3 +2620,60 @@ bool valid_windows_name(struct ntfs_sb_info *sbi,=20 const struct le_str *fname) =C2=A0=C2=A0=C2=A0 =C2=A0return !name_has_forbidden_chars(fname) && =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 !is_reserved= _name(sbi, fname); =C2=A0} + +/* + * ntfs_set_label - updates current ntfs label. + */ +int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len) +{ +=C2=A0=C2=A0 =C2=A0int err; +=C2=A0=C2=A0 =C2=A0struct ATTRIB *attr; +=C2=A0=C2=A0 =C2=A0struct ntfs_inode *ni =3D sbi->volume.ni; +=C2=A0=C2=A0 =C2=A0const u8 max_ulen =3D 0x80; /* TODO: use attrdef to get= maximum length */ +=C2=A0=C2=A0 =C2=A0/* Allocate PATH_MAX bytes. */ +=C2=A0=C2=A0 =C2=A0struct cpu_str *uni =3D __getname(); + +=C2=A0=C2=A0 =C2=A0if (!uni) +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0return -ENOMEM; + +=C2=A0=C2=A0 =C2=A0err =3D ntfs_nls_to_utf16(sbi, label, len, uni, (PATH_M= AX - 2) / 2, +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2= =A0UTF16_LITTLE_ENDIAN); +=C2=A0=C2=A0 =C2=A0if (err < 0) +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0goto out; + +=C2=A0=C2=A0 =C2=A0if (uni->len > max_ulen) { +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0ntfs_warn(sbi->sb, "new label is too= long"); +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0err =3D -EFBIG; +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0goto out; +=C2=A0=C2=A0 =C2=A0} + +=C2=A0=C2=A0 =C2=A0ni_lock(ni); + +=C2=A0=C2=A0 =C2=A0/* Ignore any errors. */ +=C2=A0=C2=A0 =C2=A0ni_remove_attr(ni, ATTR_LABEL, NULL, 0, false, NULL); + +=C2=A0=C2=A0 =C2=A0err =3D ni_insert_resident(ni, uni->len * sizeof(u16), = ATTR_LABEL, NULL, +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2= =A0 0, &attr, NULL, NULL); +=C2=A0=C2=A0 =C2=A0if (err < 0) +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0goto unlock_out; + +=C2=A0=C2=A0 =C2=A0/* write new label in on-disk struct. */ +=C2=A0=C2=A0 =C2=A0memcpy(resident_data(attr), uni->name, uni->len * sizeo= f(u16)); + +=C2=A0=C2=A0 =C2=A0/* update cached value of current label. */ +=C2=A0=C2=A0 =C2=A0if (len >=3D ARRAY_SIZE(sbi->volume.label)) +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0len =3D ARRAY_SIZE(sbi->volume.label= ) - 1; +=C2=A0=C2=A0 =C2=A0memcpy(sbi->volume.label, label, len); +=C2=A0=C2=A0 =C2=A0sbi->volume.label[len] =3D 0; +=C2=A0=C2=A0 =C2=A0mark_inode_dirty_sync(&ni->vfs_inode); + +unlock_out: +=C2=A0=C2=A0 =C2=A0ni_unlock(ni); + +=C2=A0=C2=A0 =C2=A0if (!err) +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0err =3D _ni_write_inode(&ni->vfs_ino= de, 0); + +out: +=C2=A0=C2=A0 =C2=A0__putname(uni); +=C2=A0=C2=A0 =C2=A0return err; +} \ No newline at end of file diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 00fa782fcada..629403ede6e5 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -276,7 +276,7 @@ struct ntfs_sb_info { =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0__le16 flags; // Cached curren= t VOLUME_INFO::flags,=20 VOLUME_FLAG_DIRTY. =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0u8 major_ver; =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0u8 minor_ver; -=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0char label[65]; +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0char label[256]; =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0bool real_dirty; // Real fs st= ate. =C2=A0=C2=A0=C2=A0 =C2=A0} volume; @@ -286,7 +286,6 @@ struct ntfs_sb_info { =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0struct ntfs_inode *ni; =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0u32 next_id; =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0u64 next_off; - =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0__le32 def_security_id; =C2=A0=C2=A0=C2=A0 =C2=A0} security; @@ -314,6 +313,7 @@ struct ntfs_sb_info { =C2=A0=C2=A0=C2=A0 =C2=A0struct ntfs_mount_options *options; =C2=A0=C2=A0=C2=A0 =C2=A0struct ratelimit_state msg_ratelimit; +=C2=A0=C2=A0 =C2=A0struct proc_dir_entry *procdir; =C2=A0}; =C2=A0/* One MFT record(usually 1024 bytes), consists of attributes. */ @@ -651,6 +651,7 @@ void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST=20 lcn, CLST len, bool trim); =C2=A0int run_deallocate(struct ntfs_sb_info *sbi, const struct runs_tree = *run, =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 bool trim); =C2=A0bool valid_windows_name(struct ntfs_sb_info *sbi, const struct le_st= r=20 *name); +int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len); =C2=A0/* Globals from index.c */ =C2=A0int indx_used_bit(struct ntfs_index *indx, struct ntfs_inode *ni,=20 size_t *bit); diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 7ab0a79c7d84..e36769eac7de 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -57,6 +57,7 @@ =C2=A0#include =C2=A0#include =C2=A0#include +#include =C2=A0#include =C2=A0#include @@ -441,6 +442,103 @@ static int ntfs_fs_reconfigure(struct fs_context *fc) =C2=A0=C2=A0=C2=A0 =C2=A0return 0; =C2=A0} +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *proc_info_root; + +/* + * ntfs3_volinfo: + * + * The content of /proc/fs/ntfs3//volinfo + * + * ntfs3.1 + * cluster size + * number of clusters +*/ +static int ntfs3_volinfo(struct seq_file *m, void *o) +{ +=C2=A0=C2=A0 =C2=A0struct super_block *sb =3D m->private; +=C2=A0=C2=A0 =C2=A0struct ntfs_sb_info *sbi =3D sb->s_fs_info; + +=C2=A0=C2=A0 =C2=A0seq_printf(m, "ntfs%d.%d\n%u\n%zu\n", sbi->volume.major= _ver, +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 sbi->volume.minor_ver, = sbi->cluster_size, +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 sbi->used.bitmap.nbits); + +=C2=A0=C2=A0 =C2=A0return 0; +} + +static int ntfs3_volinfo_open(struct inode *inode, struct file *file) +{ +=C2=A0=C2=A0 =C2=A0return single_open(file, ntfs3_volinfo, pde_data(inode)= ); +} + +/* read /proc/fs/ntfs3//label */ +static int ntfs3_label_show(struct seq_file *m, void *o) +{ +=C2=A0=C2=A0 =C2=A0struct super_block *sb =3D m->private; +=C2=A0=C2=A0 =C2=A0struct ntfs_sb_info *sbi =3D sb->s_fs_info; + +=C2=A0=C2=A0 =C2=A0seq_printf(m, "%s\n", sbi->volume.label); + +=C2=A0=C2=A0 =C2=A0return 0; +} + +/* write /proc/fs/ntfs3//label */ +static ssize_t ntfs3_label_write(struct file *file, const char __user=20 *buffer, +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2= =A0 size_t count, loff_t *ppos) +{ +=C2=A0=C2=A0 =C2=A0int err; +=C2=A0=C2=A0 =C2=A0struct super_block *sb =3D pde_data(file_inode(file)); +=C2=A0=C2=A0 =C2=A0struct ntfs_sb_info *sbi =3D sb->s_fs_info; +=C2=A0=C2=A0 =C2=A0ssize_t ret =3D count; +=C2=A0=C2=A0 =C2=A0u8 *label =3D kmalloc(count, GFP_NOFS); + +=C2=A0=C2=A0 =C2=A0if (!label) +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0return -ENOMEM; + +=C2=A0=C2=A0 =C2=A0if (copy_from_user(label, buffer, ret)) { +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0ret =3D -EFAULT; +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0goto out; +=C2=A0=C2=A0 =C2=A0} +=C2=A0=C2=A0 =C2=A0while (ret > 0 && label[ret - 1] =3D=3D '\n') +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0ret -=3D 1; + +=C2=A0=C2=A0 =C2=A0err =3D ntfs_set_label(sbi, label, ret); + +=C2=A0=C2=A0 =C2=A0if (err < 0) { +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0ntfs_err(sb, "failed (%d) to write l= abel", err); +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0ret =3D err; +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0goto out; +=C2=A0=C2=A0 =C2=A0} + +=C2=A0=C2=A0 =C2=A0*ppos +=3D count; +=C2=A0=C2=A0 =C2=A0ret =3D count; +out: +=C2=A0=C2=A0 =C2=A0kfree(label); +=C2=A0=C2=A0 =C2=A0return ret; +} + +static int ntfs3_label_open(struct inode *inode, struct file *file) +{ +=C2=A0=C2=A0 =C2=A0return single_open(file, ntfs3_label_show, pde_data(ino= de)); +} + +static const struct proc_ops ntfs3_volinfo_fops =3D { +=C2=A0=C2=A0 =C2=A0.proc_read =3D seq_read, +=C2=A0=C2=A0 =C2=A0.proc_lseek =3D seq_lseek, +=C2=A0=C2=A0 =C2=A0.proc_release =3D single_release, +=C2=A0=C2=A0 =C2=A0.proc_open =3D ntfs3_volinfo_open, +}; + +static const struct proc_ops ntfs3_label_fops =3D { +=C2=A0=C2=A0 =C2=A0.proc_read =3D seq_read, +=C2=A0=C2=A0 =C2=A0.proc_lseek =3D seq_lseek, +=C2=A0=C2=A0 =C2=A0.proc_release =3D single_release, +=C2=A0=C2=A0 =C2=A0.proc_open =3D ntfs3_label_open, +=C2=A0=C2=A0 =C2=A0.proc_write =3D ntfs3_label_write, +}; + +#endif + =C2=A0static struct kmem_cache *ntfs_inode_cachep; =C2=A0static struct inode *ntfs_alloc_inode(struct super_block *sb) @@ -515,6 +613,16 @@ static void ntfs_put_super(struct super_block *sb) =C2=A0{ =C2=A0=C2=A0=C2=A0 =C2=A0struct ntfs_sb_info *sbi =3D sb->s_fs_info; +#ifdef CONFIG_PROC_FS +=C2=A0=C2=A0 =C2=A0// Remove /proc/fs/ntfs3/.. +=C2=A0=C2=A0 =C2=A0if (sbi->procdir) { +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0remove_proc_entry("label", sbi->proc= dir); +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0remove_proc_entry("volinfo", sbi->pr= ocdir); +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0remove_proc_entry(sb->s_id, proc_inf= o_root); +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0sbi->procdir =3D NULL; +=C2=A0=C2=A0 =C2=A0} +#endif + =C2=A0=C2=A0=C2=A0 =C2=A0/* Mark rw ntfs as clear, if possible. */ =C2=A0=C2=A0=C2=A0 =C2=A0ntfs_set_state(sbi, NTFS_DIRTY_CLEAR); @@ -1436,6 +1544,20 @@ static int ntfs_fill_super(struct super_block=20 *sb, struct fs_context *fc) =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0kfree(boot2); =C2=A0=C2=A0=C2=A0 =C2=A0} +#ifdef CONFIG_PROC_FS +=C2=A0=C2=A0 =C2=A0/* Create /proc/fs/ntfs3/.. */ +=C2=A0=C2=A0 =C2=A0if (proc_info_root) { +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0struct proc_dir_entry *e =3D proc_mk= dir(sb->s_id, proc_info_root); +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0if (e) { +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0proc_create_data(= "volinfo", S_IFREG | S_IRUGO, e, +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2= =A0=C2=A0=C2=A0 =C2=A0 &ntfs3_volinfo_fops, sb); +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0proc_create_data(= "label", S_IFREG | S_IRUGO | S_IWUGO, +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2= =A0=C2=A0=C2=A0 =C2=A0 e, &ntfs3_label_fops, sb); +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0sbi->procdir =3D = e; +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0} +=C2=A0=C2=A0 =C2=A0} +#endif + =C2=A0=C2=A0=C2=A0 =C2=A0return 0; =C2=A0put_inode_out: @@ -1630,6 +1752,12 @@ static int __init init_ntfs_fs(void) =C2=A0=C2=A0=C2=A0 =C2=A0if (IS_ENABLED(CONFIG_NTFS3_LZX_XPRESS)) =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0pr_info("ntfs3: Read-only LZX/= Xpress compression included\n"); + +#ifdef CONFIG_PROC_FS +=C2=A0=C2=A0 =C2=A0/* Create "/proc/fs/ntfs3" */ +=C2=A0=C2=A0 =C2=A0proc_info_root =3D proc_mkdir("fs/ntfs3", NULL); +#endif + =C2=A0=C2=A0=C2=A0 =C2=A0err =3D ntfs3_init_bitmap(); =C2=A0=C2=A0=C2=A0 =C2=A0if (err) =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0return err; @@ -1661,6 +1789,12 @@ static void __exit exit_ntfs_fs(void) =C2=A0=C2=A0=C2=A0 =C2=A0kmem_cache_destroy(ntfs_inode_cachep); =C2=A0=C2=A0=C2=A0 =C2=A0unregister_filesystem(&ntfs_fs_type); =C2=A0=C2=A0=C2=A0 =C2=A0ntfs3_exit_bitmap(); + +#ifdef CONFIG_PROC_FS +=C2=A0=C2=A0 =C2=A0if (proc_info_root) +=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0remove_proc_entry("fs/ntfs3", NULL); +#endif + =C2=A0} =C2=A0MODULE_LICENSE("GPL"); --=20 2.34.1