blob: f27da3bbafac5810359f2a0b0bba200864238199 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Mike Marshall1182fca2015-07-17 10:38:15 -04002/*
3 * (C) 2001 Clemson University and The University of Chicago
4 *
5 * See COPYING in top-level directory.
6 */
7
8#include "protocol.h"
Mike Marshall575e9462015-12-04 12:56:14 -05009#include "orangefs-kernel.h"
10#include "orangefs-bufmap.h"
Mike Marshall1182fca2015-07-17 10:38:15 -040011
12#include <linux/parser.h>
Martin Brandenburgfc2e2e92017-12-12 13:46:30 -050013#include <linux/hashtable.h>
Mike Marshall1182fca2015-07-17 10:38:15 -040014
Yi Liu8bb8aef2015-11-24 15:12:14 -050015/* a cache for orangefs-inode objects (i.e. orangefs inode private data) */
16static struct kmem_cache *orangefs_inode_cache;
Mike Marshall1182fca2015-07-17 10:38:15 -040017
Yi Liu8bb8aef2015-11-24 15:12:14 -050018/* list for storing orangefs specific superblocks in use */
19LIST_HEAD(orangefs_superblocks);
Mike Marshall1182fca2015-07-17 10:38:15 -040020
Yi Liu8bb8aef2015-11-24 15:12:14 -050021DEFINE_SPINLOCK(orangefs_superblocks_lock);
Mike Marshall1182fca2015-07-17 10:38:15 -040022
23enum {
24 Opt_intr,
25 Opt_acl,
26 Opt_local_lock,
27
28 Opt_err
29};
30
31static const match_table_t tokens = {
32 { Opt_acl, "acl" },
33 { Opt_intr, "intr" },
34 { Opt_local_lock, "local_lock" },
35 { Opt_err, NULL }
36};
37
Martin Brandenburg482664d2016-08-12 12:02:31 -040038uint64_t orangefs_features;
Mike Marshall1182fca2015-07-17 10:38:15 -040039
David Howells4dfdb712017-07-05 16:25:45 +010040static int orangefs_show_options(struct seq_file *m, struct dentry *root)
41{
42 struct orangefs_sb_info_s *orangefs_sb = ORANGEFS_SB(root->d_sb);
43
Linus Torvalds1751e8a2017-11-27 13:05:09 -080044 if (root->d_sb->s_flags & SB_POSIXACL)
David Howells4dfdb712017-07-05 16:25:45 +010045 seq_puts(m, ",acl");
46 if (orangefs_sb->flags & ORANGEFS_OPT_INTR)
47 seq_puts(m, ",intr");
48 if (orangefs_sb->flags & ORANGEFS_OPT_LOCAL_LOCK)
49 seq_puts(m, ",local_lock");
50 return 0;
51}
52
Mike Marshall1182fca2015-07-17 10:38:15 -040053static int parse_mount_options(struct super_block *sb, char *options,
54 int silent)
55{
Yi Liu8bb8aef2015-11-24 15:12:14 -050056 struct orangefs_sb_info_s *orangefs_sb = ORANGEFS_SB(sb);
Mike Marshall1182fca2015-07-17 10:38:15 -040057 substring_t args[MAX_OPT_ARGS];
58 char *p;
59
60 /*
61 * Force any potential flags that might be set from the mount
62 * to zero, ie, initialize to unset.
63 */
Linus Torvalds1751e8a2017-11-27 13:05:09 -080064 sb->s_flags &= ~SB_POSIXACL;
Yi Liu8bb8aef2015-11-24 15:12:14 -050065 orangefs_sb->flags &= ~ORANGEFS_OPT_INTR;
66 orangefs_sb->flags &= ~ORANGEFS_OPT_LOCAL_LOCK;
Mike Marshall1182fca2015-07-17 10:38:15 -040067
68 while ((p = strsep(&options, ",")) != NULL) {
69 int token;
70
71 if (!*p)
72 continue;
73
74 token = match_token(p, tokens, args);
75 switch (token) {
76 case Opt_acl:
Linus Torvalds1751e8a2017-11-27 13:05:09 -080077 sb->s_flags |= SB_POSIXACL;
Mike Marshall1182fca2015-07-17 10:38:15 -040078 break;
79 case Opt_intr:
Yi Liu8bb8aef2015-11-24 15:12:14 -050080 orangefs_sb->flags |= ORANGEFS_OPT_INTR;
Mike Marshall1182fca2015-07-17 10:38:15 -040081 break;
82 case Opt_local_lock:
Yi Liu8bb8aef2015-11-24 15:12:14 -050083 orangefs_sb->flags |= ORANGEFS_OPT_LOCAL_LOCK;
Mike Marshall1182fca2015-07-17 10:38:15 -040084 break;
85 default:
86 goto fail;
87 }
88 }
89
90 return 0;
91fail:
92 if (!silent)
93 gossip_err("Error: mount option [%s] is not supported.\n", p);
94 return -EINVAL;
95}
96
Yi Liu8bb8aef2015-11-24 15:12:14 -050097static void orangefs_inode_cache_ctor(void *req)
Mike Marshall1182fca2015-07-17 10:38:15 -040098{
Yi Liu8bb8aef2015-11-24 15:12:14 -050099 struct orangefs_inode_s *orangefs_inode = req;
Mike Marshall1182fca2015-07-17 10:38:15 -0400100
Yi Liu8bb8aef2015-11-24 15:12:14 -0500101 inode_init_once(&orangefs_inode->vfs_inode);
102 init_rwsem(&orangefs_inode->xattr_sem);
Mike Marshall1182fca2015-07-17 10:38:15 -0400103}
104
Yi Liu8bb8aef2015-11-24 15:12:14 -0500105static struct inode *orangefs_alloc_inode(struct super_block *sb)
Mike Marshall1182fca2015-07-17 10:38:15 -0400106{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500107 struct orangefs_inode_s *orangefs_inode;
Mike Marshall1182fca2015-07-17 10:38:15 -0400108
Mike Marshall2d4cae02016-02-04 13:48:16 -0500109 orangefs_inode = kmem_cache_alloc(orangefs_inode_cache, GFP_KERNEL);
Markus Elfring07a25852017-08-17 21:00:07 +0200110 if (!orangefs_inode)
Mike Marshall1182fca2015-07-17 10:38:15 -0400111 return NULL;
Mike Marshall1182fca2015-07-17 10:38:15 -0400112
113 /*
114 * We want to clear everything except for rw_semaphore and the
115 * vfs_inode.
116 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500117 memset(&orangefs_inode->refn.khandle, 0, 16);
118 orangefs_inode->refn.fs_id = ORANGEFS_FS_ID_NULL;
119 orangefs_inode->last_failed_block_index_read = 0;
120 memset(orangefs_inode->link_target, 0, sizeof(orangefs_inode->link_target));
Mike Marshall1182fca2015-07-17 10:38:15 -0400121
122 gossip_debug(GOSSIP_SUPER_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500123 "orangefs_alloc_inode: allocated %p\n",
124 &orangefs_inode->vfs_inode);
125 return &orangefs_inode->vfs_inode;
Mike Marshall1182fca2015-07-17 10:38:15 -0400126}
127
Peter Zijlstra0695d7d2017-02-24 16:43:36 +0100128static void orangefs_i_callback(struct rcu_head *head)
129{
130 struct inode *inode = container_of(head, struct inode, i_rcu);
131 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
Martin Brandenburgfc2e2e92017-12-12 13:46:30 -0500132 struct orangefs_cached_xattr *cx;
133 struct hlist_node *tmp;
134 int i;
135
136 hash_for_each_safe(orangefs_inode->xattr_cache, i, tmp, cx, node) {
137 hlist_del(&cx->node);
138 kfree(cx);
139 }
140
Peter Zijlstra0695d7d2017-02-24 16:43:36 +0100141 kmem_cache_free(orangefs_inode_cache, orangefs_inode);
142}
143
Yi Liu8bb8aef2015-11-24 15:12:14 -0500144static void orangefs_destroy_inode(struct inode *inode)
Mike Marshall1182fca2015-07-17 10:38:15 -0400145{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500146 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
Mike Marshall1182fca2015-07-17 10:38:15 -0400147
148 gossip_debug(GOSSIP_SUPER_DEBUG,
149 "%s: deallocated %p destroying inode %pU\n",
Yi Liu8bb8aef2015-11-24 15:12:14 -0500150 __func__, orangefs_inode, get_khandle_from_ino(inode));
Mike Marshall1182fca2015-07-17 10:38:15 -0400151
Peter Zijlstra0695d7d2017-02-24 16:43:36 +0100152 call_rcu(&inode->i_rcu, orangefs_i_callback);
Mike Marshall1182fca2015-07-17 10:38:15 -0400153}
154
Martin Brandenburgdf2d7332018-02-12 20:29:37 +0000155static int orangefs_write_inode(struct inode *inode,
156 struct writeback_control *wbc)
157{
158 struct iattr iattr;
159 gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_write_inode\n");
160 iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_ATIME |
161 ATTR_ATIME_SET | ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME;
162 iattr.ia_mode = inode->i_mode;
163 iattr.ia_uid = inode->i_uid;
164 iattr.ia_gid = inode->i_gid;
165 iattr.ia_atime = inode->i_atime;
166 iattr.ia_mtime = inode->i_mtime;
167 iattr.ia_ctime = inode->i_ctime;
168 return orangefs_inode_setattr(inode, &iattr);
169}
170
Mike Marshall1182fca2015-07-17 10:38:15 -0400171/*
172 * NOTE: information filled in here is typically reflected in the
173 * output of the system command 'df'
174*/
Yi Liu8bb8aef2015-11-24 15:12:14 -0500175static int orangefs_statfs(struct dentry *dentry, struct kstatfs *buf)
Mike Marshall1182fca2015-07-17 10:38:15 -0400176{
177 int ret = -ENOMEM;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500178 struct orangefs_kernel_op_s *new_op = NULL;
Mike Marshall1182fca2015-07-17 10:38:15 -0400179 int flags = 0;
180 struct super_block *sb = NULL;
181
182 sb = dentry->d_sb;
183
184 gossip_debug(GOSSIP_SUPER_DEBUG,
Mike Marshall95f5f882018-05-11 17:11:48 -0400185 "%s: called on sb %p (fs_id is %d)\n",
186 __func__,
187 sb,
188 (int)(ORANGEFS_SB(sb)->fs_id));
Mike Marshall1182fca2015-07-17 10:38:15 -0400189
Yi Liu8bb8aef2015-11-24 15:12:14 -0500190 new_op = op_alloc(ORANGEFS_VFS_OP_STATFS);
Mike Marshall1182fca2015-07-17 10:38:15 -0400191 if (!new_op)
192 return ret;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500193 new_op->upcall.req.statfs.fs_id = ORANGEFS_SB(sb)->fs_id;
Mike Marshall1182fca2015-07-17 10:38:15 -0400194
Yi Liu8bb8aef2015-11-24 15:12:14 -0500195 if (ORANGEFS_SB(sb)->flags & ORANGEFS_OPT_INTR)
196 flags = ORANGEFS_OP_INTERRUPTIBLE;
Mike Marshall1182fca2015-07-17 10:38:15 -0400197
Yi Liu8bb8aef2015-11-24 15:12:14 -0500198 ret = service_operation(new_op, "orangefs_statfs", flags);
Mike Marshall1182fca2015-07-17 10:38:15 -0400199
200 if (new_op->downcall.status < 0)
201 goto out_op_release;
202
203 gossip_debug(GOSSIP_SUPER_DEBUG,
Mike Marshallbe573662016-01-13 11:38:14 -0500204 "%s: got %ld blocks available | "
205 "%ld blocks total | %ld block size | "
206 "%ld files total | %ld files avail\n",
207 __func__,
Mike Marshall1182fca2015-07-17 10:38:15 -0400208 (long)new_op->downcall.resp.statfs.blocks_avail,
209 (long)new_op->downcall.resp.statfs.blocks_total,
Mike Marshallbe573662016-01-13 11:38:14 -0500210 (long)new_op->downcall.resp.statfs.block_size,
211 (long)new_op->downcall.resp.statfs.files_total,
212 (long)new_op->downcall.resp.statfs.files_avail);
Mike Marshall1182fca2015-07-17 10:38:15 -0400213
214 buf->f_type = sb->s_magic;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500215 memcpy(&buf->f_fsid, &ORANGEFS_SB(sb)->fs_id, sizeof(buf->f_fsid));
Mike Marshall1182fca2015-07-17 10:38:15 -0400216 buf->f_bsize = new_op->downcall.resp.statfs.block_size;
Martin Brandenburg47b49482016-02-20 14:22:40 -0500217 buf->f_namelen = ORANGEFS_NAME_MAX;
Mike Marshall1182fca2015-07-17 10:38:15 -0400218
219 buf->f_blocks = (sector_t) new_op->downcall.resp.statfs.blocks_total;
220 buf->f_bfree = (sector_t) new_op->downcall.resp.statfs.blocks_avail;
221 buf->f_bavail = (sector_t) new_op->downcall.resp.statfs.blocks_avail;
222 buf->f_files = (sector_t) new_op->downcall.resp.statfs.files_total;
223 buf->f_ffree = (sector_t) new_op->downcall.resp.statfs.files_avail;
224 buf->f_frsize = sb->s_blocksize;
225
226out_op_release:
227 op_release(new_op);
Mike Marshall95f5f882018-05-11 17:11:48 -0400228 gossip_debug(GOSSIP_SUPER_DEBUG, "%s: returning %d\n", __func__, ret);
Mike Marshall1182fca2015-07-17 10:38:15 -0400229 return ret;
230}
231
232/*
233 * Remount as initiated by VFS layer. We just need to reparse the mount
234 * options, no need to signal pvfs2-client-core about it.
235 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500236static int orangefs_remount_fs(struct super_block *sb, int *flags, char *data)
Mike Marshall1182fca2015-07-17 10:38:15 -0400237{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500238 gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount_fs: called\n");
Mike Marshall1182fca2015-07-17 10:38:15 -0400239 return parse_mount_options(sb, data, 1);
240}
241
242/*
243 * Remount as initiated by pvfs2-client-core on restart. This is used to
244 * repopulate mount information left from previous pvfs2-client-core.
245 *
246 * the idea here is that given a valid superblock, we're
247 * re-initializing the user space client with the initial mount
248 * information specified when the super block was first initialized.
249 * this is very different than the first initialization/creation of a
250 * superblock. we use the special service_priority_operation to make
251 * sure that the mount gets ahead of any other pending operation that
252 * is waiting for servicing. this means that the pvfs2-client won't
253 * fail to start several times for all other pending operations before
254 * the client regains all of the mount information from us.
255 * NOTE: this function assumes that the request_mutex is already acquired!
256 */
Al Viro45996492016-03-25 19:56:34 -0400257int orangefs_remount(struct orangefs_sb_info_s *orangefs_sb)
Mike Marshall1182fca2015-07-17 10:38:15 -0400258{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500259 struct orangefs_kernel_op_s *new_op;
Mike Marshall1182fca2015-07-17 10:38:15 -0400260 int ret = -EINVAL;
261
Yi Liu8bb8aef2015-11-24 15:12:14 -0500262 gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount: called\n");
Mike Marshall1182fca2015-07-17 10:38:15 -0400263
Yi Liu8bb8aef2015-11-24 15:12:14 -0500264 new_op = op_alloc(ORANGEFS_VFS_OP_FS_MOUNT);
Mike Marshall1182fca2015-07-17 10:38:15 -0400265 if (!new_op)
266 return -ENOMEM;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500267 strncpy(new_op->upcall.req.fs_mount.orangefs_config_server,
Al Viro45996492016-03-25 19:56:34 -0400268 orangefs_sb->devname,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500269 ORANGEFS_MAX_SERVER_ADDR_LEN);
Mike Marshall1182fca2015-07-17 10:38:15 -0400270
271 gossip_debug(GOSSIP_SUPER_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500272 "Attempting ORANGEFS Remount via host %s\n",
273 new_op->upcall.req.fs_mount.orangefs_config_server);
Mike Marshall1182fca2015-07-17 10:38:15 -0400274
275 /*
Mike Marshalladcf34a2016-02-24 16:54:27 -0500276 * we assume that the calling function has already acquired the
Mike Marshall1182fca2015-07-17 10:38:15 -0400277 * request_mutex to prevent other operations from bypassing
278 * this one
279 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500280 ret = service_operation(new_op, "orangefs_remount",
Mike Marshalladcf34a2016-02-24 16:54:27 -0500281 ORANGEFS_OP_PRIORITY | ORANGEFS_OP_NO_MUTEX);
Mike Marshall1182fca2015-07-17 10:38:15 -0400282 gossip_debug(GOSSIP_SUPER_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500283 "orangefs_remount: mount got return value of %d\n",
Mike Marshall1182fca2015-07-17 10:38:15 -0400284 ret);
285 if (ret == 0) {
286 /*
287 * store the id assigned to this sb -- it's just a
288 * short-lived mapping that the system interface uses
289 * to map this superblock to a particular mount entry
290 */
Al Viro45996492016-03-25 19:56:34 -0400291 orangefs_sb->id = new_op->downcall.resp.fs_mount.id;
292 orangefs_sb->mount_pending = 0;
Mike Marshall1182fca2015-07-17 10:38:15 -0400293 }
294
295 op_release(new_op);
Martin Brandenburg482664d2016-08-12 12:02:31 -0400296
Mike Marshallf60fbdb2016-10-03 15:07:36 -0400297 if (orangefs_userspace_version >= 20906) {
Martin Brandenburg482664d2016-08-12 12:02:31 -0400298 new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
299 if (!new_op)
300 return -ENOMEM;
301 new_op->upcall.req.features.features = 0;
Martin Brandenburgcefdc262017-04-06 18:11:00 -0400302 ret = service_operation(new_op, "orangefs_features",
303 ORANGEFS_OP_PRIORITY | ORANGEFS_OP_NO_MUTEX);
304 if (!ret)
305 orangefs_features =
306 new_op->downcall.resp.features.features;
307 else
308 orangefs_features = 0;
Martin Brandenburg482664d2016-08-12 12:02:31 -0400309 op_release(new_op);
310 } else {
311 orangefs_features = 0;
312 }
313
Mike Marshall1182fca2015-07-17 10:38:15 -0400314 return ret;
315}
316
317int fsid_key_table_initialize(void)
318{
319 return 0;
320}
321
322void fsid_key_table_finalize(void)
323{
324}
325
Yi Liu8bb8aef2015-11-24 15:12:14 -0500326static const struct super_operations orangefs_s_ops = {
327 .alloc_inode = orangefs_alloc_inode,
328 .destroy_inode = orangefs_destroy_inode,
Martin Brandenburgdf2d7332018-02-12 20:29:37 +0000329 .write_inode = orangefs_write_inode,
Mike Marshall1182fca2015-07-17 10:38:15 -0400330 .drop_inode = generic_delete_inode,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500331 .statfs = orangefs_statfs,
332 .remount_fs = orangefs_remount_fs,
David Howells4dfdb712017-07-05 16:25:45 +0100333 .show_options = orangefs_show_options,
Mike Marshall1182fca2015-07-17 10:38:15 -0400334};
335
Yi Liu8bb8aef2015-11-24 15:12:14 -0500336static struct dentry *orangefs_fh_to_dentry(struct super_block *sb,
Mike Marshall1182fca2015-07-17 10:38:15 -0400337 struct fid *fid,
338 int fh_len,
339 int fh_type)
340{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500341 struct orangefs_object_kref refn;
Mike Marshall1182fca2015-07-17 10:38:15 -0400342
343 if (fh_len < 5 || fh_type > 2)
344 return NULL;
345
Yi Liu8bb8aef2015-11-24 15:12:14 -0500346 ORANGEFS_khandle_from(&(refn.khandle), fid->raw, 16);
Mike Marshall1182fca2015-07-17 10:38:15 -0400347 refn.fs_id = (u32) fid->raw[4];
348 gossip_debug(GOSSIP_SUPER_DEBUG,
349 "fh_to_dentry: handle %pU, fs_id %d\n",
350 &refn.khandle,
351 refn.fs_id);
352
Yi Liu8bb8aef2015-11-24 15:12:14 -0500353 return d_obtain_alias(orangefs_iget(sb, &refn));
Mike Marshall1182fca2015-07-17 10:38:15 -0400354}
355
Yi Liu8bb8aef2015-11-24 15:12:14 -0500356static int orangefs_encode_fh(struct inode *inode,
Mike Marshall1182fca2015-07-17 10:38:15 -0400357 __u32 *fh,
358 int *max_len,
359 struct inode *parent)
360{
361 int len = parent ? 10 : 5;
362 int type = 1;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500363 struct orangefs_object_kref refn;
Mike Marshall1182fca2015-07-17 10:38:15 -0400364
365 if (*max_len < len) {
Martin Brandenburg79d7cd62018-01-26 14:07:12 -0500366 gossip_err("fh buffer is too small for encoding\n");
Mike Marshall1182fca2015-07-17 10:38:15 -0400367 *max_len = len;
368 type = 255;
369 goto out;
370 }
371
Yi Liu8bb8aef2015-11-24 15:12:14 -0500372 refn = ORANGEFS_I(inode)->refn;
373 ORANGEFS_khandle_to(&refn.khandle, fh, 16);
Mike Marshall1182fca2015-07-17 10:38:15 -0400374 fh[4] = refn.fs_id;
375
376 gossip_debug(GOSSIP_SUPER_DEBUG,
377 "Encoding fh: handle %pU, fsid %u\n",
378 &refn.khandle,
379 refn.fs_id);
380
381
382 if (parent) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500383 refn = ORANGEFS_I(parent)->refn;
384 ORANGEFS_khandle_to(&refn.khandle, (char *) fh + 20, 16);
Mike Marshall1182fca2015-07-17 10:38:15 -0400385 fh[9] = refn.fs_id;
386
387 type = 2;
388 gossip_debug(GOSSIP_SUPER_DEBUG,
389 "Encoding parent: handle %pU, fsid %u\n",
390 &refn.khandle,
391 refn.fs_id);
392 }
393 *max_len = len;
394
395out:
396 return type;
397}
398
Julia Lawallacaca362016-01-01 10:01:52 +0100399static const struct export_operations orangefs_export_ops = {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500400 .encode_fh = orangefs_encode_fh,
401 .fh_to_dentry = orangefs_fh_to_dentry,
Mike Marshall1182fca2015-07-17 10:38:15 -0400402};
403
Martin Brandenburg9d286b02017-04-25 15:38:05 -0400404static int orangefs_unmount(int id, __s32 fs_id, const char *devname)
405{
406 struct orangefs_kernel_op_s *op;
407 int r;
408 op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
409 if (!op)
410 return -ENOMEM;
411 op->upcall.req.fs_umount.id = id;
412 op->upcall.req.fs_umount.fs_id = fs_id;
413 strncpy(op->upcall.req.fs_umount.orangefs_config_server,
Xiongfeng Wang6bdfb482018-01-08 20:22:33 +0800414 devname, ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
Martin Brandenburg9d286b02017-04-25 15:38:05 -0400415 r = service_operation(op, "orangefs_fs_umount", 0);
416 /* Not much to do about an error here. */
417 if (r)
418 gossip_err("orangefs_unmount: service_operation %d\n", r);
419 op_release(op);
420 return r;
421}
422
Yi Liu8bb8aef2015-11-24 15:12:14 -0500423static int orangefs_fill_sb(struct super_block *sb,
424 struct orangefs_fs_mount_response *fs_mount,
Al Viro5c0dbbc2015-10-08 20:22:43 -0400425 void *data, int silent)
Mike Marshall1182fca2015-07-17 10:38:15 -0400426{
Martin Brandenburgf2d34c72018-02-12 20:28:42 +0000427 int ret;
428 struct inode *root;
429 struct dentry *root_dentry;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500430 struct orangefs_object_kref root_object;
Mike Marshall1182fca2015-07-17 10:38:15 -0400431
Yi Liu8bb8aef2015-11-24 15:12:14 -0500432 ORANGEFS_SB(sb)->sb = sb;
Mike Marshall1182fca2015-07-17 10:38:15 -0400433
Yi Liu8bb8aef2015-11-24 15:12:14 -0500434 ORANGEFS_SB(sb)->root_khandle = fs_mount->root_khandle;
435 ORANGEFS_SB(sb)->fs_id = fs_mount->fs_id;
436 ORANGEFS_SB(sb)->id = fs_mount->id;
Mike Marshall1182fca2015-07-17 10:38:15 -0400437
Al Viro5c0dbbc2015-10-08 20:22:43 -0400438 if (data) {
439 ret = parse_mount_options(sb, data, silent);
Mike Marshall1182fca2015-07-17 10:38:15 -0400440 if (ret)
441 return ret;
442 }
443
444 /* Hang the xattr handlers off the superblock */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500445 sb->s_xattr = orangefs_xattr_handlers;
446 sb->s_magic = ORANGEFS_SUPER_MAGIC;
447 sb->s_op = &orangefs_s_ops;
448 sb->s_d_op = &orangefs_dentry_operations;
Mike Marshall1182fca2015-07-17 10:38:15 -0400449
Martin Brandenburg9f8fd532018-05-31 16:36:59 +0000450 sb->s_blocksize = PAGE_SIZE;
451 sb->s_blocksize_bits = PAGE_SHIFT;
Mike Marshall1182fca2015-07-17 10:38:15 -0400452 sb->s_maxbytes = MAX_LFS_FILESIZE;
453
Martin Brandenburgf2d34c72018-02-12 20:28:42 +0000454 ret = super_setup_bdi(sb);
455 if (ret)
456 return ret;
457
Yi Liu8bb8aef2015-11-24 15:12:14 -0500458 root_object.khandle = ORANGEFS_SB(sb)->root_khandle;
459 root_object.fs_id = ORANGEFS_SB(sb)->fs_id;
Mike Marshall1182fca2015-07-17 10:38:15 -0400460 gossip_debug(GOSSIP_SUPER_DEBUG,
461 "get inode %pU, fsid %d\n",
462 &root_object.khandle,
463 root_object.fs_id);
464
Yi Liu8bb8aef2015-11-24 15:12:14 -0500465 root = orangefs_iget(sb, &root_object);
Mike Marshall1182fca2015-07-17 10:38:15 -0400466 if (IS_ERR(root))
467 return PTR_ERR(root);
468
469 gossip_debug(GOSSIP_SUPER_DEBUG,
470 "Allocated root inode [%p] with mode %x\n",
471 root,
472 root->i_mode);
473
474 /* allocates and places root dentry in dcache */
475 root_dentry = d_make_root(root);
Al Virob05a7852015-10-08 20:18:00 -0400476 if (!root_dentry)
Mike Marshall1182fca2015-07-17 10:38:15 -0400477 return -ENOMEM;
Mike Marshall1182fca2015-07-17 10:38:15 -0400478
Yi Liu8bb8aef2015-11-24 15:12:14 -0500479 sb->s_export_op = &orangefs_export_ops;
Mike Marshall1182fca2015-07-17 10:38:15 -0400480 sb->s_root = root_dentry;
481 return 0;
482}
483
Yi Liu8bb8aef2015-11-24 15:12:14 -0500484struct dentry *orangefs_mount(struct file_system_type *fst,
Mike Marshall1182fca2015-07-17 10:38:15 -0400485 int flags,
486 const char *devname,
487 void *data)
488{
489 int ret = -EINVAL;
490 struct super_block *sb = ERR_PTR(-EINVAL);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500491 struct orangefs_kernel_op_s *new_op;
Mike Marshall1be21f82015-09-29 15:26:37 -0400492 struct dentry *d = ERR_PTR(-EINVAL);
Mike Marshall1182fca2015-07-17 10:38:15 -0400493
494 gossip_debug(GOSSIP_SUPER_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500495 "orangefs_mount: called with devname %s\n",
Mike Marshall1182fca2015-07-17 10:38:15 -0400496 devname);
497
498 if (!devname) {
499 gossip_err("ERROR: device name not specified.\n");
500 return ERR_PTR(-EINVAL);
501 }
502
Yi Liu8bb8aef2015-11-24 15:12:14 -0500503 new_op = op_alloc(ORANGEFS_VFS_OP_FS_MOUNT);
Mike Marshall1182fca2015-07-17 10:38:15 -0400504 if (!new_op)
505 return ERR_PTR(-ENOMEM);
506
Yi Liu8bb8aef2015-11-24 15:12:14 -0500507 strncpy(new_op->upcall.req.fs_mount.orangefs_config_server,
Mike Marshall1182fca2015-07-17 10:38:15 -0400508 devname,
Xiongfeng Wang6bdfb482018-01-08 20:22:33 +0800509 ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
Mike Marshall1182fca2015-07-17 10:38:15 -0400510
511 gossip_debug(GOSSIP_SUPER_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500512 "Attempting ORANGEFS Mount via host %s\n",
513 new_op->upcall.req.fs_mount.orangefs_config_server);
Mike Marshall1182fca2015-07-17 10:38:15 -0400514
Yi Liu8bb8aef2015-11-24 15:12:14 -0500515 ret = service_operation(new_op, "orangefs_mount", 0);
Mike Marshall1182fca2015-07-17 10:38:15 -0400516 gossip_debug(GOSSIP_SUPER_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500517 "orangefs_mount: mount got return value of %d\n", ret);
Mike Marshall1182fca2015-07-17 10:38:15 -0400518 if (ret)
519 goto free_op;
520
Yi Liu8bb8aef2015-11-24 15:12:14 -0500521 if (new_op->downcall.resp.fs_mount.fs_id == ORANGEFS_FS_ID_NULL) {
Mike Marshall1182fca2015-07-17 10:38:15 -0400522 gossip_err("ERROR: Retrieved null fs_id\n");
523 ret = -EINVAL;
524 goto free_op;
525 }
526
Mike Marshall1be21f82015-09-29 15:26:37 -0400527 sb = sget(fst, NULL, set_anon_super, flags, NULL);
528
529 if (IS_ERR(sb)) {
530 d = ERR_CAST(sb);
Martin Brandenburg9d286b02017-04-25 15:38:05 -0400531 orangefs_unmount(new_op->downcall.resp.fs_mount.id,
532 new_op->downcall.resp.fs_mount.fs_id, devname);
Mike Marshall1182fca2015-07-17 10:38:15 -0400533 goto free_op;
534 }
535
Martin Brandenburgf2d34c72018-02-12 20:28:42 +0000536 /* alloc and init our private orangefs sb info */
537 sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL);
538 if (!ORANGEFS_SB(sb)) {
539 d = ERR_PTR(-ENOMEM);
540 goto free_op;
541 }
542
Yi Liu8bb8aef2015-11-24 15:12:14 -0500543 ret = orangefs_fill_sb(sb,
Al Viro5c0dbbc2015-10-08 20:22:43 -0400544 &new_op->downcall.resp.fs_mount, data,
Linus Torvalds1751e8a2017-11-27 13:05:09 -0800545 flags & SB_SILENT ? 1 : 0);
Mike Marshall1be21f82015-09-29 15:26:37 -0400546
547 if (ret) {
548 d = ERR_PTR(ret);
Martin Brandenburg1ec16882017-04-14 14:22:41 -0400549 goto free_sb_and_op;
Mike Marshall1be21f82015-09-29 15:26:37 -0400550 }
Mike Marshall1182fca2015-07-17 10:38:15 -0400551
552 /*
553 * on successful mount, store the devname and data
554 * used
555 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500556 strncpy(ORANGEFS_SB(sb)->devname,
Mike Marshall1182fca2015-07-17 10:38:15 -0400557 devname,
Xiongfeng Wang6bdfb482018-01-08 20:22:33 +0800558 ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
Mike Marshall1182fca2015-07-17 10:38:15 -0400559
560 /* mount_pending must be cleared */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500561 ORANGEFS_SB(sb)->mount_pending = 0;
Mike Marshall1182fca2015-07-17 10:38:15 -0400562
563 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500564 * finally, add this sb to our list of known orangefs
Mike Marshall1182fca2015-07-17 10:38:15 -0400565 * sb's
566 */
Al Viro45996492016-03-25 19:56:34 -0400567 gossip_debug(GOSSIP_SUPER_DEBUG,
568 "Adding SB %p to orangefs superblocks\n",
569 ORANGEFS_SB(sb));
570 spin_lock(&orangefs_superblocks_lock);
571 list_add_tail(&ORANGEFS_SB(sb)->list, &orangefs_superblocks);
572 spin_unlock(&orangefs_superblocks_lock);
Mike Marshall1182fca2015-07-17 10:38:15 -0400573 op_release(new_op);
Martin Brandenburg482664d2016-08-12 12:02:31 -0400574
Martin Brandenburg1ec16882017-04-14 14:22:41 -0400575 /* Must be removed from the list now. */
576 ORANGEFS_SB(sb)->no_list = 0;
577
Mike Marshallf60fbdb2016-10-03 15:07:36 -0400578 if (orangefs_userspace_version >= 20906) {
Martin Brandenburg482664d2016-08-12 12:02:31 -0400579 new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
580 if (!new_op)
581 return ERR_PTR(-ENOMEM);
582 new_op->upcall.req.features.features = 0;
583 ret = service_operation(new_op, "orangefs_features", 0);
584 orangefs_features = new_op->downcall.resp.features.features;
585 op_release(new_op);
586 } else {
587 orangefs_features = 0;
588 }
589
Mike Marshall1be21f82015-09-29 15:26:37 -0400590 return dget(sb->s_root);
Mike Marshall1182fca2015-07-17 10:38:15 -0400591
Martin Brandenburg1ec16882017-04-14 14:22:41 -0400592free_sb_and_op:
593 /* Will call orangefs_kill_sb with sb not in list. */
594 ORANGEFS_SB(sb)->no_list = 1;
Martin Brandenburg9d286b02017-04-25 15:38:05 -0400595 /* ORANGEFS_VFS_OP_FS_UMOUNT is done by orangefs_kill_sb. */
Martin Brandenburg1ec16882017-04-14 14:22:41 -0400596 deactivate_locked_super(sb);
Mike Marshall1182fca2015-07-17 10:38:15 -0400597free_op:
Yi Liu8bb8aef2015-11-24 15:12:14 -0500598 gossip_err("orangefs_mount: mount request failed with %d\n", ret);
Mike Marshall1182fca2015-07-17 10:38:15 -0400599 if (ret == -EINVAL) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500600 gossip_err("Ensure that all orangefs-servers have the same FS configuration files\n");
Mike Marshall1182fca2015-07-17 10:38:15 -0400601 gossip_err("Look at pvfs2-client-core log file (typically /tmp/pvfs2-client.log) for more details\n");
602 }
603
604 op_release(new_op);
605
Mike Marshall1be21f82015-09-29 15:26:37 -0400606 return d;
Mike Marshall1182fca2015-07-17 10:38:15 -0400607}
608
Yi Liu8bb8aef2015-11-24 15:12:14 -0500609void orangefs_kill_sb(struct super_block *sb)
Mike Marshall1182fca2015-07-17 10:38:15 -0400610{
Martin Brandenburg9d286b02017-04-25 15:38:05 -0400611 int r;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500612 gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_kill_sb: called\n");
Mike Marshall1182fca2015-07-17 10:38:15 -0400613
Al Viro524b1d32016-02-16 21:08:29 -0500614 /* provided sb cleanup */
615 kill_anon_super(sb);
616
Al Viro65903842018-04-03 00:13:17 -0400617 if (!ORANGEFS_SB(sb)) {
618 mutex_lock(&orangefs_request_mutex);
619 mutex_unlock(&orangefs_request_mutex);
620 return;
621 }
Mike Marshall1182fca2015-07-17 10:38:15 -0400622 /*
623 * issue the unmount to userspace to tell it to remove the
624 * dynamic mount info it has for this superblock
625 */
Martin Brandenburg9d286b02017-04-25 15:38:05 -0400626 r = orangefs_unmount(ORANGEFS_SB(sb)->id, ORANGEFS_SB(sb)->fs_id,
627 ORANGEFS_SB(sb)->devname);
628 if (!r)
629 ORANGEFS_SB(sb)->mount_pending = 1;
Mike Marshall1182fca2015-07-17 10:38:15 -0400630
Martin Brandenburg1ec16882017-04-14 14:22:41 -0400631 if (!ORANGEFS_SB(sb)->no_list) {
632 /* remove the sb from our list of orangefs specific sb's */
633 spin_lock(&orangefs_superblocks_lock);
634 /* not list_del_init */
635 __list_del_entry(&ORANGEFS_SB(sb)->list);
636 ORANGEFS_SB(sb)->list.prev = NULL;
637 spin_unlock(&orangefs_superblocks_lock);
638 }
Al Viro45996492016-03-25 19:56:34 -0400639
640 /*
641 * make sure that ORANGEFS_DEV_REMOUNT_ALL loop that might've seen us
642 * gets completed before we free the dang thing.
643 */
Martin Brandenburg1d503612016-08-16 11:38:14 -0400644 mutex_lock(&orangefs_request_mutex);
645 mutex_unlock(&orangefs_request_mutex);
Mike Marshall1182fca2015-07-17 10:38:15 -0400646
Yi Liu8bb8aef2015-11-24 15:12:14 -0500647 /* free the orangefs superblock private data */
648 kfree(ORANGEFS_SB(sb));
Mike Marshall1182fca2015-07-17 10:38:15 -0400649}
650
Yi Liu8bb8aef2015-11-24 15:12:14 -0500651int orangefs_inode_cache_initialize(void)
Mike Marshall1182fca2015-07-17 10:38:15 -0400652{
David Windsor6b330622017-06-10 22:50:39 -0400653 orangefs_inode_cache = kmem_cache_create_usercopy(
654 "orangefs_inode_cache",
655 sizeof(struct orangefs_inode_s),
656 0,
657 ORANGEFS_CACHE_CREATE_FLAGS,
658 offsetof(struct orangefs_inode_s,
659 link_target),
660 sizeof_field(struct orangefs_inode_s,
661 link_target),
662 orangefs_inode_cache_ctor);
Mike Marshall1182fca2015-07-17 10:38:15 -0400663
Yi Liu8bb8aef2015-11-24 15:12:14 -0500664 if (!orangefs_inode_cache) {
665 gossip_err("Cannot create orangefs_inode_cache\n");
Mike Marshall1182fca2015-07-17 10:38:15 -0400666 return -ENOMEM;
667 }
668 return 0;
669}
670
Yi Liu8bb8aef2015-11-24 15:12:14 -0500671int orangefs_inode_cache_finalize(void)
Mike Marshall1182fca2015-07-17 10:38:15 -0400672{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500673 kmem_cache_destroy(orangefs_inode_cache);
Mike Marshall1182fca2015-07-17 10:38:15 -0400674 return 0;
675}