orangefs: hopefully saner op refcounting and locking
[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_op_initialize(struct orangefs_kernel_op_s *op)
597 {
598 if (op) {
599 spin_lock(&op->lock);
600 op->io_completed = 0;
601
602 op->upcall.type = ORANGEFS_VFS_OP_INVALID;
603 op->downcall.type = ORANGEFS_VFS_OP_INVALID;
604 op->downcall.status = -1;
605
606 op->op_state = OP_VFS_STATE_UNKNOWN;
607 op->tag = 0;
608 spin_unlock(&op->lock);
609 }
610 }
611
612 void orangefs_make_bad_inode(struct inode *inode)
613 {
614 if (is_root_handle(inode)) {
615 /*
616 * if this occurs, the pvfs2-client-core was killed but we
617 * can't afford to lose the inode operations and such
618 * associated with the root handle in any case.
619 */
620 gossip_debug(GOSSIP_UTILS_DEBUG,
621 "*** NOT making bad root inode %pU\n",
622 get_khandle_from_ino(inode));
623 } else {
624 gossip_debug(GOSSIP_UTILS_DEBUG,
625 "*** making bad inode %pU\n",
626 get_khandle_from_ino(inode));
627 make_bad_inode(inode);
628 }
629 }
630
631 /* Block all blockable signals... */
632 void orangefs_block_signals(sigset_t *orig_sigset)
633 {
634 sigset_t mask;
635
636 /*
637 * Initialize all entries in the signal set to the
638 * inverse of the given mask.
639 */
640 siginitsetinv(&mask, sigmask(SIGKILL));
641
642 /* Block 'em Danno... */
643 sigprocmask(SIG_BLOCK, &mask, orig_sigset);
644 }
645
646 /* set the signal mask to the given template... */
647 void orangefs_set_signals(sigset_t *sigset)
648 {
649 sigprocmask(SIG_SETMASK, sigset, NULL);
650 }
651
652 /*
653 * The following is a very dirty hack that is now a permanent part of the
654 * ORANGEFS protocol. See protocol.h for more error definitions.
655 */
656
657 /* The order matches include/orangefs-types.h in the OrangeFS source. */
658 static int PINT_errno_mapping[] = {
659 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
660 EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
661 EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
662 ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
663 EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
664 EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
665 ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
666 EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
667 ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
668 EACCES, ECONNRESET, ERANGE
669 };
670
671 int orangefs_normalize_to_errno(__s32 error_code)
672 {
673 __u32 i;
674
675 /* Success */
676 if (error_code == 0) {
677 return 0;
678 /*
679 * This shouldn't ever happen. If it does it should be fixed on the
680 * server.
681 */
682 } else if (error_code > 0) {
683 gossip_err("orangefs: error status receieved.\n");
684 gossip_err("orangefs: assuming error code is inverted.\n");
685 error_code = -error_code;
686 }
687
688 /*
689 * XXX: This is very bad since error codes from ORANGEFS may not be
690 * suitable for return into userspace.
691 */
692
693 /*
694 * Convert ORANGEFS error values into errno values suitable for return
695 * from the kernel.
696 */
697 if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
698 if (((-error_code) &
699 (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
700 ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
701 /*
702 * cancellation error codes generally correspond to
703 * a timeout from the client's perspective
704 */
705 error_code = -ETIMEDOUT;
706 } else {
707 /* assume a default error code */
708 gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
709 error_code = -EINVAL;
710 }
711
712 /* Convert ORANGEFS encoded errno values into regular errno values. */
713 } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
714 i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
715 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
716 error_code = -PINT_errno_mapping[i];
717 else
718 error_code = -EINVAL;
719
720 /*
721 * Only ORANGEFS protocol error codes should ever come here. Otherwise
722 * there is a bug somewhere.
723 */
724 } else {
725 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
726 }
727 return error_code;
728 }
729
730 #define NUM_MODES 11
731 __s32 ORANGEFS_util_translate_mode(int mode)
732 {
733 int ret = 0;
734 int i = 0;
735 static int modes[NUM_MODES] = {
736 S_IXOTH, S_IWOTH, S_IROTH,
737 S_IXGRP, S_IWGRP, S_IRGRP,
738 S_IXUSR, S_IWUSR, S_IRUSR,
739 S_ISGID, S_ISUID
740 };
741 static int orangefs_modes[NUM_MODES] = {
742 ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
743 ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
744 ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
745 ORANGEFS_G_SGID, ORANGEFS_U_SUID
746 };
747
748 for (i = 0; i < NUM_MODES; i++)
749 if (mode & modes[i])
750 ret |= orangefs_modes[i];
751
752 return ret;
753 }
754 #undef NUM_MODES
755
756 /*
757 * After obtaining a string representation of the client's debug
758 * keywords and their associated masks, this function is called to build an
759 * array of these values.
760 */
761 int orangefs_prepare_cdm_array(char *debug_array_string)
762 {
763 int i;
764 int rc = -EINVAL;
765 char *cds_head = NULL;
766 char *cds_delimiter = NULL;
767 int keyword_len = 0;
768
769 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
770
771 /*
772 * figure out how many elements the cdm_array needs.
773 */
774 for (i = 0; i < strlen(debug_array_string); i++)
775 if (debug_array_string[i] == '\n')
776 cdm_element_count++;
777
778 if (!cdm_element_count) {
779 pr_info("No elements in client debug array string!\n");
780 goto out;
781 }
782
783 cdm_array =
784 kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
785 GFP_KERNEL);
786 if (!cdm_array) {
787 pr_info("malloc failed for cdm_array!\n");
788 rc = -ENOMEM;
789 goto out;
790 }
791
792 cds_head = debug_array_string;
793
794 for (i = 0; i < cdm_element_count; i++) {
795 cds_delimiter = strchr(cds_head, '\n');
796 *cds_delimiter = '\0';
797
798 keyword_len = strcspn(cds_head, " ");
799
800 cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
801 if (!cdm_array[i].keyword) {
802 rc = -ENOMEM;
803 goto out;
804 }
805
806 sscanf(cds_head,
807 "%s %llx %llx",
808 cdm_array[i].keyword,
809 (unsigned long long *)&(cdm_array[i].mask1),
810 (unsigned long long *)&(cdm_array[i].mask2));
811
812 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
813 client_verbose_index = i;
814
815 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
816 client_all_index = i;
817
818 cds_head = cds_delimiter + 1;
819 }
820
821 rc = cdm_element_count;
822
823 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
824
825 out:
826
827 return rc;
828
829 }
830
831 /*
832 * /sys/kernel/debug/orangefs/debug-help can be catted to
833 * see all the available kernel and client debug keywords.
834 *
835 * When the kernel boots, we have no idea what keywords the
836 * client supports, nor their associated masks.
837 *
838 * We pass through this function once at boot and stamp a
839 * boilerplate "we don't know" message for the client in the
840 * debug-help file. We pass through here again when the client
841 * starts and then we can fill out the debug-help file fully.
842 *
843 * The client might be restarted any number of times between
844 * reboots, we only build the debug-help file the first time.
845 */
846 int orangefs_prepare_debugfs_help_string(int at_boot)
847 {
848 int rc = -EINVAL;
849 int i;
850 int byte_count = 0;
851 char *client_title = "Client Debug Keywords:\n";
852 char *kernel_title = "Kernel Debug Keywords:\n";
853
854 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
855
856 if (at_boot) {
857 byte_count += strlen(HELP_STRING_UNINITIALIZED);
858 client_title = HELP_STRING_UNINITIALIZED;
859 } else {
860 /*
861 * fill the client keyword/mask array and remember
862 * how many elements there were.
863 */
864 cdm_element_count =
865 orangefs_prepare_cdm_array(client_debug_array_string);
866 if (cdm_element_count <= 0)
867 goto out;
868
869 /* Count the bytes destined for debug_help_string. */
870 byte_count += strlen(client_title);
871
872 for (i = 0; i < cdm_element_count; i++) {
873 byte_count += strlen(cdm_array[i].keyword + 2);
874 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
875 pr_info("%s: overflow 1!\n", __func__);
876 goto out;
877 }
878 }
879
880 gossip_debug(GOSSIP_UTILS_DEBUG,
881 "%s: cdm_element_count:%d:\n",
882 __func__,
883 cdm_element_count);
884 }
885
886 byte_count += strlen(kernel_title);
887 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
888 byte_count +=
889 strlen(s_kmod_keyword_mask_map[i].keyword + 2);
890 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
891 pr_info("%s: overflow 2!\n", __func__);
892 goto out;
893 }
894 }
895
896 /* build debug_help_string. */
897 debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
898 if (!debug_help_string) {
899 rc = -ENOMEM;
900 goto out;
901 }
902
903 strcat(debug_help_string, client_title);
904
905 if (!at_boot) {
906 for (i = 0; i < cdm_element_count; i++) {
907 strcat(debug_help_string, "\t");
908 strcat(debug_help_string, cdm_array[i].keyword);
909 strcat(debug_help_string, "\n");
910 }
911 }
912
913 strcat(debug_help_string, "\n");
914 strcat(debug_help_string, kernel_title);
915
916 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
917 strcat(debug_help_string, "\t");
918 strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
919 strcat(debug_help_string, "\n");
920 }
921
922 rc = 0;
923
924 out:
925
926 return rc;
927
928 }
929
930 /*
931 * kernel = type 0
932 * client = type 1
933 */
934 void debug_mask_to_string(void *mask, int type)
935 {
936 int i;
937 int len = 0;
938 char *debug_string;
939 int element_count = 0;
940
941 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
942
943 if (type) {
944 debug_string = client_debug_string;
945 element_count = cdm_element_count;
946 } else {
947 debug_string = kernel_debug_string;
948 element_count = num_kmod_keyword_mask_map;
949 }
950
951 memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
952
953 /*
954 * Some keywords, like "all" or "verbose", are amalgams of
955 * numerous other keywords. Make a special check for those
956 * before grinding through the whole mask only to find out
957 * later...
958 */
959 if (check_amalgam_keyword(mask, type))
960 goto out;
961
962 /* Build the debug string. */
963 for (i = 0; i < element_count; i++)
964 if (type)
965 do_c_string(mask, i);
966 else
967 do_k_string(mask, i);
968
969 len = strlen(debug_string);
970
971 if ((len) && (type))
972 client_debug_string[len - 1] = '\0';
973 else if (len)
974 kernel_debug_string[len - 1] = '\0';
975 else if (type)
976 strcpy(client_debug_string, "none");
977 else
978 strcpy(kernel_debug_string, "none");
979
980 out:
981 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
982
983 return;
984
985 }
986
987 void do_k_string(void *k_mask, int index)
988 {
989 __u64 *mask = (__u64 *) k_mask;
990
991 if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
992 goto out;
993
994 if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
995 if ((strlen(kernel_debug_string) +
996 strlen(s_kmod_keyword_mask_map[index].keyword))
997 < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
998 strcat(kernel_debug_string,
999 s_kmod_keyword_mask_map[index].keyword);
1000 strcat(kernel_debug_string, ",");
1001 } else {
1002 gossip_err("%s: overflow!\n", __func__);
1003 strcpy(kernel_debug_string, ORANGEFS_ALL);
1004 goto out;
1005 }
1006 }
1007
1008 out:
1009
1010 return;
1011 }
1012
1013 void do_c_string(void *c_mask, int index)
1014 {
1015 struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
1016
1017 if (keyword_is_amalgam(cdm_array[index].keyword))
1018 goto out;
1019
1020 if ((mask->mask1 & cdm_array[index].mask1) ||
1021 (mask->mask2 & cdm_array[index].mask2)) {
1022 if ((strlen(client_debug_string) +
1023 strlen(cdm_array[index].keyword) + 1)
1024 < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
1025 strcat(client_debug_string,
1026 cdm_array[index].keyword);
1027 strcat(client_debug_string, ",");
1028 } else {
1029 gossip_err("%s: overflow!\n", __func__);
1030 strcpy(client_debug_string, ORANGEFS_ALL);
1031 goto out;
1032 }
1033 }
1034 out:
1035 return;
1036 }
1037
1038 int keyword_is_amalgam(char *keyword)
1039 {
1040 int rc = 0;
1041
1042 if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
1043 rc = 1;
1044
1045 return rc;
1046 }
1047
1048 /*
1049 * kernel = type 0
1050 * client = type 1
1051 *
1052 * return 1 if we found an amalgam.
1053 */
1054 int check_amalgam_keyword(void *mask, int type)
1055 {
1056 __u64 *k_mask;
1057 struct client_debug_mask *c_mask;
1058 int k_all_index = num_kmod_keyword_mask_map - 1;
1059 int rc = 0;
1060
1061 if (type) {
1062 c_mask = (struct client_debug_mask *) mask;
1063
1064 if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
1065 (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
1066 strcpy(client_debug_string, ORANGEFS_ALL);
1067 rc = 1;
1068 goto out;
1069 }
1070
1071 if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
1072 (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
1073 strcpy(client_debug_string, ORANGEFS_VERBOSE);
1074 rc = 1;
1075 goto out;
1076 }
1077
1078 } else {
1079 k_mask = (__u64 *) mask;
1080
1081 if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
1082 strcpy(kernel_debug_string, ORANGEFS_ALL);
1083 rc = 1;
1084 goto out;
1085 }
1086 }
1087
1088 out:
1089
1090 return rc;
1091 }
1092
1093 /*
1094 * kernel = type 0
1095 * client = type 1
1096 */
1097 void debug_string_to_mask(char *debug_string, void *mask, int type)
1098 {
1099 char *unchecked_keyword;
1100 int i;
1101 char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
1102 char *original_pointer;
1103 int element_count = 0;
1104 struct client_debug_mask *c_mask;
1105 __u64 *k_mask;
1106
1107 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1108
1109 if (type) {
1110 c_mask = (struct client_debug_mask *)mask;
1111 element_count = cdm_element_count;
1112 } else {
1113 k_mask = (__u64 *)mask;
1114 *k_mask = 0;
1115 element_count = num_kmod_keyword_mask_map;
1116 }
1117
1118 original_pointer = strsep_fodder;
1119 while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
1120 if (strlen(unchecked_keyword)) {
1121 for (i = 0; i < element_count; i++)
1122 if (type)
1123 do_c_mask(i,
1124 unchecked_keyword,
1125 &c_mask);
1126 else
1127 do_k_mask(i,
1128 unchecked_keyword,
1129 &k_mask);
1130 }
1131
1132 kfree(original_pointer);
1133 }
1134
1135 void do_c_mask(int i,
1136 char *unchecked_keyword,
1137 struct client_debug_mask **sane_mask)
1138 {
1139
1140 if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
1141 (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
1142 (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
1143 }
1144 }
1145
1146 void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
1147 {
1148
1149 if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
1150 **sane_mask = (**sane_mask) |
1151 s_kmod_keyword_mask_map[i].mask_val;
1152 }
This page took 0.054201 seconds and 5 git commands to generate.