92a38b0091f2b9c63e06ae6bed6723e78c3ca637
[deliverable/linux.git] / fs / orangefs / orangefs-utils.c
1 /*
2 * (C) 2001 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6 #include "protocol.h"
7 #include "orangefs-kernel.h"
8 #include "orangefs-dev-proto.h"
9 #include "orangefs-bufmap.h"
10
11 __s32 fsid_of_op(struct orangefs_kernel_op_s *op)
12 {
13 __s32 fsid = ORANGEFS_FS_ID_NULL;
14
15 if (op) {
16 switch (op->upcall.type) {
17 case ORANGEFS_VFS_OP_FILE_IO:
18 fsid = op->upcall.req.io.refn.fs_id;
19 break;
20 case ORANGEFS_VFS_OP_LOOKUP:
21 fsid = op->upcall.req.lookup.parent_refn.fs_id;
22 break;
23 case ORANGEFS_VFS_OP_CREATE:
24 fsid = op->upcall.req.create.parent_refn.fs_id;
25 break;
26 case ORANGEFS_VFS_OP_GETATTR:
27 fsid = op->upcall.req.getattr.refn.fs_id;
28 break;
29 case ORANGEFS_VFS_OP_REMOVE:
30 fsid = op->upcall.req.remove.parent_refn.fs_id;
31 break;
32 case ORANGEFS_VFS_OP_MKDIR:
33 fsid = op->upcall.req.mkdir.parent_refn.fs_id;
34 break;
35 case ORANGEFS_VFS_OP_READDIR:
36 fsid = op->upcall.req.readdir.refn.fs_id;
37 break;
38 case ORANGEFS_VFS_OP_SETATTR:
39 fsid = op->upcall.req.setattr.refn.fs_id;
40 break;
41 case ORANGEFS_VFS_OP_SYMLINK:
42 fsid = op->upcall.req.sym.parent_refn.fs_id;
43 break;
44 case ORANGEFS_VFS_OP_RENAME:
45 fsid = op->upcall.req.rename.old_parent_refn.fs_id;
46 break;
47 case ORANGEFS_VFS_OP_STATFS:
48 fsid = op->upcall.req.statfs.fs_id;
49 break;
50 case ORANGEFS_VFS_OP_TRUNCATE:
51 fsid = op->upcall.req.truncate.refn.fs_id;
52 break;
53 case ORANGEFS_VFS_OP_MMAP_RA_FLUSH:
54 fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
55 break;
56 case ORANGEFS_VFS_OP_FS_UMOUNT:
57 fsid = op->upcall.req.fs_umount.fs_id;
58 break;
59 case ORANGEFS_VFS_OP_GETXATTR:
60 fsid = op->upcall.req.getxattr.refn.fs_id;
61 break;
62 case ORANGEFS_VFS_OP_SETXATTR:
63 fsid = op->upcall.req.setxattr.refn.fs_id;
64 break;
65 case ORANGEFS_VFS_OP_LISTXATTR:
66 fsid = op->upcall.req.listxattr.refn.fs_id;
67 break;
68 case ORANGEFS_VFS_OP_REMOVEXATTR:
69 fsid = op->upcall.req.removexattr.refn.fs_id;
70 break;
71 case ORANGEFS_VFS_OP_FSYNC:
72 fsid = op->upcall.req.fsync.refn.fs_id;
73 break;
74 default:
75 break;
76 }
77 }
78 return fsid;
79 }
80
81 static void orangefs_set_inode_flags(struct inode *inode,
82 struct ORANGEFS_sys_attr_s *attrs)
83 {
84 if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
85 inode->i_flags |= S_IMMUTABLE;
86 else
87 inode->i_flags &= ~S_IMMUTABLE;
88
89 if (attrs->flags & ORANGEFS_APPEND_FL)
90 inode->i_flags |= S_APPEND;
91 else
92 inode->i_flags &= ~S_APPEND;
93
94 if (attrs->flags & ORANGEFS_NOATIME_FL)
95 inode->i_flags |= S_NOATIME;
96 else
97 inode->i_flags &= ~S_NOATIME;
98
99 }
100
101 /* NOTE: symname is ignored unless the inode is a sym link */
102 static int copy_attributes_to_inode(struct inode *inode,
103 struct ORANGEFS_sys_attr_s *attrs,
104 char *symname)
105 {
106 int ret = -1;
107 int perm_mode = 0;
108 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
109 loff_t inode_size = 0;
110 loff_t rounded_up_size = 0;
111
112
113 /*
114 * arbitrarily set the inode block size; FIXME: we need to
115 * resolve the difference between the reported inode blocksize
116 * and the PAGE_CACHE_SIZE, since our block count will always
117 * be wrong.
118 *
119 * For now, we're setting the block count to be the proper
120 * number assuming the block size is 512 bytes, and the size is
121 * rounded up to the nearest 4K. This is apparently required
122 * to get proper size reports from the 'du' shell utility.
123 *
124 * changing the inode->i_blkbits to something other than
125 * PAGE_CACHE_SHIFT breaks mmap/execution as we depend on that.
126 */
127 gossip_debug(GOSSIP_UTILS_DEBUG,
128 "attrs->mask = %x (objtype = %s)\n",
129 attrs->mask,
130 attrs->objtype == ORANGEFS_TYPE_METAFILE ? "file" :
131 attrs->objtype == ORANGEFS_TYPE_DIRECTORY ? "directory" :
132 attrs->objtype == ORANGEFS_TYPE_SYMLINK ? "symlink" :
133 "invalid/unknown");
134
135 switch (attrs->objtype) {
136 case ORANGEFS_TYPE_METAFILE:
137 orangefs_set_inode_flags(inode, attrs);
138 if (attrs->mask & ORANGEFS_ATTR_SYS_SIZE) {
139 inode_size = (loff_t) attrs->size;
140 rounded_up_size =
141 (inode_size + (4096 - (inode_size % 4096)));
142
143 orangefs_lock_inode(inode);
144 inode->i_bytes = inode_size;
145 inode->i_blocks =
146 (unsigned long)(rounded_up_size / 512);
147 orangefs_unlock_inode(inode);
148
149 /*
150 * NOTE: make sure all the places we're called
151 * from have the inode->i_sem lock. We're fine
152 * in 99% of the cases since we're mostly
153 * called from a lookup.
154 */
155 inode->i_size = inode_size;
156 }
157 break;
158 case ORANGEFS_TYPE_SYMLINK:
159 if (symname != NULL) {
160 inode->i_size = (loff_t) strlen(symname);
161 break;
162 }
163 /*FALLTHRU*/
164 default:
165 inode->i_size = PAGE_CACHE_SIZE;
166
167 orangefs_lock_inode(inode);
168 inode_set_bytes(inode, inode->i_size);
169 orangefs_unlock_inode(inode);
170 break;
171 }
172
173 inode->i_uid = make_kuid(&init_user_ns, attrs->owner);
174 inode->i_gid = make_kgid(&init_user_ns, attrs->group);
175 inode->i_atime.tv_sec = (time_t) attrs->atime;
176 inode->i_mtime.tv_sec = (time_t) attrs->mtime;
177 inode->i_ctime.tv_sec = (time_t) attrs->ctime;
178 inode->i_atime.tv_nsec = 0;
179 inode->i_mtime.tv_nsec = 0;
180 inode->i_ctime.tv_nsec = 0;
181
182 if (attrs->perms & ORANGEFS_O_EXECUTE)
183 perm_mode |= S_IXOTH;
184 if (attrs->perms & ORANGEFS_O_WRITE)
185 perm_mode |= S_IWOTH;
186 if (attrs->perms & ORANGEFS_O_READ)
187 perm_mode |= S_IROTH;
188
189 if (attrs->perms & ORANGEFS_G_EXECUTE)
190 perm_mode |= S_IXGRP;
191 if (attrs->perms & ORANGEFS_G_WRITE)
192 perm_mode |= S_IWGRP;
193 if (attrs->perms & ORANGEFS_G_READ)
194 perm_mode |= S_IRGRP;
195
196 if (attrs->perms & ORANGEFS_U_EXECUTE)
197 perm_mode |= S_IXUSR;
198 if (attrs->perms & ORANGEFS_U_WRITE)
199 perm_mode |= S_IWUSR;
200 if (attrs->perms & ORANGEFS_U_READ)
201 perm_mode |= S_IRUSR;
202
203 if (attrs->perms & ORANGEFS_G_SGID)
204 perm_mode |= S_ISGID;
205 if (attrs->perms & ORANGEFS_U_SUID)
206 perm_mode |= S_ISUID;
207
208 inode->i_mode = perm_mode;
209
210 if (is_root_handle(inode)) {
211 /* special case: mark the root inode as sticky */
212 inode->i_mode |= S_ISVTX;
213 gossip_debug(GOSSIP_UTILS_DEBUG,
214 "Marking inode %pU as sticky\n",
215 get_khandle_from_ino(inode));
216 }
217
218 switch (attrs->objtype) {
219 case ORANGEFS_TYPE_METAFILE:
220 inode->i_mode |= S_IFREG;
221 ret = 0;
222 break;
223 case ORANGEFS_TYPE_DIRECTORY:
224 inode->i_mode |= S_IFDIR;
225 /* NOTE: we have no good way to keep nlink consistent
226 * for directories across clients; keep constant at 1.
227 * Why 1? If we go with 2, then find(1) gets confused
228 * and won't work properly withouth the -noleaf option
229 */
230 set_nlink(inode, 1);
231 ret = 0;
232 break;
233 case ORANGEFS_TYPE_SYMLINK:
234 inode->i_mode |= S_IFLNK;
235
236 /* copy link target to inode private data */
237 if (orangefs_inode && symname) {
238 strncpy(orangefs_inode->link_target,
239 symname,
240 ORANGEFS_NAME_MAX);
241 gossip_debug(GOSSIP_UTILS_DEBUG,
242 "Copied attr link target %s\n",
243 orangefs_inode->link_target);
244 }
245 gossip_debug(GOSSIP_UTILS_DEBUG,
246 "symlink mode %o\n",
247 inode->i_mode);
248 ret = 0;
249 break;
250 default:
251 gossip_err("orangefs: copy_attributes_to_inode: got invalid attribute type %x\n",
252 attrs->objtype);
253 }
254
255 gossip_debug(GOSSIP_UTILS_DEBUG,
256 "orangefs: copy_attributes_to_inode: setting i_mode to %o, i_size to %lu\n",
257 inode->i_mode,
258 (unsigned long)i_size_read(inode));
259
260 return ret;
261 }
262
263 /*
264 * NOTE: in kernel land, we never use the sys_attr->link_target for
265 * anything, so don't bother copying it into the sys_attr object here.
266 */
267 static inline int copy_attributes_from_inode(struct inode *inode,
268 struct ORANGEFS_sys_attr_s *attrs,
269 struct iattr *iattr)
270 {
271 umode_t tmp_mode;
272
273 if (!iattr || !inode || !attrs) {
274 gossip_err("NULL iattr (%p), inode (%p), attrs (%p) "
275 "in copy_attributes_from_inode!\n",
276 iattr,
277 inode,
278 attrs);
279 return -EINVAL;
280 }
281 /*
282 * We need to be careful to only copy the attributes out of the
283 * iattr object that we know are valid.
284 */
285 attrs->mask = 0;
286 if (iattr->ia_valid & ATTR_UID) {
287 attrs->owner = from_kuid(current_user_ns(), iattr->ia_uid);
288 attrs->mask |= ORANGEFS_ATTR_SYS_UID;
289 gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
290 }
291 if (iattr->ia_valid & ATTR_GID) {
292 attrs->group = from_kgid(current_user_ns(), iattr->ia_gid);
293 attrs->mask |= ORANGEFS_ATTR_SYS_GID;
294 gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
295 }
296
297 if (iattr->ia_valid & ATTR_ATIME) {
298 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
299 if (iattr->ia_valid & ATTR_ATIME_SET) {
300 attrs->atime =
301 orangefs_convert_time_field(&iattr->ia_atime);
302 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
303 }
304 }
305 if (iattr->ia_valid & ATTR_MTIME) {
306 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
307 if (iattr->ia_valid & ATTR_MTIME_SET) {
308 attrs->mtime =
309 orangefs_convert_time_field(&iattr->ia_mtime);
310 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
311 }
312 }
313 if (iattr->ia_valid & ATTR_CTIME)
314 attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
315
316 /*
317 * ORANGEFS cannot set size with a setattr operation. Probably not likely
318 * to be requested through the VFS, but just in case, don't worry about
319 * ATTR_SIZE
320 */
321
322 if (iattr->ia_valid & ATTR_MODE) {
323 tmp_mode = iattr->ia_mode;
324 if (tmp_mode & (S_ISVTX)) {
325 if (is_root_handle(inode)) {
326 /*
327 * allow sticky bit to be set on root (since
328 * it shows up that way by default anyhow),
329 * but don't show it to the server
330 */
331 tmp_mode -= S_ISVTX;
332 } else {
333 gossip_debug(GOSSIP_UTILS_DEBUG,
334 "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
335 return -EINVAL;
336 }
337 }
338
339 if (tmp_mode & (S_ISUID)) {
340 gossip_debug(GOSSIP_UTILS_DEBUG,
341 "Attempting to set setuid bit (not supported); returning EINVAL.\n");
342 return -EINVAL;
343 }
344
345 attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
346 attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
347 }
348
349 return 0;
350 }
351
352 /*
353 * issues a orangefs getattr request and fills in the appropriate inode
354 * attributes if successful. returns 0 on success; -errno otherwise
355 */
356 int orangefs_inode_getattr(struct inode *inode, __u32 getattr_mask)
357 {
358 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
359 struct orangefs_kernel_op_s *new_op;
360 int ret = -EINVAL;
361
362 gossip_debug(GOSSIP_UTILS_DEBUG,
363 "%s: called on inode %pU\n",
364 __func__,
365 get_khandle_from_ino(inode));
366
367 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
368 if (!new_op)
369 return -ENOMEM;
370 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
371 new_op->upcall.req.getattr.mask = getattr_mask;
372
373 ret = service_operation(new_op, __func__,
374 get_interruptible_flag(inode));
375 if (ret != 0)
376 goto out;
377
378 if (copy_attributes_to_inode(inode,
379 &new_op->downcall.resp.getattr.attributes,
380 new_op->downcall.resp.getattr.link_target)) {
381 gossip_err("%s: failed to copy attributes\n", __func__);
382 ret = -ENOENT;
383 goto out;
384 }
385
386 /*
387 * Store blksize in orangefs specific part of inode structure; we are
388 * only going to use this to report to stat to make sure it doesn't
389 * perturb any inode related code paths.
390 */
391 if (new_op->downcall.resp.getattr.attributes.objtype ==
392 ORANGEFS_TYPE_METAFILE) {
393 orangefs_inode->blksize =
394 new_op->downcall.resp.getattr.attributes.blksize;
395 } else {
396 /* mimic behavior of generic_fillattr() for other types. */
397 orangefs_inode->blksize = (1 << inode->i_blkbits);
398
399 }
400
401 out:
402 gossip_debug(GOSSIP_UTILS_DEBUG,
403 "Getattr on handle %pU, "
404 "fsid %d\n (inode ct = %d) returned %d\n",
405 &orangefs_inode->refn.khandle,
406 orangefs_inode->refn.fs_id,
407 (int)atomic_read(&inode->i_count),
408 ret);
409
410 op_release(new_op);
411 return ret;
412 }
413
414 /*
415 * issues a orangefs setattr request to make sure the new attribute values
416 * take effect if successful. returns 0 on success; -errno otherwise
417 */
418 int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
419 {
420 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
421 struct orangefs_kernel_op_s *new_op;
422 int ret;
423
424 new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
425 if (!new_op)
426 return -ENOMEM;
427
428 new_op->upcall.req.setattr.refn = orangefs_inode->refn;
429 ret = copy_attributes_from_inode(inode,
430 &new_op->upcall.req.setattr.attributes,
431 iattr);
432 if (ret >= 0) {
433 ret = service_operation(new_op, __func__,
434 get_interruptible_flag(inode));
435
436 gossip_debug(GOSSIP_UTILS_DEBUG,
437 "orangefs_inode_setattr: returning %d\n",
438 ret);
439 }
440
441 op_release(new_op);
442
443 /*
444 * successful setattr should clear the atime, mtime and
445 * ctime flags.
446 */
447 if (ret == 0) {
448 ClearAtimeFlag(orangefs_inode);
449 ClearMtimeFlag(orangefs_inode);
450 ClearCtimeFlag(orangefs_inode);
451 ClearModeFlag(orangefs_inode);
452 }
453
454 return ret;
455 }
456
457 int orangefs_flush_inode(struct inode *inode)
458 {
459 /*
460 * If it is a dirty inode, this function gets called.
461 * Gather all the information that needs to be setattr'ed
462 * Right now, this will only be used for mode, atime, mtime
463 * and/or ctime.
464 */
465 struct iattr wbattr;
466 int ret;
467 int mtime_flag;
468 int ctime_flag;
469 int atime_flag;
470 int mode_flag;
471 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
472
473 memset(&wbattr, 0, sizeof(wbattr));
474
475 /*
476 * check inode flags up front, and clear them if they are set. This
477 * will prevent multiple processes from all trying to flush the same
478 * inode if they call close() simultaneously
479 */
480 mtime_flag = MtimeFlag(orangefs_inode);
481 ClearMtimeFlag(orangefs_inode);
482 ctime_flag = CtimeFlag(orangefs_inode);
483 ClearCtimeFlag(orangefs_inode);
484 atime_flag = AtimeFlag(orangefs_inode);
485 ClearAtimeFlag(orangefs_inode);
486 mode_flag = ModeFlag(orangefs_inode);
487 ClearModeFlag(orangefs_inode);
488
489 /* -- Lazy atime,mtime and ctime update --
490 * Note: all times are dictated by server in the new scheme
491 * and not by the clients
492 *
493 * Also mode updates are being handled now..
494 */
495
496 if (mtime_flag)
497 wbattr.ia_valid |= ATTR_MTIME;
498 if (ctime_flag)
499 wbattr.ia_valid |= ATTR_CTIME;
500 if (atime_flag)
501 wbattr.ia_valid |= ATTR_ATIME;
502
503 if (mode_flag) {
504 wbattr.ia_mode = inode->i_mode;
505 wbattr.ia_valid |= ATTR_MODE;
506 }
507
508 gossip_debug(GOSSIP_UTILS_DEBUG,
509 "*********** orangefs_flush_inode: %pU "
510 "(ia_valid %d)\n",
511 get_khandle_from_ino(inode),
512 wbattr.ia_valid);
513 if (wbattr.ia_valid == 0) {
514 gossip_debug(GOSSIP_UTILS_DEBUG,
515 "orangefs_flush_inode skipping setattr()\n");
516 return 0;
517 }
518
519 gossip_debug(GOSSIP_UTILS_DEBUG,
520 "orangefs_flush_inode (%pU) writing mode %o\n",
521 get_khandle_from_ino(inode),
522 inode->i_mode);
523
524 ret = orangefs_inode_setattr(inode, &wbattr);
525
526 return ret;
527 }
528
529 int orangefs_unmount_sb(struct super_block *sb)
530 {
531 int ret = -EINVAL;
532 struct orangefs_kernel_op_s *new_op = NULL;
533
534 gossip_debug(GOSSIP_UTILS_DEBUG,
535 "orangefs_unmount_sb called on sb %p\n",
536 sb);
537
538 new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
539 if (!new_op)
540 return -ENOMEM;
541 new_op->upcall.req.fs_umount.id = ORANGEFS_SB(sb)->id;
542 new_op->upcall.req.fs_umount.fs_id = ORANGEFS_SB(sb)->fs_id;
543 strncpy(new_op->upcall.req.fs_umount.orangefs_config_server,
544 ORANGEFS_SB(sb)->devname,
545 ORANGEFS_MAX_SERVER_ADDR_LEN);
546
547 gossip_debug(GOSSIP_UTILS_DEBUG,
548 "Attempting ORANGEFS Unmount via host %s\n",
549 new_op->upcall.req.fs_umount.orangefs_config_server);
550
551 ret = service_operation(new_op, "orangefs_fs_umount", 0);
552
553 gossip_debug(GOSSIP_UTILS_DEBUG,
554 "orangefs_unmount: got return value of %d\n", ret);
555 if (ret)
556 sb = ERR_PTR(ret);
557 else
558 ORANGEFS_SB(sb)->mount_pending = 1;
559
560 op_release(new_op);
561 return ret;
562 }
563
564 /*
565 * NOTE: on successful cancellation, be sure to return -EINTR, as
566 * that's the return value the caller expects
567 */
568 int orangefs_cancel_op_in_progress(__u64 tag)
569 {
570 int ret = -EINVAL;
571 struct orangefs_kernel_op_s *new_op = NULL;
572
573 gossip_debug(GOSSIP_UTILS_DEBUG,
574 "orangefs_cancel_op_in_progress called on tag %llu\n",
575 llu(tag));
576
577 new_op = op_alloc(ORANGEFS_VFS_OP_CANCEL);
578 if (!new_op)
579 return -ENOMEM;
580 new_op->upcall.req.cancel.op_tag = tag;
581
582 gossip_debug(GOSSIP_UTILS_DEBUG,
583 "Attempting ORANGEFS operation cancellation of tag %llu\n",
584 llu(new_op->upcall.req.cancel.op_tag));
585
586 ret = service_operation(new_op, "orangefs_cancel", ORANGEFS_OP_CANCELLATION);
587
588 gossip_debug(GOSSIP_UTILS_DEBUG,
589 "orangefs_cancel_op_in_progress: got return value of %d\n",
590 ret);
591
592 op_release(new_op);
593 return ret;
594 }
595
596 void orangefs_make_bad_inode(struct inode *inode)
597 {
598 if (is_root_handle(inode)) {
599 /*
600 * if this occurs, the pvfs2-client-core was killed but we
601 * can't afford to lose the inode operations and such
602 * associated with the root handle in any case.
603 */
604 gossip_debug(GOSSIP_UTILS_DEBUG,
605 "*** NOT making bad root inode %pU\n",
606 get_khandle_from_ino(inode));
607 } else {
608 gossip_debug(GOSSIP_UTILS_DEBUG,
609 "*** making bad inode %pU\n",
610 get_khandle_from_ino(inode));
611 make_bad_inode(inode);
612 }
613 }
614
615 /* Block all blockable signals... */
616 void orangefs_block_signals(sigset_t *orig_sigset)
617 {
618 sigset_t mask;
619
620 /*
621 * Initialize all entries in the signal set to the
622 * inverse of the given mask.
623 */
624 siginitsetinv(&mask, sigmask(SIGKILL));
625
626 /* Block 'em Danno... */
627 sigprocmask(SIG_BLOCK, &mask, orig_sigset);
628 }
629
630 /* set the signal mask to the given template... */
631 void orangefs_set_signals(sigset_t *sigset)
632 {
633 sigprocmask(SIG_SETMASK, sigset, NULL);
634 }
635
636 /*
637 * The following is a very dirty hack that is now a permanent part of the
638 * ORANGEFS protocol. See protocol.h for more error definitions.
639 */
640
641 /* The order matches include/orangefs-types.h in the OrangeFS source. */
642 static int PINT_errno_mapping[] = {
643 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
644 EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
645 EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
646 ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
647 EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
648 EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
649 ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
650 EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
651 ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
652 EACCES, ECONNRESET, ERANGE
653 };
654
655 int orangefs_normalize_to_errno(__s32 error_code)
656 {
657 __u32 i;
658
659 /* Success */
660 if (error_code == 0) {
661 return 0;
662 /*
663 * This shouldn't ever happen. If it does it should be fixed on the
664 * server.
665 */
666 } else if (error_code > 0) {
667 gossip_err("orangefs: error status receieved.\n");
668 gossip_err("orangefs: assuming error code is inverted.\n");
669 error_code = -error_code;
670 }
671
672 /*
673 * XXX: This is very bad since error codes from ORANGEFS may not be
674 * suitable for return into userspace.
675 */
676
677 /*
678 * Convert ORANGEFS error values into errno values suitable for return
679 * from the kernel.
680 */
681 if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
682 if (((-error_code) &
683 (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
684 ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
685 /*
686 * cancellation error codes generally correspond to
687 * a timeout from the client's perspective
688 */
689 error_code = -ETIMEDOUT;
690 } else {
691 /* assume a default error code */
692 gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
693 error_code = -EINVAL;
694 }
695
696 /* Convert ORANGEFS encoded errno values into regular errno values. */
697 } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
698 i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
699 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
700 error_code = -PINT_errno_mapping[i];
701 else
702 error_code = -EINVAL;
703
704 /*
705 * Only ORANGEFS protocol error codes should ever come here. Otherwise
706 * there is a bug somewhere.
707 */
708 } else {
709 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
710 }
711 return error_code;
712 }
713
714 #define NUM_MODES 11
715 __s32 ORANGEFS_util_translate_mode(int mode)
716 {
717 int ret = 0;
718 int i = 0;
719 static int modes[NUM_MODES] = {
720 S_IXOTH, S_IWOTH, S_IROTH,
721 S_IXGRP, S_IWGRP, S_IRGRP,
722 S_IXUSR, S_IWUSR, S_IRUSR,
723 S_ISGID, S_ISUID
724 };
725 static int orangefs_modes[NUM_MODES] = {
726 ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
727 ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
728 ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
729 ORANGEFS_G_SGID, ORANGEFS_U_SUID
730 };
731
732 for (i = 0; i < NUM_MODES; i++)
733 if (mode & modes[i])
734 ret |= orangefs_modes[i];
735
736 return ret;
737 }
738 #undef NUM_MODES
739
740 /*
741 * After obtaining a string representation of the client's debug
742 * keywords and their associated masks, this function is called to build an
743 * array of these values.
744 */
745 int orangefs_prepare_cdm_array(char *debug_array_string)
746 {
747 int i;
748 int rc = -EINVAL;
749 char *cds_head = NULL;
750 char *cds_delimiter = NULL;
751 int keyword_len = 0;
752
753 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
754
755 /*
756 * figure out how many elements the cdm_array needs.
757 */
758 for (i = 0; i < strlen(debug_array_string); i++)
759 if (debug_array_string[i] == '\n')
760 cdm_element_count++;
761
762 if (!cdm_element_count) {
763 pr_info("No elements in client debug array string!\n");
764 goto out;
765 }
766
767 cdm_array =
768 kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
769 GFP_KERNEL);
770 if (!cdm_array) {
771 pr_info("malloc failed for cdm_array!\n");
772 rc = -ENOMEM;
773 goto out;
774 }
775
776 cds_head = debug_array_string;
777
778 for (i = 0; i < cdm_element_count; i++) {
779 cds_delimiter = strchr(cds_head, '\n');
780 *cds_delimiter = '\0';
781
782 keyword_len = strcspn(cds_head, " ");
783
784 cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
785 if (!cdm_array[i].keyword) {
786 rc = -ENOMEM;
787 goto out;
788 }
789
790 sscanf(cds_head,
791 "%s %llx %llx",
792 cdm_array[i].keyword,
793 (unsigned long long *)&(cdm_array[i].mask1),
794 (unsigned long long *)&(cdm_array[i].mask2));
795
796 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
797 client_verbose_index = i;
798
799 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
800 client_all_index = i;
801
802 cds_head = cds_delimiter + 1;
803 }
804
805 rc = cdm_element_count;
806
807 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
808
809 out:
810
811 return rc;
812
813 }
814
815 /*
816 * /sys/kernel/debug/orangefs/debug-help can be catted to
817 * see all the available kernel and client debug keywords.
818 *
819 * When the kernel boots, we have no idea what keywords the
820 * client supports, nor their associated masks.
821 *
822 * We pass through this function once at boot and stamp a
823 * boilerplate "we don't know" message for the client in the
824 * debug-help file. We pass through here again when the client
825 * starts and then we can fill out the debug-help file fully.
826 *
827 * The client might be restarted any number of times between
828 * reboots, we only build the debug-help file the first time.
829 */
830 int orangefs_prepare_debugfs_help_string(int at_boot)
831 {
832 int rc = -EINVAL;
833 int i;
834 int byte_count = 0;
835 char *client_title = "Client Debug Keywords:\n";
836 char *kernel_title = "Kernel Debug Keywords:\n";
837
838 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
839
840 if (at_boot) {
841 byte_count += strlen(HELP_STRING_UNINITIALIZED);
842 client_title = HELP_STRING_UNINITIALIZED;
843 } else {
844 /*
845 * fill the client keyword/mask array and remember
846 * how many elements there were.
847 */
848 cdm_element_count =
849 orangefs_prepare_cdm_array(client_debug_array_string);
850 if (cdm_element_count <= 0)
851 goto out;
852
853 /* Count the bytes destined for debug_help_string. */
854 byte_count += strlen(client_title);
855
856 for (i = 0; i < cdm_element_count; i++) {
857 byte_count += strlen(cdm_array[i].keyword + 2);
858 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
859 pr_info("%s: overflow 1!\n", __func__);
860 goto out;
861 }
862 }
863
864 gossip_debug(GOSSIP_UTILS_DEBUG,
865 "%s: cdm_element_count:%d:\n",
866 __func__,
867 cdm_element_count);
868 }
869
870 byte_count += strlen(kernel_title);
871 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
872 byte_count +=
873 strlen(s_kmod_keyword_mask_map[i].keyword + 2);
874 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
875 pr_info("%s: overflow 2!\n", __func__);
876 goto out;
877 }
878 }
879
880 /* build debug_help_string. */
881 debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
882 if (!debug_help_string) {
883 rc = -ENOMEM;
884 goto out;
885 }
886
887 strcat(debug_help_string, client_title);
888
889 if (!at_boot) {
890 for (i = 0; i < cdm_element_count; i++) {
891 strcat(debug_help_string, "\t");
892 strcat(debug_help_string, cdm_array[i].keyword);
893 strcat(debug_help_string, "\n");
894 }
895 }
896
897 strcat(debug_help_string, "\n");
898 strcat(debug_help_string, kernel_title);
899
900 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
901 strcat(debug_help_string, "\t");
902 strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
903 strcat(debug_help_string, "\n");
904 }
905
906 rc = 0;
907
908 out:
909
910 return rc;
911
912 }
913
914 /*
915 * kernel = type 0
916 * client = type 1
917 */
918 void debug_mask_to_string(void *mask, int type)
919 {
920 int i;
921 int len = 0;
922 char *debug_string;
923 int element_count = 0;
924
925 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
926
927 if (type) {
928 debug_string = client_debug_string;
929 element_count = cdm_element_count;
930 } else {
931 debug_string = kernel_debug_string;
932 element_count = num_kmod_keyword_mask_map;
933 }
934
935 memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
936
937 /*
938 * Some keywords, like "all" or "verbose", are amalgams of
939 * numerous other keywords. Make a special check for those
940 * before grinding through the whole mask only to find out
941 * later...
942 */
943 if (check_amalgam_keyword(mask, type))
944 goto out;
945
946 /* Build the debug string. */
947 for (i = 0; i < element_count; i++)
948 if (type)
949 do_c_string(mask, i);
950 else
951 do_k_string(mask, i);
952
953 len = strlen(debug_string);
954
955 if ((len) && (type))
956 client_debug_string[len - 1] = '\0';
957 else if (len)
958 kernel_debug_string[len - 1] = '\0';
959 else if (type)
960 strcpy(client_debug_string, "none");
961 else
962 strcpy(kernel_debug_string, "none");
963
964 out:
965 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
966
967 return;
968
969 }
970
971 void do_k_string(void *k_mask, int index)
972 {
973 __u64 *mask = (__u64 *) k_mask;
974
975 if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
976 goto out;
977
978 if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
979 if ((strlen(kernel_debug_string) +
980 strlen(s_kmod_keyword_mask_map[index].keyword))
981 < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
982 strcat(kernel_debug_string,
983 s_kmod_keyword_mask_map[index].keyword);
984 strcat(kernel_debug_string, ",");
985 } else {
986 gossip_err("%s: overflow!\n", __func__);
987 strcpy(kernel_debug_string, ORANGEFS_ALL);
988 goto out;
989 }
990 }
991
992 out:
993
994 return;
995 }
996
997 void do_c_string(void *c_mask, int index)
998 {
999 struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
1000
1001 if (keyword_is_amalgam(cdm_array[index].keyword))
1002 goto out;
1003
1004 if ((mask->mask1 & cdm_array[index].mask1) ||
1005 (mask->mask2 & cdm_array[index].mask2)) {
1006 if ((strlen(client_debug_string) +
1007 strlen(cdm_array[index].keyword) + 1)
1008 < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
1009 strcat(client_debug_string,
1010 cdm_array[index].keyword);
1011 strcat(client_debug_string, ",");
1012 } else {
1013 gossip_err("%s: overflow!\n", __func__);
1014 strcpy(client_debug_string, ORANGEFS_ALL);
1015 goto out;
1016 }
1017 }
1018 out:
1019 return;
1020 }
1021
1022 int keyword_is_amalgam(char *keyword)
1023 {
1024 int rc = 0;
1025
1026 if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
1027 rc = 1;
1028
1029 return rc;
1030 }
1031
1032 /*
1033 * kernel = type 0
1034 * client = type 1
1035 *
1036 * return 1 if we found an amalgam.
1037 */
1038 int check_amalgam_keyword(void *mask, int type)
1039 {
1040 __u64 *k_mask;
1041 struct client_debug_mask *c_mask;
1042 int k_all_index = num_kmod_keyword_mask_map - 1;
1043 int rc = 0;
1044
1045 if (type) {
1046 c_mask = (struct client_debug_mask *) mask;
1047
1048 if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
1049 (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
1050 strcpy(client_debug_string, ORANGEFS_ALL);
1051 rc = 1;
1052 goto out;
1053 }
1054
1055 if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
1056 (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
1057 strcpy(client_debug_string, ORANGEFS_VERBOSE);
1058 rc = 1;
1059 goto out;
1060 }
1061
1062 } else {
1063 k_mask = (__u64 *) mask;
1064
1065 if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
1066 strcpy(kernel_debug_string, ORANGEFS_ALL);
1067 rc = 1;
1068 goto out;
1069 }
1070 }
1071
1072 out:
1073
1074 return rc;
1075 }
1076
1077 /*
1078 * kernel = type 0
1079 * client = type 1
1080 */
1081 void debug_string_to_mask(char *debug_string, void *mask, int type)
1082 {
1083 char *unchecked_keyword;
1084 int i;
1085 char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
1086 char *original_pointer;
1087 int element_count = 0;
1088 struct client_debug_mask *c_mask;
1089 __u64 *k_mask;
1090
1091 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1092
1093 if (type) {
1094 c_mask = (struct client_debug_mask *)mask;
1095 element_count = cdm_element_count;
1096 } else {
1097 k_mask = (__u64 *)mask;
1098 *k_mask = 0;
1099 element_count = num_kmod_keyword_mask_map;
1100 }
1101
1102 original_pointer = strsep_fodder;
1103 while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
1104 if (strlen(unchecked_keyword)) {
1105 for (i = 0; i < element_count; i++)
1106 if (type)
1107 do_c_mask(i,
1108 unchecked_keyword,
1109 &c_mask);
1110 else
1111 do_k_mask(i,
1112 unchecked_keyword,
1113 &k_mask);
1114 }
1115
1116 kfree(original_pointer);
1117 }
1118
1119 void do_c_mask(int i,
1120 char *unchecked_keyword,
1121 struct client_debug_mask **sane_mask)
1122 {
1123
1124 if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
1125 (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
1126 (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
1127 }
1128 }
1129
1130 void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
1131 {
1132
1133 if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
1134 **sane_mask = (**sane_mask) |
1135 s_kmod_keyword_mask_map[i].mask_val;
1136 }
This page took 0.063887 seconds and 4 git commands to generate.