1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * fs/sharefs/main.c 4 * 5 * Copyright (c) 1998-2022 Erez Zadok 6 * Copyright (c) 2009 Shrikar Archak 7 * Copyright (c) 2003-2022 Stony Brook University 8 * Copyright (c) 2003-2022 The Research Foundation of SUNY 9 * Copyright (c) 2023 Huawei Device Co., Ltd. 10 */ 11 12#include <linux/module.h> 13#include "sharefs.h" 14#include "authentication.h" 15 16 17struct sharefs_mount_priv { 18 const char *dev_name; 19 const char *raw_data; 20}; 21 22/* 23 * There is no need to lock the sharefs_super_info's rwsem as there is no 24 * way anyone can have a reference to the superblock at this point in time. 25 */ 26static int sharefs_fill_super(struct super_block *sb, void *data, int silent) 27{ 28 29 struct sharefs_mount_priv *priv = (struct sharefs_mount_priv *)data; 30 const char *dev_name = priv->dev_name; 31 const char *raw_data = priv->raw_data; 32 33 int err = 0; 34 struct super_block *lower_sb; 35 struct path lower_path; 36 struct inode *inode; 37 38 /* parse lower path */ 39 err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, 40 &lower_path); 41 if (err) { 42 printk(KERN_ERR "sharefs: error accessing " 43 "lower directory '%s'\n", dev_name); 44 goto out; 45 } 46 47 /* allocate superblock private data */ 48 sb->s_fs_info = kzalloc(sizeof(struct sharefs_sb_info), GFP_KERNEL); 49 if (!SHAREFS_SB(sb)) { 50 printk(KERN_CRIT "sharefs: fill_super: out of memory\n"); 51 err = -ENOMEM; 52 goto out_pput; 53 } 54 55 /* set the lower superblock field of upper superblock */ 56 lower_sb = lower_path.dentry->d_sb; 57 atomic_inc(&lower_sb->s_active); 58 sharefs_set_lower_super(sb, lower_sb); 59 60 /* inherit maxbytes from lower file system */ 61 sb->s_maxbytes = lower_sb->s_maxbytes; 62 63 /* 64 * Our c/m/atime granularity is 1 ns because we may stack on file 65 * systems whose granularity is as good. 66 */ 67 sb->s_time_gran = 1; 68 69 sb->s_op = &sharefs_sops; 70 71 /* get a new inode and allocate our root dentry */ 72 inode = sharefs_iget(sb, d_inode(lower_path.dentry)); 73 if (IS_ERR(inode)) { 74 err = PTR_ERR(inode); 75 goto out_pput; 76 } 77 sharefs_root_inode_perm_init(inode); 78 sb->s_root = d_make_root(inode); 79 if (!sb->s_root) { 80 err = -ENOMEM; 81 goto out_pput; 82 } 83 d_set_d_op(sb->s_root, &sharefs_dops); 84 85 err = sharefs_parse_options(sb->s_fs_info, raw_data); 86 if (err) 87 goto out_pput; 88 89 /* link the upper and lower dentries */ 90 sb->s_root->d_fsdata = NULL; 91 err = new_dentry_private_data(sb->s_root); 92 if (err) 93 goto out_pput; 94 95 /* if get here: cannot have error */ 96 97 /* set the lower dentries for s_root */ 98 sharefs_set_lower_path(sb->s_root, &lower_path); 99 100 /* 101 * No need to call interpose because we already have a positive 102 * dentry, which was instantiated by d_make_root. Just need to 103 * d_rehash it. 104 */ 105 d_rehash(sb->s_root); 106 if (!silent) 107 printk(KERN_INFO 108 "sharefs: mounted on top of %s type %s\n", 109 dev_name, lower_sb->s_type->name); 110 goto out; /* all is well */ 111 112 /* 113 * path_put is the only resource we need to free if an error occurred 114 * because returning an error from this function will cause 115 * generic_shutdown_super to be called, which will call 116 * sharefs_put_super, and that function will release any other 117 * resources we took. 118 */ 119out_pput: 120 path_put(&lower_path); 121out: 122 return err; 123} 124 125struct dentry *sharefs_mount(struct file_system_type *fs_type, int flags, 126 const char *dev_name, void *raw_data) 127{ 128 struct sharefs_mount_priv priv = { 129 .dev_name = dev_name, 130 .raw_data = raw_data, 131 }; 132 133 /* sharefs needs a valid dev_name to get the lower_sb's metadata */ 134 if (!dev_name || !*dev_name) 135 return ERR_PTR(-EINVAL); 136 137 return mount_nodev(fs_type, flags, &priv, 138 sharefs_fill_super); 139} 140 141static struct file_system_type sharefs_fs_type = { 142 .owner = THIS_MODULE, 143 .name = SHAREFS_NAME, 144 .mount = sharefs_mount, 145 .kill_sb = generic_shutdown_super, 146 .fs_flags = 0, 147}; 148 149static int __init init_sharefs_fs(void) 150{ 151 int err; 152 153 pr_info("Registering sharefs"); 154 155 err = sharefs_init_inode_cache(); 156 if (err) 157 goto out_err; 158 err = sharefs_init_dentry_cache(); 159 if (err) 160 goto out_err; 161 err = register_filesystem(&sharefs_fs_type); 162 if (err) { 163 sharefs_err("share register failed!"); 164 goto out_err; 165 } 166 167 err = sharefs_init_configfs(); 168 if (err) 169 goto out_err; 170 return 0; 171out_err: 172 sharefs_exit_configfs(); 173 sharefs_destroy_inode_cache(); 174 sharefs_destroy_dentry_cache(); 175 sharefs_err("sharefs init failed!"); 176 return err; 177} 178 179static void __exit exit_sharefs_fs(void) 180{ 181 sharefs_destroy_inode_cache(); 182 sharefs_destroy_dentry_cache(); 183 unregister_filesystem(&sharefs_fs_type); 184 sharefs_exit_configfs(); 185 pr_info("Completed sharefs module unload\n"); 186} 187 188module_init(init_sharefs_fs); 189module_exit(exit_sharefs_fs); 190 191MODULE_LICENSE("GPL V2"); 192MODULE_AUTHOR("Jingjing Mao"); 193MODULE_DESCRIPTION("Share File System"); 194MODULE_ALIAS_FS("sharefs"); 195