0001
0002
0003
0004
0005
0006
0007
0008 #include "protocol.h"
0009 #include "orangefs-kernel.h"
0010 #include "orangefs-bufmap.h"
0011
0012 #include <linux/parser.h>
0013 #include <linux/hashtable.h>
0014 #include <linux/seq_file.h>
0015
0016
0017 static struct kmem_cache *orangefs_inode_cache;
0018
0019
0020 LIST_HEAD(orangefs_superblocks);
0021
0022 DEFINE_SPINLOCK(orangefs_superblocks_lock);
0023
0024 enum {
0025 Opt_intr,
0026 Opt_acl,
0027 Opt_local_lock,
0028
0029 Opt_err
0030 };
0031
0032 static const match_table_t tokens = {
0033 { Opt_acl, "acl" },
0034 { Opt_intr, "intr" },
0035 { Opt_local_lock, "local_lock" },
0036 { Opt_err, NULL }
0037 };
0038
0039 uint64_t orangefs_features;
0040
0041 static int orangefs_show_options(struct seq_file *m, struct dentry *root)
0042 {
0043 struct orangefs_sb_info_s *orangefs_sb = ORANGEFS_SB(root->d_sb);
0044
0045 if (root->d_sb->s_flags & SB_POSIXACL)
0046 seq_puts(m, ",acl");
0047 if (orangefs_sb->flags & ORANGEFS_OPT_INTR)
0048 seq_puts(m, ",intr");
0049 if (orangefs_sb->flags & ORANGEFS_OPT_LOCAL_LOCK)
0050 seq_puts(m, ",local_lock");
0051 return 0;
0052 }
0053
0054 static int parse_mount_options(struct super_block *sb, char *options,
0055 int silent)
0056 {
0057 struct orangefs_sb_info_s *orangefs_sb = ORANGEFS_SB(sb);
0058 substring_t args[MAX_OPT_ARGS];
0059 char *p;
0060
0061
0062
0063
0064
0065 sb->s_flags &= ~SB_POSIXACL;
0066 orangefs_sb->flags &= ~ORANGEFS_OPT_INTR;
0067 orangefs_sb->flags &= ~ORANGEFS_OPT_LOCAL_LOCK;
0068
0069 while ((p = strsep(&options, ",")) != NULL) {
0070 int token;
0071
0072 if (!*p)
0073 continue;
0074
0075 token = match_token(p, tokens, args);
0076 switch (token) {
0077 case Opt_acl:
0078 sb->s_flags |= SB_POSIXACL;
0079 break;
0080 case Opt_intr:
0081 orangefs_sb->flags |= ORANGEFS_OPT_INTR;
0082 break;
0083 case Opt_local_lock:
0084 orangefs_sb->flags |= ORANGEFS_OPT_LOCAL_LOCK;
0085 break;
0086 default:
0087 goto fail;
0088 }
0089 }
0090
0091 return 0;
0092 fail:
0093 if (!silent)
0094 gossip_err("Error: mount option [%s] is not supported.\n", p);
0095 return -EINVAL;
0096 }
0097
0098 static void orangefs_inode_cache_ctor(void *req)
0099 {
0100 struct orangefs_inode_s *orangefs_inode = req;
0101
0102 inode_init_once(&orangefs_inode->vfs_inode);
0103 init_rwsem(&orangefs_inode->xattr_sem);
0104 }
0105
0106 static struct inode *orangefs_alloc_inode(struct super_block *sb)
0107 {
0108 struct orangefs_inode_s *orangefs_inode;
0109
0110 orangefs_inode = alloc_inode_sb(sb, orangefs_inode_cache, GFP_KERNEL);
0111 if (!orangefs_inode)
0112 return NULL;
0113
0114
0115
0116
0117
0118 memset(&orangefs_inode->refn.khandle, 0, 16);
0119 orangefs_inode->refn.fs_id = ORANGEFS_FS_ID_NULL;
0120 orangefs_inode->last_failed_block_index_read = 0;
0121 memset(orangefs_inode->link_target, 0, sizeof(orangefs_inode->link_target));
0122
0123 gossip_debug(GOSSIP_SUPER_DEBUG,
0124 "orangefs_alloc_inode: allocated %p\n",
0125 &orangefs_inode->vfs_inode);
0126 return &orangefs_inode->vfs_inode;
0127 }
0128
0129 static void orangefs_free_inode(struct inode *inode)
0130 {
0131 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
0132 struct orangefs_cached_xattr *cx;
0133 struct hlist_node *tmp;
0134 int i;
0135
0136 hash_for_each_safe(orangefs_inode->xattr_cache, i, tmp, cx, node) {
0137 hlist_del(&cx->node);
0138 kfree(cx);
0139 }
0140
0141 kmem_cache_free(orangefs_inode_cache, orangefs_inode);
0142 }
0143
0144 static void orangefs_destroy_inode(struct inode *inode)
0145 {
0146 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
0147
0148 gossip_debug(GOSSIP_SUPER_DEBUG,
0149 "%s: deallocated %p destroying inode %pU\n",
0150 __func__, orangefs_inode, get_khandle_from_ino(inode));
0151 }
0152
0153 static int orangefs_write_inode(struct inode *inode,
0154 struct writeback_control *wbc)
0155 {
0156 gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_write_inode\n");
0157 return orangefs_inode_setattr(inode);
0158 }
0159
0160
0161
0162
0163
0164 static int orangefs_statfs(struct dentry *dentry, struct kstatfs *buf)
0165 {
0166 int ret = -ENOMEM;
0167 struct orangefs_kernel_op_s *new_op = NULL;
0168 int flags = 0;
0169 struct super_block *sb = NULL;
0170
0171 sb = dentry->d_sb;
0172
0173 gossip_debug(GOSSIP_SUPER_DEBUG,
0174 "%s: called on sb %p (fs_id is %d)\n",
0175 __func__,
0176 sb,
0177 (int)(ORANGEFS_SB(sb)->fs_id));
0178
0179 new_op = op_alloc(ORANGEFS_VFS_OP_STATFS);
0180 if (!new_op)
0181 return ret;
0182 new_op->upcall.req.statfs.fs_id = ORANGEFS_SB(sb)->fs_id;
0183
0184 if (ORANGEFS_SB(sb)->flags & ORANGEFS_OPT_INTR)
0185 flags = ORANGEFS_OP_INTERRUPTIBLE;
0186
0187 ret = service_operation(new_op, "orangefs_statfs", flags);
0188
0189 if (new_op->downcall.status < 0)
0190 goto out_op_release;
0191
0192 gossip_debug(GOSSIP_SUPER_DEBUG,
0193 "%s: got %ld blocks available | "
0194 "%ld blocks total | %ld block size | "
0195 "%ld files total | %ld files avail\n",
0196 __func__,
0197 (long)new_op->downcall.resp.statfs.blocks_avail,
0198 (long)new_op->downcall.resp.statfs.blocks_total,
0199 (long)new_op->downcall.resp.statfs.block_size,
0200 (long)new_op->downcall.resp.statfs.files_total,
0201 (long)new_op->downcall.resp.statfs.files_avail);
0202
0203 buf->f_type = sb->s_magic;
0204 memcpy(&buf->f_fsid, &ORANGEFS_SB(sb)->fs_id, sizeof(buf->f_fsid));
0205 buf->f_bsize = new_op->downcall.resp.statfs.block_size;
0206 buf->f_namelen = ORANGEFS_NAME_MAX;
0207
0208 buf->f_blocks = (sector_t) new_op->downcall.resp.statfs.blocks_total;
0209 buf->f_bfree = (sector_t) new_op->downcall.resp.statfs.blocks_avail;
0210 buf->f_bavail = (sector_t) new_op->downcall.resp.statfs.blocks_avail;
0211 buf->f_files = (sector_t) new_op->downcall.resp.statfs.files_total;
0212 buf->f_ffree = (sector_t) new_op->downcall.resp.statfs.files_avail;
0213 buf->f_frsize = 0;
0214
0215 out_op_release:
0216 op_release(new_op);
0217 gossip_debug(GOSSIP_SUPER_DEBUG, "%s: returning %d\n", __func__, ret);
0218 return ret;
0219 }
0220
0221
0222
0223
0224
0225 static int orangefs_remount_fs(struct super_block *sb, int *flags, char *data)
0226 {
0227 gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount_fs: called\n");
0228 return parse_mount_options(sb, data, 1);
0229 }
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 int orangefs_remount(struct orangefs_sb_info_s *orangefs_sb)
0247 {
0248 struct orangefs_kernel_op_s *new_op;
0249 int ret = -EINVAL;
0250
0251 gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount: called\n");
0252
0253 new_op = op_alloc(ORANGEFS_VFS_OP_FS_MOUNT);
0254 if (!new_op)
0255 return -ENOMEM;
0256 strncpy(new_op->upcall.req.fs_mount.orangefs_config_server,
0257 orangefs_sb->devname,
0258 ORANGEFS_MAX_SERVER_ADDR_LEN);
0259
0260 gossip_debug(GOSSIP_SUPER_DEBUG,
0261 "Attempting ORANGEFS Remount via host %s\n",
0262 new_op->upcall.req.fs_mount.orangefs_config_server);
0263
0264
0265
0266
0267
0268
0269 ret = service_operation(new_op, "orangefs_remount",
0270 ORANGEFS_OP_PRIORITY | ORANGEFS_OP_NO_MUTEX);
0271 gossip_debug(GOSSIP_SUPER_DEBUG,
0272 "orangefs_remount: mount got return value of %d\n",
0273 ret);
0274 if (ret == 0) {
0275
0276
0277
0278
0279
0280 orangefs_sb->id = new_op->downcall.resp.fs_mount.id;
0281 orangefs_sb->mount_pending = 0;
0282 }
0283
0284 op_release(new_op);
0285
0286 if (orangefs_userspace_version >= 20906) {
0287 new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
0288 if (!new_op)
0289 return -ENOMEM;
0290 new_op->upcall.req.features.features = 0;
0291 ret = service_operation(new_op, "orangefs_features",
0292 ORANGEFS_OP_PRIORITY | ORANGEFS_OP_NO_MUTEX);
0293 if (!ret)
0294 orangefs_features =
0295 new_op->downcall.resp.features.features;
0296 else
0297 orangefs_features = 0;
0298 op_release(new_op);
0299 } else {
0300 orangefs_features = 0;
0301 }
0302
0303 return ret;
0304 }
0305
0306 int fsid_key_table_initialize(void)
0307 {
0308 return 0;
0309 }
0310
0311 void fsid_key_table_finalize(void)
0312 {
0313 }
0314
0315 static const struct super_operations orangefs_s_ops = {
0316 .alloc_inode = orangefs_alloc_inode,
0317 .free_inode = orangefs_free_inode,
0318 .destroy_inode = orangefs_destroy_inode,
0319 .write_inode = orangefs_write_inode,
0320 .drop_inode = generic_delete_inode,
0321 .statfs = orangefs_statfs,
0322 .remount_fs = orangefs_remount_fs,
0323 .show_options = orangefs_show_options,
0324 };
0325
0326 static struct dentry *orangefs_fh_to_dentry(struct super_block *sb,
0327 struct fid *fid,
0328 int fh_len,
0329 int fh_type)
0330 {
0331 struct orangefs_object_kref refn;
0332
0333 if (fh_len < 5 || fh_type > 2)
0334 return NULL;
0335
0336 ORANGEFS_khandle_from(&(refn.khandle), fid->raw, 16);
0337 refn.fs_id = (u32) fid->raw[4];
0338 gossip_debug(GOSSIP_SUPER_DEBUG,
0339 "fh_to_dentry: handle %pU, fs_id %d\n",
0340 &refn.khandle,
0341 refn.fs_id);
0342
0343 return d_obtain_alias(orangefs_iget(sb, &refn));
0344 }
0345
0346 static int orangefs_encode_fh(struct inode *inode,
0347 __u32 *fh,
0348 int *max_len,
0349 struct inode *parent)
0350 {
0351 int len = parent ? 10 : 5;
0352 int type = 1;
0353 struct orangefs_object_kref refn;
0354
0355 if (*max_len < len) {
0356 gossip_err("fh buffer is too small for encoding\n");
0357 *max_len = len;
0358 type = 255;
0359 goto out;
0360 }
0361
0362 refn = ORANGEFS_I(inode)->refn;
0363 ORANGEFS_khandle_to(&refn.khandle, fh, 16);
0364 fh[4] = refn.fs_id;
0365
0366 gossip_debug(GOSSIP_SUPER_DEBUG,
0367 "Encoding fh: handle %pU, fsid %u\n",
0368 &refn.khandle,
0369 refn.fs_id);
0370
0371
0372 if (parent) {
0373 refn = ORANGEFS_I(parent)->refn;
0374 ORANGEFS_khandle_to(&refn.khandle, (char *) fh + 20, 16);
0375 fh[9] = refn.fs_id;
0376
0377 type = 2;
0378 gossip_debug(GOSSIP_SUPER_DEBUG,
0379 "Encoding parent: handle %pU, fsid %u\n",
0380 &refn.khandle,
0381 refn.fs_id);
0382 }
0383 *max_len = len;
0384
0385 out:
0386 return type;
0387 }
0388
0389 static const struct export_operations orangefs_export_ops = {
0390 .encode_fh = orangefs_encode_fh,
0391 .fh_to_dentry = orangefs_fh_to_dentry,
0392 };
0393
0394 static int orangefs_unmount(int id, __s32 fs_id, const char *devname)
0395 {
0396 struct orangefs_kernel_op_s *op;
0397 int r;
0398 op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
0399 if (!op)
0400 return -ENOMEM;
0401 op->upcall.req.fs_umount.id = id;
0402 op->upcall.req.fs_umount.fs_id = fs_id;
0403 strncpy(op->upcall.req.fs_umount.orangefs_config_server,
0404 devname, ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
0405 r = service_operation(op, "orangefs_fs_umount", 0);
0406
0407 if (r)
0408 gossip_err("orangefs_unmount: service_operation %d\n", r);
0409 op_release(op);
0410 return r;
0411 }
0412
0413 static int orangefs_fill_sb(struct super_block *sb,
0414 struct orangefs_fs_mount_response *fs_mount,
0415 void *data, int silent)
0416 {
0417 int ret;
0418 struct inode *root;
0419 struct dentry *root_dentry;
0420 struct orangefs_object_kref root_object;
0421
0422 ORANGEFS_SB(sb)->sb = sb;
0423
0424 ORANGEFS_SB(sb)->root_khandle = fs_mount->root_khandle;
0425 ORANGEFS_SB(sb)->fs_id = fs_mount->fs_id;
0426 ORANGEFS_SB(sb)->id = fs_mount->id;
0427
0428 if (data) {
0429 ret = parse_mount_options(sb, data, silent);
0430 if (ret)
0431 return ret;
0432 }
0433
0434
0435 sb->s_xattr = orangefs_xattr_handlers;
0436 sb->s_magic = ORANGEFS_SUPER_MAGIC;
0437 sb->s_op = &orangefs_s_ops;
0438 sb->s_d_op = &orangefs_dentry_operations;
0439
0440 sb->s_blocksize = PAGE_SIZE;
0441 sb->s_blocksize_bits = PAGE_SHIFT;
0442 sb->s_maxbytes = MAX_LFS_FILESIZE;
0443
0444 ret = super_setup_bdi(sb);
0445 if (ret)
0446 return ret;
0447
0448 root_object.khandle = ORANGEFS_SB(sb)->root_khandle;
0449 root_object.fs_id = ORANGEFS_SB(sb)->fs_id;
0450 gossip_debug(GOSSIP_SUPER_DEBUG,
0451 "get inode %pU, fsid %d\n",
0452 &root_object.khandle,
0453 root_object.fs_id);
0454
0455 root = orangefs_iget(sb, &root_object);
0456 if (IS_ERR(root))
0457 return PTR_ERR(root);
0458
0459 gossip_debug(GOSSIP_SUPER_DEBUG,
0460 "Allocated root inode [%p] with mode %x\n",
0461 root,
0462 root->i_mode);
0463
0464
0465 root_dentry = d_make_root(root);
0466 if (!root_dentry)
0467 return -ENOMEM;
0468
0469 sb->s_export_op = &orangefs_export_ops;
0470 sb->s_root = root_dentry;
0471 return 0;
0472 }
0473
0474 struct dentry *orangefs_mount(struct file_system_type *fst,
0475 int flags,
0476 const char *devname,
0477 void *data)
0478 {
0479 int ret;
0480 struct super_block *sb = ERR_PTR(-EINVAL);
0481 struct orangefs_kernel_op_s *new_op;
0482 struct dentry *d = ERR_PTR(-EINVAL);
0483
0484 gossip_debug(GOSSIP_SUPER_DEBUG,
0485 "orangefs_mount: called with devname %s\n",
0486 devname);
0487
0488 if (!devname) {
0489 gossip_err("ERROR: device name not specified.\n");
0490 return ERR_PTR(-EINVAL);
0491 }
0492
0493 new_op = op_alloc(ORANGEFS_VFS_OP_FS_MOUNT);
0494 if (!new_op)
0495 return ERR_PTR(-ENOMEM);
0496
0497 strncpy(new_op->upcall.req.fs_mount.orangefs_config_server,
0498 devname,
0499 ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
0500
0501 gossip_debug(GOSSIP_SUPER_DEBUG,
0502 "Attempting ORANGEFS Mount via host %s\n",
0503 new_op->upcall.req.fs_mount.orangefs_config_server);
0504
0505 ret = service_operation(new_op, "orangefs_mount", 0);
0506 gossip_debug(GOSSIP_SUPER_DEBUG,
0507 "orangefs_mount: mount got return value of %d\n", ret);
0508 if (ret)
0509 goto free_op;
0510
0511 if (new_op->downcall.resp.fs_mount.fs_id == ORANGEFS_FS_ID_NULL) {
0512 gossip_err("ERROR: Retrieved null fs_id\n");
0513 ret = -EINVAL;
0514 goto free_op;
0515 }
0516
0517 sb = sget(fst, NULL, set_anon_super, flags, NULL);
0518
0519 if (IS_ERR(sb)) {
0520 d = ERR_CAST(sb);
0521 orangefs_unmount(new_op->downcall.resp.fs_mount.id,
0522 new_op->downcall.resp.fs_mount.fs_id, devname);
0523 goto free_op;
0524 }
0525
0526
0527 sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL);
0528 if (!ORANGEFS_SB(sb)) {
0529 d = ERR_PTR(-ENOMEM);
0530 goto free_sb_and_op;
0531 }
0532
0533 ret = orangefs_fill_sb(sb,
0534 &new_op->downcall.resp.fs_mount, data,
0535 flags & SB_SILENT ? 1 : 0);
0536
0537 if (ret) {
0538 d = ERR_PTR(ret);
0539 goto free_sb_and_op;
0540 }
0541
0542
0543
0544
0545
0546 strncpy(ORANGEFS_SB(sb)->devname,
0547 devname,
0548 ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
0549
0550
0551 ORANGEFS_SB(sb)->mount_pending = 0;
0552
0553
0554
0555
0556
0557 gossip_debug(GOSSIP_SUPER_DEBUG,
0558 "Adding SB %p to orangefs superblocks\n",
0559 ORANGEFS_SB(sb));
0560 spin_lock(&orangefs_superblocks_lock);
0561 list_add_tail(&ORANGEFS_SB(sb)->list, &orangefs_superblocks);
0562 spin_unlock(&orangefs_superblocks_lock);
0563 op_release(new_op);
0564
0565
0566 ORANGEFS_SB(sb)->no_list = 0;
0567
0568 if (orangefs_userspace_version >= 20906) {
0569 new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
0570 if (!new_op)
0571 return ERR_PTR(-ENOMEM);
0572 new_op->upcall.req.features.features = 0;
0573 ret = service_operation(new_op, "orangefs_features", 0);
0574 orangefs_features = new_op->downcall.resp.features.features;
0575 op_release(new_op);
0576 } else {
0577 orangefs_features = 0;
0578 }
0579
0580 return dget(sb->s_root);
0581
0582 free_sb_and_op:
0583
0584 ORANGEFS_SB(sb)->no_list = 1;
0585
0586 deactivate_locked_super(sb);
0587 free_op:
0588 gossip_err("orangefs_mount: mount request failed with %d\n", ret);
0589 if (ret == -EINVAL) {
0590 gossip_err("Ensure that all orangefs-servers have the same FS configuration files\n");
0591 gossip_err("Look at pvfs2-client-core log file (typically /tmp/pvfs2-client.log) for more details\n");
0592 }
0593
0594 op_release(new_op);
0595
0596 return d;
0597 }
0598
0599 void orangefs_kill_sb(struct super_block *sb)
0600 {
0601 int r;
0602 gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_kill_sb: called\n");
0603
0604
0605 kill_anon_super(sb);
0606
0607 if (!ORANGEFS_SB(sb)) {
0608 mutex_lock(&orangefs_request_mutex);
0609 mutex_unlock(&orangefs_request_mutex);
0610 return;
0611 }
0612
0613
0614
0615
0616 r = orangefs_unmount(ORANGEFS_SB(sb)->id, ORANGEFS_SB(sb)->fs_id,
0617 ORANGEFS_SB(sb)->devname);
0618 if (!r)
0619 ORANGEFS_SB(sb)->mount_pending = 1;
0620
0621 if (!ORANGEFS_SB(sb)->no_list) {
0622
0623 spin_lock(&orangefs_superblocks_lock);
0624
0625 __list_del_entry(&ORANGEFS_SB(sb)->list);
0626 ORANGEFS_SB(sb)->list.prev = NULL;
0627 spin_unlock(&orangefs_superblocks_lock);
0628 }
0629
0630
0631
0632
0633
0634 mutex_lock(&orangefs_request_mutex);
0635 mutex_unlock(&orangefs_request_mutex);
0636
0637
0638 kfree(ORANGEFS_SB(sb));
0639 }
0640
0641 int orangefs_inode_cache_initialize(void)
0642 {
0643 orangefs_inode_cache = kmem_cache_create_usercopy(
0644 "orangefs_inode_cache",
0645 sizeof(struct orangefs_inode_s),
0646 0,
0647 ORANGEFS_CACHE_CREATE_FLAGS,
0648 offsetof(struct orangefs_inode_s,
0649 link_target),
0650 sizeof_field(struct orangefs_inode_s,
0651 link_target),
0652 orangefs_inode_cache_ctor);
0653
0654 if (!orangefs_inode_cache) {
0655 gossip_err("Cannot create orangefs_inode_cache\n");
0656 return -ENOMEM;
0657 }
0658 return 0;
0659 }
0660
0661 int orangefs_inode_cache_finalize(void)
0662 {
0663 kmem_cache_destroy(orangefs_inode_cache);
0664 return 0;
0665 }