1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 1998-2022 Erez Zadok 4 * Copyright (c) 2009 Shrikar Archak 5 * Copyright (c) 2003-2022 Stony Brook University 6 * Copyright (c) 2003-2022 The Research Foundation of SUNY 7 */ 8#include <linux/backing-dev-defs.h> 9#include <linux/ratelimit.h> 10#include <linux/slab.h> 11#include <linux/parser.h> 12#include "sharefs.h" 13 14enum { 15 OPT_USER_ID, 16 OPT_OVERRIDE, 17 OPT_OVERRIDE_SUPPORT_DELETE, 18 OPT_ERR, 19}; 20 21static match_table_t sharefs_tokens = { 22 { OPT_USER_ID, "user_id=%s" }, 23 { OPT_OVERRIDE, "override" }, 24 { OPT_OVERRIDE_SUPPORT_DELETE, "override_support_delete" }, 25 { OPT_ERR, NULL } 26}; 27 28int sharefs_parse_options(struct sharefs_sb_info *sbi, const char *data) 29{ 30 char *p = NULL; 31 char *name = NULL; 32 char *options = NULL; 33 char *options_src = NULL; 34 substring_t args[MAX_OPT_ARGS]; 35 unsigned int user_id = 0; 36 int err = 0; 37 38 options = kstrdup(data, GFP_KERNEL); 39 if (data && !options) { 40 err = -ENOMEM; 41 goto out; 42 } 43 options_src = options; 44 45 while ((p = strsep(&options_src, ",")) != NULL) { 46 int token; 47 48 if (!*p) 49 continue; 50 args[0].to = args[0].from = NULL; 51 token = match_token(p, sharefs_tokens, args); 52 53 switch (token) { 54 case OPT_USER_ID: 55 name = match_strdup(&args[0]); 56 if (name) { 57 err = kstrtouint(name, 10, &user_id); 58 kfree(name); 59 name = NULL; 60 if (err) 61 goto out; 62 sbi->user_id = user_id; 63 } 64 break; 65 case OPT_OVERRIDE: 66 sbi->override = true; 67 break; 68 case OPT_OVERRIDE_SUPPORT_DELETE: 69 sbi->override_support_delete = true; 70 break; 71 default: 72 err = -EINVAL; 73 goto out; 74 } 75 } 76out: 77 kfree(options); 78 79 return err; 80} 81 82/* 83 * The inode cache is used with alloc_inode for both our inode info and the 84 * vfs inode. 85 */ 86static struct kmem_cache *sharefs_inode_cachep; 87 88/* final actions when unmounting a file system */ 89static void sharefs_put_super(struct super_block *sb) 90{ 91 struct sharefs_sb_info *spd; 92 struct super_block *s; 93 94 spd = SHAREFS_SB(sb); 95 if (!spd) 96 return; 97 98 /* decrement lower super references */ 99 s = sharefs_lower_super(sb); 100 sharefs_set_lower_super(sb, NULL); 101 atomic_dec(&s->s_active); 102 103 kfree(spd); 104 sb->s_fs_info = NULL; 105} 106 107static int sharefs_statfs(struct dentry *dentry, struct kstatfs *buf) 108{ 109 int err; 110 struct path lower_path; 111 112 sharefs_get_lower_path(dentry, &lower_path); 113 err = vfs_statfs(&lower_path, buf); 114 sharefs_put_lower_path(dentry, &lower_path); 115 116 /* set return buf to our f/s to avoid confusing user-level utils */ 117 buf->f_type = SHAREFS_SUPER_MAGIC; 118 119 return err; 120} 121 122/* 123 * Called by iput() when the inode reference count reached zero 124 * and the inode is not hashed anywhere. Used to clear anything 125 * that needs to be, before the inode is completely destroyed and put 126 * on the inode free list. 127 */ 128static void sharefs_evict_inode(struct inode *inode) 129{ 130 struct inode *lower_inode; 131 132 truncate_inode_pages(&inode->i_data, 0); 133 clear_inode(inode); 134 /* 135 * Decrement a reference to a lower_inode, which was incremented 136 * by our read_inode when it was created initially. 137 */ 138 lower_inode = sharefs_lower_inode(inode); 139 sharefs_set_lower_inode(inode, NULL); 140 iput(lower_inode); 141} 142 143void __sharefs_log(const char *level, const bool ratelimited, 144 const char *function, const char *fmt, ...) 145{ 146 struct va_format vaf; 147 va_list args; 148 149 va_start(args, fmt); 150 vaf.fmt = fmt; 151 vaf.va = &args; 152 if (ratelimited) 153 printk_ratelimited("%s sharefs: %s() %pV\n", level, 154 function, &vaf); 155 else 156 printk("%s sharefs: %s() %pV\n", level, function, &vaf); 157 va_end(args); 158} 159 160static struct inode *sharefs_alloc_inode(struct super_block *sb) 161{ 162 struct sharefs_inode_info *i; 163 164 i = kmem_cache_alloc(sharefs_inode_cachep, GFP_KERNEL); 165 if (!i) 166 return NULL; 167 168 /* memset everything up to the inode to 0 */ 169 memset(i, 0, offsetof(struct sharefs_inode_info, vfs_inode)); 170 171 atomic64_set(&i->vfs_inode.i_version, 1); 172 return &i->vfs_inode; 173} 174 175static void sharefs_destroy_inode(struct inode *inode) 176{ 177 kmem_cache_free(sharefs_inode_cachep, SHAREFS_I(inode)); 178} 179 180/* sharefs inode cache constructor */ 181static void init_once(void *obj) 182{ 183 struct sharefs_inode_info *i = obj; 184 185 inode_init_once(&i->vfs_inode); 186} 187 188int sharefs_init_inode_cache(void) 189{ 190 int err = 0; 191 192 sharefs_inode_cachep = 193 kmem_cache_create("sharefs_inode_cache", 194 sizeof(struct sharefs_inode_info), 0, 195 SLAB_RECLAIM_ACCOUNT, init_once); 196 if (!sharefs_inode_cachep) 197 err = -ENOMEM; 198 return err; 199} 200 201/* sharefs inode cache destructor */ 202void sharefs_destroy_inode_cache(void) 203{ 204 if (sharefs_inode_cachep) 205 kmem_cache_destroy(sharefs_inode_cachep); 206} 207 208const struct super_operations sharefs_sops = { 209 .put_super = sharefs_put_super, 210 .statfs = sharefs_statfs, 211 .evict_inode = sharefs_evict_inode, 212 .alloc_inode = sharefs_alloc_inode, 213 .destroy_inode = sharefs_destroy_inode, 214}; 215