Orangefs: kernel client part 4
[deliverable/linux.git] / fs / orangefs / pvfs2-utils.c
CommitLineData
f7be4ee0
MM
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 "pvfs2-kernel.h"
8#include "pvfs2-dev-proto.h"
9#include "pvfs2-bufmap.h"
10
11__s32 fsid_of_op(struct pvfs2_kernel_op_s *op)
12{
13 __s32 fsid = PVFS_FS_ID_NULL;
14
15 if (op) {
16 switch (op->upcall.type) {
17 case PVFS2_VFS_OP_FILE_IO:
18 fsid = op->upcall.req.io.refn.fs_id;
19 break;
20 case PVFS2_VFS_OP_LOOKUP:
21 fsid = op->upcall.req.lookup.parent_refn.fs_id;
22 break;
23 case PVFS2_VFS_OP_CREATE:
24 fsid = op->upcall.req.create.parent_refn.fs_id;
25 break;
26 case PVFS2_VFS_OP_GETATTR:
27 fsid = op->upcall.req.getattr.refn.fs_id;
28 break;
29 case PVFS2_VFS_OP_REMOVE:
30 fsid = op->upcall.req.remove.parent_refn.fs_id;
31 break;
32 case PVFS2_VFS_OP_MKDIR:
33 fsid = op->upcall.req.mkdir.parent_refn.fs_id;
34 break;
35 case PVFS2_VFS_OP_READDIR:
36 fsid = op->upcall.req.readdir.refn.fs_id;
37 break;
38 case PVFS2_VFS_OP_SETATTR:
39 fsid = op->upcall.req.setattr.refn.fs_id;
40 break;
41 case PVFS2_VFS_OP_SYMLINK:
42 fsid = op->upcall.req.sym.parent_refn.fs_id;
43 break;
44 case PVFS2_VFS_OP_RENAME:
45 fsid = op->upcall.req.rename.old_parent_refn.fs_id;
46 break;
47 case PVFS2_VFS_OP_STATFS:
48 fsid = op->upcall.req.statfs.fs_id;
49 break;
50 case PVFS2_VFS_OP_TRUNCATE:
51 fsid = op->upcall.req.truncate.refn.fs_id;
52 break;
53 case PVFS2_VFS_OP_MMAP_RA_FLUSH:
54 fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
55 break;
56 case PVFS2_VFS_OP_FS_UMOUNT:
57 fsid = op->upcall.req.fs_umount.fs_id;
58 break;
59 case PVFS2_VFS_OP_GETXATTR:
60 fsid = op->upcall.req.getxattr.refn.fs_id;
61 break;
62 case PVFS2_VFS_OP_SETXATTR:
63 fsid = op->upcall.req.setxattr.refn.fs_id;
64 break;
65 case PVFS2_VFS_OP_LISTXATTR:
66 fsid = op->upcall.req.listxattr.refn.fs_id;
67 break;
68 case PVFS2_VFS_OP_REMOVEXATTR:
69 fsid = op->upcall.req.removexattr.refn.fs_id;
70 break;
71 case PVFS2_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
81static void pvfs2_set_inode_flags(struct inode *inode,
82 struct PVFS_sys_attr_s *attrs)
83{
84 if (attrs->flags & PVFS_IMMUTABLE_FL)
85 inode->i_flags |= S_IMMUTABLE;
86 else
87 inode->i_flags &= ~S_IMMUTABLE;
88
89 if (attrs->flags & PVFS_APPEND_FL)
90 inode->i_flags |= S_APPEND;
91 else
92 inode->i_flags &= ~S_APPEND;
93
94 if (attrs->flags & PVFS_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 */
102static int copy_attributes_to_inode(struct inode *inode,
103 struct PVFS_sys_attr_s *attrs,
104 char *symname)
105{
106 int ret = -1;
107 int perm_mode = 0;
108 struct pvfs2_inode_s *pvfs2_inode = PVFS2_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 == PVFS_TYPE_METAFILE ? "file" :
131 attrs->objtype == PVFS_TYPE_DIRECTORY ? "directory" :
132 attrs->objtype == PVFS_TYPE_SYMLINK ? "symlink" :
133 "invalid/unknown");
134
135 switch (attrs->objtype) {
136 case PVFS_TYPE_METAFILE:
137 pvfs2_set_inode_flags(inode, attrs);
138 if (attrs->mask & PVFS_ATTR_SYS_SIZE) {
139 inode_size = (loff_t) attrs->size;
140 rounded_up_size =
141 (inode_size + (4096 - (inode_size % 4096)));
142
143 pvfs2_lock_inode(inode);
144 inode->i_bytes = inode_size;
145 inode->i_blocks =
146 (unsigned long)(rounded_up_size / 512);
147 pvfs2_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 PVFS_TYPE_SYMLINK:
159 if (symname != NULL) {
160 inode->i_size = (loff_t) strlen(symname);
161 break;
162 }
163 /*FALLTHRU*/
164 default:
165 pvfs2_lock_inode(inode);
166 inode->i_bytes = PAGE_CACHE_SIZE;
167 inode->i_blocks = (unsigned long)(PAGE_CACHE_SIZE / 512);
168 pvfs2_unlock_inode(inode);
169
170 inode->i_size = PAGE_CACHE_SIZE;
171 break;
172 }
173
174 inode->i_uid = make_kuid(&init_user_ns, attrs->owner);
175 inode->i_gid = make_kgid(&init_user_ns, attrs->group);
176 inode->i_atime.tv_sec = (time_t) attrs->atime;
177 inode->i_mtime.tv_sec = (time_t) attrs->mtime;
178 inode->i_ctime.tv_sec = (time_t) attrs->ctime;
179 inode->i_atime.tv_nsec = 0;
180 inode->i_mtime.tv_nsec = 0;
181 inode->i_ctime.tv_nsec = 0;
182
183 if (attrs->perms & PVFS_O_EXECUTE)
184 perm_mode |= S_IXOTH;
185 if (attrs->perms & PVFS_O_WRITE)
186 perm_mode |= S_IWOTH;
187 if (attrs->perms & PVFS_O_READ)
188 perm_mode |= S_IROTH;
189
190 if (attrs->perms & PVFS_G_EXECUTE)
191 perm_mode |= S_IXGRP;
192 if (attrs->perms & PVFS_G_WRITE)
193 perm_mode |= S_IWGRP;
194 if (attrs->perms & PVFS_G_READ)
195 perm_mode |= S_IRGRP;
196
197 if (attrs->perms & PVFS_U_EXECUTE)
198 perm_mode |= S_IXUSR;
199 if (attrs->perms & PVFS_U_WRITE)
200 perm_mode |= S_IWUSR;
201 if (attrs->perms & PVFS_U_READ)
202 perm_mode |= S_IRUSR;
203
204 if (attrs->perms & PVFS_G_SGID)
205 perm_mode |= S_ISGID;
206 if (attrs->perms & PVFS_U_SUID)
207 perm_mode |= S_ISUID;
208
209 inode->i_mode = perm_mode;
210
211 if (is_root_handle(inode)) {
212 /* special case: mark the root inode as sticky */
213 inode->i_mode |= S_ISVTX;
214 gossip_debug(GOSSIP_UTILS_DEBUG,
215 "Marking inode %pU as sticky\n",
216 get_khandle_from_ino(inode));
217 }
218
219 switch (attrs->objtype) {
220 case PVFS_TYPE_METAFILE:
221 inode->i_mode |= S_IFREG;
222 ret = 0;
223 break;
224 case PVFS_TYPE_DIRECTORY:
225 inode->i_mode |= S_IFDIR;
226 /* NOTE: we have no good way to keep nlink consistent
227 * for directories across clients; keep constant at 1.
228 * Why 1? If we go with 2, then find(1) gets confused
229 * and won't work properly withouth the -noleaf option
230 */
231 set_nlink(inode, 1);
232 ret = 0;
233 break;
234 case PVFS_TYPE_SYMLINK:
235 inode->i_mode |= S_IFLNK;
236
237 /* copy link target to inode private data */
238 if (pvfs2_inode && symname) {
239 strncpy(pvfs2_inode->link_target,
240 symname,
241 PVFS_NAME_MAX);
242 gossip_debug(GOSSIP_UTILS_DEBUG,
243 "Copied attr link target %s\n",
244 pvfs2_inode->link_target);
245 }
246 gossip_debug(GOSSIP_UTILS_DEBUG,
247 "symlink mode %o\n",
248 inode->i_mode);
249 ret = 0;
250 break;
251 default:
252 gossip_err("pvfs2: copy_attributes_to_inode: got invalid attribute type %x\n",
253 attrs->objtype);
254 }
255
256 gossip_debug(GOSSIP_UTILS_DEBUG,
257 "pvfs2: copy_attributes_to_inode: setting i_mode to %o, i_size to %lu\n",
258 inode->i_mode,
259 (unsigned long)i_size_read(inode));
260
261 return ret;
262}
263
264/*
265 * NOTE: in kernel land, we never use the sys_attr->link_target for
266 * anything, so don't bother copying it into the sys_attr object here.
267 */
268static inline int copy_attributes_from_inode(struct inode *inode,
269 struct PVFS_sys_attr_s *attrs,
270 struct iattr *iattr)
271{
272 umode_t tmp_mode;
273
274 if (!iattr || !inode || !attrs) {
275 gossip_err("NULL iattr (%p), inode (%p), attrs (%p) "
276 "in copy_attributes_from_inode!\n",
277 iattr,
278 inode,
279 attrs);
280 return -EINVAL;
281 }
282 /*
283 * We need to be careful to only copy the attributes out of the
284 * iattr object that we know are valid.
285 */
286 attrs->mask = 0;
287 if (iattr->ia_valid & ATTR_UID) {
288 attrs->owner = from_kuid(current_user_ns(), iattr->ia_uid);
289 attrs->mask |= PVFS_ATTR_SYS_UID;
290 gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
291 }
292 if (iattr->ia_valid & ATTR_GID) {
293 attrs->group = from_kgid(current_user_ns(), iattr->ia_gid);
294 attrs->mask |= PVFS_ATTR_SYS_GID;
295 gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
296 }
297
298 if (iattr->ia_valid & ATTR_ATIME) {
299 attrs->mask |= PVFS_ATTR_SYS_ATIME;
300 if (iattr->ia_valid & ATTR_ATIME_SET) {
301 attrs->atime =
302 pvfs2_convert_time_field((void *)&iattr->ia_atime);
303 attrs->mask |= PVFS_ATTR_SYS_ATIME_SET;
304 }
305 }
306 if (iattr->ia_valid & ATTR_MTIME) {
307 attrs->mask |= PVFS_ATTR_SYS_MTIME;
308 if (iattr->ia_valid & ATTR_MTIME_SET) {
309 attrs->mtime =
310 pvfs2_convert_time_field((void *)&iattr->ia_mtime);
311 attrs->mask |= PVFS_ATTR_SYS_MTIME_SET;
312 }
313 }
314 if (iattr->ia_valid & ATTR_CTIME)
315 attrs->mask |= PVFS_ATTR_SYS_CTIME;
316
317 /*
318 * PVFS2 cannot set size with a setattr operation. Probably not likely
319 * to be requested through the VFS, but just in case, don't worry about
320 * ATTR_SIZE
321 */
322
323 if (iattr->ia_valid & ATTR_MODE) {
324 tmp_mode = iattr->ia_mode;
325 if (tmp_mode & (S_ISVTX)) {
326 if (is_root_handle(inode)) {
327 /*
328 * allow sticky bit to be set on root (since
329 * it shows up that way by default anyhow),
330 * but don't show it to the server
331 */
332 tmp_mode -= S_ISVTX;
333 } else {
334 gossip_debug(GOSSIP_UTILS_DEBUG,
335 "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
336 return -EINVAL;
337 }
338 }
339
340 if (tmp_mode & (S_ISUID)) {
341 gossip_debug(GOSSIP_UTILS_DEBUG,
342 "Attempting to set setuid bit (not supported); returning EINVAL.\n");
343 return -EINVAL;
344 }
345
346 attrs->perms = PVFS_util_translate_mode(tmp_mode);
347 attrs->mask |= PVFS_ATTR_SYS_PERM;
348 }
349
350 return 0;
351}
352
353/*
354 * issues a pvfs2 getattr request and fills in the appropriate inode
355 * attributes if successful. returns 0 on success; -errno otherwise
356 */
357int pvfs2_inode_getattr(struct inode *inode, __u32 getattr_mask)
358{
359 struct pvfs2_inode_s *pvfs2_inode = PVFS2_I(inode);
360 struct pvfs2_kernel_op_s *new_op;
361 int ret = -EINVAL;
362
363 gossip_debug(GOSSIP_UTILS_DEBUG,
364 "%s: called on inode %pU\n",
365 __func__,
366 get_khandle_from_ino(inode));
367
368 new_op = op_alloc(PVFS2_VFS_OP_GETATTR);
369 if (!new_op)
370 return -ENOMEM;
371 new_op->upcall.req.getattr.refn = pvfs2_inode->refn;
372 new_op->upcall.req.getattr.mask = getattr_mask;
373
374 ret = service_operation(new_op, __func__,
375 get_interruptible_flag(inode));
376 if (ret != 0)
377 goto out;
378
379 if (copy_attributes_to_inode(inode,
380 &new_op->downcall.resp.getattr.attributes,
381 new_op->downcall.resp.getattr.link_target)) {
382 gossip_err("%s: failed to copy attributes\n", __func__);
383 ret = -ENOENT;
384 goto out;
385 }
386
387 /*
388 * Store blksize in pvfs2 specific part of inode structure; we are
389 * only going to use this to report to stat to make sure it doesn't
390 * perturb any inode related code paths.
391 */
392 if (new_op->downcall.resp.getattr.attributes.objtype ==
393 PVFS_TYPE_METAFILE) {
394 pvfs2_inode->blksize =
395 new_op->downcall.resp.getattr.attributes.blksize;
396 } else {
397 /* mimic behavior of generic_fillattr() for other types. */
398 pvfs2_inode->blksize = (1 << inode->i_blkbits);
399
400 }
401
402out:
403 gossip_debug(GOSSIP_UTILS_DEBUG,
404 "Getattr on handle %pU, "
405 "fsid %d\n (inode ct = %d) returned %d\n",
406 &pvfs2_inode->refn.khandle,
407 pvfs2_inode->refn.fs_id,
408 (int)atomic_read(&inode->i_count),
409 ret);
410
411 op_release(new_op);
412 return ret;
413}
414
415/*
416 * issues a pvfs2 setattr request to make sure the new attribute values
417 * take effect if successful. returns 0 on success; -errno otherwise
418 */
419int pvfs2_inode_setattr(struct inode *inode, struct iattr *iattr)
420{
421 struct pvfs2_inode_s *pvfs2_inode = PVFS2_I(inode);
422 struct pvfs2_kernel_op_s *new_op;
423 int ret;
424
425 new_op = op_alloc(PVFS2_VFS_OP_SETATTR);
426 if (!new_op)
427 return -ENOMEM;
428
429 new_op->upcall.req.setattr.refn = pvfs2_inode->refn;
430 ret = copy_attributes_from_inode(inode,
431 &new_op->upcall.req.setattr.attributes,
432 iattr);
433 if (ret < 0) {
434 op_release(new_op);
435 return ret;
436 }
437
438 ret = service_operation(new_op, __func__,
439 get_interruptible_flag(inode));
440
441 gossip_debug(GOSSIP_UTILS_DEBUG,
442 "pvfs2_inode_setattr: returning %d\n",
443 ret);
444
445 /* when request is serviced properly, free req op struct */
446 op_release(new_op);
447
448 /*
449 * successful setattr should clear the atime, mtime and
450 * ctime flags.
451 */
452 if (ret == 0) {
453 ClearAtimeFlag(pvfs2_inode);
454 ClearMtimeFlag(pvfs2_inode);
455 ClearCtimeFlag(pvfs2_inode);
456 ClearModeFlag(pvfs2_inode);
457 }
458
459 return ret;
460}
461
462int pvfs2_flush_inode(struct inode *inode)
463{
464 /*
465 * If it is a dirty inode, this function gets called.
466 * Gather all the information that needs to be setattr'ed
467 * Right now, this will only be used for mode, atime, mtime
468 * and/or ctime.
469 */
470 struct iattr wbattr;
471 int ret;
472 int mtime_flag;
473 int ctime_flag;
474 int atime_flag;
475 int mode_flag;
476 struct pvfs2_inode_s *pvfs2_inode = PVFS2_I(inode);
477
478 memset(&wbattr, 0, sizeof(wbattr));
479
480 /*
481 * check inode flags up front, and clear them if they are set. This
482 * will prevent multiple processes from all trying to flush the same
483 * inode if they call close() simultaneously
484 */
485 mtime_flag = MtimeFlag(pvfs2_inode);
486 ClearMtimeFlag(pvfs2_inode);
487 ctime_flag = CtimeFlag(pvfs2_inode);
488 ClearCtimeFlag(pvfs2_inode);
489 atime_flag = AtimeFlag(pvfs2_inode);
490 ClearAtimeFlag(pvfs2_inode);
491 mode_flag = ModeFlag(pvfs2_inode);
492 ClearModeFlag(pvfs2_inode);
493
494 /* -- Lazy atime,mtime and ctime update --
495 * Note: all times are dictated by server in the new scheme
496 * and not by the clients
497 *
498 * Also mode updates are being handled now..
499 */
500
501 if (mtime_flag)
502 wbattr.ia_valid |= ATTR_MTIME;
503 if (ctime_flag)
504 wbattr.ia_valid |= ATTR_CTIME;
505 if (atime_flag)
506 wbattr.ia_valid |= ATTR_ATIME;
507
508 if (mode_flag) {
509 wbattr.ia_mode = inode->i_mode;
510 wbattr.ia_valid |= ATTR_MODE;
511 }
512
513 gossip_debug(GOSSIP_UTILS_DEBUG,
514 "*********** pvfs2_flush_inode: %pU "
515 "(ia_valid %d)\n",
516 get_khandle_from_ino(inode),
517 wbattr.ia_valid);
518 if (wbattr.ia_valid == 0) {
519 gossip_debug(GOSSIP_UTILS_DEBUG,
520 "pvfs2_flush_inode skipping setattr()\n");
521 return 0;
522 }
523
524 gossip_debug(GOSSIP_UTILS_DEBUG,
525 "pvfs2_flush_inode (%pU) writing mode %o\n",
526 get_khandle_from_ino(inode),
527 inode->i_mode);
528
529 ret = pvfs2_inode_setattr(inode, &wbattr);
530
531 return ret;
532}
533
534int pvfs2_unmount_sb(struct super_block *sb)
535{
536 int ret = -EINVAL;
537 struct pvfs2_kernel_op_s *new_op = NULL;
538
539 gossip_debug(GOSSIP_UTILS_DEBUG,
540 "pvfs2_unmount_sb called on sb %p\n",
541 sb);
542
543 new_op = op_alloc(PVFS2_VFS_OP_FS_UMOUNT);
544 if (!new_op)
545 return -ENOMEM;
546 new_op->upcall.req.fs_umount.id = PVFS2_SB(sb)->id;
547 new_op->upcall.req.fs_umount.fs_id = PVFS2_SB(sb)->fs_id;
548 strncpy(new_op->upcall.req.fs_umount.pvfs2_config_server,
549 PVFS2_SB(sb)->devname,
550 PVFS_MAX_SERVER_ADDR_LEN);
551
552 gossip_debug(GOSSIP_UTILS_DEBUG,
553 "Attempting PVFS2 Unmount via host %s\n",
554 new_op->upcall.req.fs_umount.pvfs2_config_server);
555
556 ret = service_operation(new_op, "pvfs2_fs_umount", 0);
557
558 gossip_debug(GOSSIP_UTILS_DEBUG,
559 "pvfs2_unmount: got return value of %d\n", ret);
560 if (ret)
561 sb = ERR_PTR(ret);
562 else
563 PVFS2_SB(sb)->mount_pending = 1;
564
565 op_release(new_op);
566 return ret;
567}
568
569/*
570 * NOTE: on successful cancellation, be sure to return -EINTR, as
571 * that's the return value the caller expects
572 */
573int pvfs2_cancel_op_in_progress(__u64 tag)
574{
575 int ret = -EINVAL;
576 struct pvfs2_kernel_op_s *new_op = NULL;
577
578 gossip_debug(GOSSIP_UTILS_DEBUG,
579 "pvfs2_cancel_op_in_progress called on tag %llu\n",
580 llu(tag));
581
582 new_op = op_alloc(PVFS2_VFS_OP_CANCEL);
583 if (!new_op)
584 return -ENOMEM;
585 new_op->upcall.req.cancel.op_tag = tag;
586
587 gossip_debug(GOSSIP_UTILS_DEBUG,
588 "Attempting PVFS2 operation cancellation of tag %llu\n",
589 llu(new_op->upcall.req.cancel.op_tag));
590
591 ret = service_operation(new_op, "pvfs2_cancel", PVFS2_OP_CANCELLATION);
592
593 gossip_debug(GOSSIP_UTILS_DEBUG,
594 "pvfs2_cancel_op_in_progress: got return value of %d\n",
595 ret);
596
597 op_release(new_op);
598 return ret;
599}
600
601void pvfs2_op_initialize(struct pvfs2_kernel_op_s *op)
602{
603 if (op) {
604 spin_lock(&op->lock);
605 op->io_completed = 0;
606
607 op->upcall.type = PVFS2_VFS_OP_INVALID;
608 op->downcall.type = PVFS2_VFS_OP_INVALID;
609 op->downcall.status = -1;
610
611 op->op_state = OP_VFS_STATE_UNKNOWN;
612 op->tag = 0;
613 spin_unlock(&op->lock);
614 }
615}
616
617void pvfs2_make_bad_inode(struct inode *inode)
618{
619 if (is_root_handle(inode)) {
620 /*
621 * if this occurs, the pvfs2-client-core was killed but we
622 * can't afford to lose the inode operations and such
623 * associated with the root handle in any case.
624 */
625 gossip_debug(GOSSIP_UTILS_DEBUG,
626 "*** NOT making bad root inode %pU\n",
627 get_khandle_from_ino(inode));
628 } else {
629 gossip_debug(GOSSIP_UTILS_DEBUG,
630 "*** making bad inode %pU\n",
631 get_khandle_from_ino(inode));
632 make_bad_inode(inode);
633 }
634}
635
636/* this code is based on linux/net/sunrpc/clnt.c:rpc_clnt_sigmask */
637void mask_blocked_signals(sigset_t *orig_sigset)
638{
639 unsigned long sigallow = sigmask(SIGKILL);
640 unsigned long irqflags = 0;
641 struct k_sigaction *action = pvfs2_current_sigaction;
642
643 sigallow |= ((action[SIGINT - 1].sa.sa_handler == SIG_DFL) ?
644 sigmask(SIGINT) :
645 0);
646 sigallow |= ((action[SIGQUIT - 1].sa.sa_handler == SIG_DFL) ?
647 sigmask(SIGQUIT) :
648 0);
649
650 spin_lock_irqsave(&pvfs2_current_signal_lock, irqflags);
651 *orig_sigset = current->blocked;
652 siginitsetinv(&current->blocked, sigallow & ~orig_sigset->sig[0]);
653 recalc_sigpending();
654 spin_unlock_irqrestore(&pvfs2_current_signal_lock, irqflags);
655}
656
657/* this code is based on linux/net/sunrpc/clnt.c:rpc_clnt_sigunmask */
658void unmask_blocked_signals(sigset_t *orig_sigset)
659{
660 unsigned long irqflags = 0;
661
662 spin_lock_irqsave(&pvfs2_current_signal_lock, irqflags);
663 current->blocked = *orig_sigset;
664 recalc_sigpending();
665 spin_unlock_irqrestore(&pvfs2_current_signal_lock, irqflags);
666}
667
668__u64 pvfs2_convert_time_field(void *time_ptr)
669{
670 __u64 pvfs2_time;
671 struct timespec *tspec = (struct timespec *)time_ptr;
672
673 pvfs2_time = (__u64) ((time_t) tspec->tv_sec);
674 return pvfs2_time;
675}
676
677/* macro defined in include/pvfs2-types.h */
678DECLARE_ERRNO_MAPPING_AND_FN();
679
680int pvfs2_normalize_to_errno(__s32 error_code)
681{
682 if (error_code > 0) {
683 gossip_err("pvfs2: error status receieved.\n");
684 gossip_err("pvfs2: assuming error code is inverted.\n");
685 error_code = -error_code;
686 }
687
688 /* convert any error codes that are in pvfs2 format */
689 if (IS_PVFS_NON_ERRNO_ERROR(-error_code)) {
690 if (PVFS_NON_ERRNO_ERROR_CODE(-error_code) == PVFS_ECANCEL) {
691 /*
692 * cancellation error codes generally correspond to
693 * a timeout from the client's perspective
694 */
695 error_code = -ETIMEDOUT;
696 } else {
697 /* assume a default error code */
698 gossip_err("pvfs2: warning: got error code without errno equivalent: %d.\n",
699 error_code);
700 error_code = -EINVAL;
701 }
702 } else if (IS_PVFS_ERROR(-error_code)) {
703 error_code = -PVFS_ERROR_TO_ERRNO(-error_code);
704 }
705 return error_code;
706}
707
708#define NUM_MODES 11
709__s32 PVFS_util_translate_mode(int mode)
710{
711 int ret = 0;
712 int i = 0;
713 static int modes[NUM_MODES] = {
714 S_IXOTH, S_IWOTH, S_IROTH,
715 S_IXGRP, S_IWGRP, S_IRGRP,
716 S_IXUSR, S_IWUSR, S_IRUSR,
717 S_ISGID, S_ISUID
718 };
719 static int pvfs2_modes[NUM_MODES] = {
720 PVFS_O_EXECUTE, PVFS_O_WRITE, PVFS_O_READ,
721 PVFS_G_EXECUTE, PVFS_G_WRITE, PVFS_G_READ,
722 PVFS_U_EXECUTE, PVFS_U_WRITE, PVFS_U_READ,
723 PVFS_G_SGID, PVFS_U_SUID
724 };
725
726 for (i = 0; i < NUM_MODES; i++)
727 if (mode & modes[i])
728 ret |= pvfs2_modes[i];
729
730 return ret;
731}
732#undef NUM_MODES
733
734/*
735 * After obtaining a string representation of the client's debug
736 * keywords and their associated masks, this function is called to build an
737 * array of these values.
738 */
739int orangefs_prepare_cdm_array(char *debug_array_string)
740{
741 int i;
742 int rc = -EINVAL;
743 char *cds_head = NULL;
744 char *cds_delimiter = NULL;
745 int keyword_len = 0;
746
747 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
748
749 /*
750 * figure out how many elements the cdm_array needs.
751 */
752 for (i = 0; i < strlen(debug_array_string); i++)
753 if (debug_array_string[i] == '\n')
754 cdm_element_count++;
755
756 if (!cdm_element_count) {
757 pr_info("No elements in client debug array string!\n");
758 goto out;
759 }
760
761 cdm_array =
762 kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
763 GFP_KERNEL);
764 if (!cdm_array) {
765 pr_info("malloc failed for cdm_array!\n");
766 rc = -ENOMEM;
767 goto out;
768 }
769
770 cds_head = debug_array_string;
771
772 for (i = 0; i < cdm_element_count; i++) {
773 cds_delimiter = strchr(cds_head, '\n');
774 *cds_delimiter = '\0';
775
776 keyword_len = strcspn(cds_head, " ");
777
778 cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
779 if (!cdm_array[i].keyword) {
780 rc = -ENOMEM;
781 goto out;
782 }
783
784 sscanf(cds_head,
785 "%s %llx %llx",
786 cdm_array[i].keyword,
787 (unsigned long long *)&(cdm_array[i].mask1),
788 (unsigned long long *)&(cdm_array[i].mask2));
789
790 if (!strcmp(cdm_array[i].keyword, PVFS2_VERBOSE))
791 client_verbose_index = i;
792
793 if (!strcmp(cdm_array[i].keyword, PVFS2_ALL))
794 client_all_index = i;
795
796 cds_head = cds_delimiter + 1;
797 }
798
799 rc = cdm_element_count;
800
801 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
802
803out:
804
805 return rc;
806
807}
808
809/*
810 * /sys/kernel/debug/orangefs/debug-help can be catted to
811 * see all the available kernel and client debug keywords.
812 *
813 * When the kernel boots, we have no idea what keywords the
814 * client supports, nor their associated masks.
815 *
816 * We pass through this function once at boot and stamp a
817 * boilerplate "we don't know" message for the client in the
818 * debug-help file. We pass through here again when the client
819 * starts and then we can fill out the debug-help file fully.
820 *
821 * The client might be restarted any number of times between
822 * reboots, we only build the debug-help file the first time.
823 */
824int orangefs_prepare_debugfs_help_string(int at_boot)
825{
826 int rc = -EINVAL;
827 int i;
828 int byte_count = 0;
829 char *client_title = "Client Debug Keywords:\n";
830 char *kernel_title = "Kernel Debug Keywords:\n";
831
832 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
833
834 if (at_boot) {
835 byte_count += strlen(HELP_STRING_UNINITIALIZED);
836 client_title = HELP_STRING_UNINITIALIZED;
837 } else {
838 /*
839 * fill the client keyword/mask array and remember
840 * how many elements there were.
841 */
842 cdm_element_count =
843 orangefs_prepare_cdm_array(client_debug_array_string);
844 if (cdm_element_count <= 0)
845 goto out;
846
847 /* Count the bytes destined for debug_help_string. */
848 byte_count += strlen(client_title);
849
850 for (i = 0; i < cdm_element_count; i++) {
851 byte_count += strlen(cdm_array[i].keyword + 2);
852 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
853 pr_info("%s: overflow 1!\n", __func__);
854 goto out;
855 }
856 }
857
858 gossip_debug(GOSSIP_UTILS_DEBUG,
859 "%s: cdm_element_count:%d:\n",
860 __func__,
861 cdm_element_count);
862 }
863
864 byte_count += strlen(kernel_title);
865 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
866 byte_count +=
867 strlen(s_kmod_keyword_mask_map[i].keyword + 2);
868 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
869 pr_info("%s: overflow 2!\n", __func__);
870 goto out;
871 }
872 }
873
874 /* build debug_help_string. */
875 debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
876 if (!debug_help_string) {
877 rc = -ENOMEM;
878 goto out;
879 }
880
881 strcat(debug_help_string, client_title);
882
883 if (!at_boot) {
884 for (i = 0; i < cdm_element_count; i++) {
885 strcat(debug_help_string, "\t");
886 strcat(debug_help_string, cdm_array[i].keyword);
887 strcat(debug_help_string, "\n");
888 }
889 }
890
891 strcat(debug_help_string, "\n");
892 strcat(debug_help_string, kernel_title);
893
894 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
895 strcat(debug_help_string, "\t");
896 strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
897 strcat(debug_help_string, "\n");
898 }
899
900 rc = 0;
901
902out:
903
904 return rc;
905
906}
907
908/*
909 * kernel = type 0
910 * client = type 1
911 */
912void debug_mask_to_string(void *mask, int type)
913{
914 int i;
915 int len = 0;
916 char *debug_string;
917 int element_count = 0;
918
919 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
920
921 if (type) {
922 debug_string = client_debug_string;
923 element_count = cdm_element_count;
924 } else {
925 debug_string = kernel_debug_string;
926 element_count = num_kmod_keyword_mask_map;
927 }
928
929 memset(debug_string, 0, PVFS2_MAX_DEBUG_STRING_LEN);
930
931 /*
932 * Some keywords, like "all" or "verbose", are amalgams of
933 * numerous other keywords. Make a special check for those
934 * before grinding through the whole mask only to find out
935 * later...
936 */
937 if (check_amalgam_keyword(mask, type))
938 goto out;
939
940 /* Build the debug string. */
941 for (i = 0; i < element_count; i++)
942 if (type)
943 do_c_string(mask, i);
944 else
945 do_k_string(mask, i);
946
947 len = strlen(debug_string);
948
949 if ((len) && (type))
950 client_debug_string[len - 1] = '\0';
951 else if (len)
952 kernel_debug_string[len - 1] = '\0';
953 else if (type)
954 strcpy(client_debug_string, "none");
955 else
956 strcpy(kernel_debug_string, "none");
957
958out:
959gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
960
961 return;
962
963}
964
965void do_k_string(void *k_mask, int index)
966{
967 __u64 *mask = (__u64 *) k_mask;
968
969 if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
970 goto out;
971
972 if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
973 if ((strlen(kernel_debug_string) +
974 strlen(s_kmod_keyword_mask_map[index].keyword))
975 < PVFS2_MAX_DEBUG_STRING_LEN - 1) {
976 strcat(kernel_debug_string,
977 s_kmod_keyword_mask_map[index].keyword);
978 strcat(kernel_debug_string, ",");
979 } else {
980 gossip_err("%s: overflow!\n", __func__);
981 strcpy(kernel_debug_string, PVFS2_ALL);
982 goto out;
983 }
984 }
985
986out:
987
988 return;
989}
990
991void do_c_string(void *c_mask, int index)
992{
993 struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
994
995 if (keyword_is_amalgam(cdm_array[index].keyword))
996 goto out;
997
998 if ((mask->mask1 & cdm_array[index].mask1) ||
999 (mask->mask2 & cdm_array[index].mask2)) {
1000 if ((strlen(client_debug_string) +
1001 strlen(cdm_array[index].keyword) + 1)
1002 < PVFS2_MAX_DEBUG_STRING_LEN - 2) {
1003 strcat(client_debug_string,
1004 cdm_array[index].keyword);
1005 strcat(client_debug_string, ",");
1006 } else {
1007 gossip_err("%s: overflow!\n", __func__);
1008 strcpy(client_debug_string, PVFS2_ALL);
1009 goto out;
1010 }
1011 }
1012out:
1013 return;
1014}
1015
1016int keyword_is_amalgam(char *keyword)
1017{
1018 int rc = 0;
1019
1020 if ((!strcmp(keyword, PVFS2_ALL)) || (!strcmp(keyword, PVFS2_VERBOSE)))
1021 rc = 1;
1022
1023 return rc;
1024}
1025
1026/*
1027 * kernel = type 0
1028 * client = type 1
1029 *
1030 * return 1 if we found an amalgam.
1031 */
1032int check_amalgam_keyword(void *mask, int type)
1033{
1034 __u64 *k_mask;
1035 struct client_debug_mask *c_mask;
1036 int k_all_index = num_kmod_keyword_mask_map - 1;
1037 int rc = 0;
1038
1039 if (type) {
1040 c_mask = (struct client_debug_mask *) mask;
1041
1042 if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
1043 (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
1044 strcpy(client_debug_string, PVFS2_ALL);
1045 rc = 1;
1046 goto out;
1047 }
1048
1049 if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
1050 (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
1051 strcpy(client_debug_string, PVFS2_VERBOSE);
1052 rc = 1;
1053 goto out;
1054 }
1055
1056 } else {
1057 k_mask = (__u64 *) mask;
1058
1059 if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
1060 strcpy(kernel_debug_string, PVFS2_ALL);
1061 rc = 1;
1062 goto out;
1063 }
1064 }
1065
1066out:
1067
1068 return rc;
1069}
1070
1071/*
1072 * kernel = type 0
1073 * client = type 1
1074 */
1075void debug_string_to_mask(char *debug_string, void *mask, int type)
1076{
1077 char *unchecked_keyword;
1078 int i;
1079 char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
1080 int element_count = 0;
1081 struct client_debug_mask *c_mask;
1082 __u64 *k_mask;
1083
1084 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1085
1086 if (type) {
1087 c_mask = (struct client_debug_mask *)mask;
1088 element_count = cdm_element_count;
1089 } else {
1090 k_mask = (__u64 *)mask;
1091 *k_mask = 0;
1092 element_count = num_kmod_keyword_mask_map;
1093 }
1094
1095 while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
1096 if (strlen(unchecked_keyword)) {
1097 for (i = 0; i < element_count; i++)
1098 if (type)
1099 do_c_mask(i,
1100 unchecked_keyword,
1101 &c_mask);
1102 else
1103 do_k_mask(i,
1104 unchecked_keyword,
1105 &k_mask);
1106 }
1107
1108 kfree(strsep_fodder);
1109}
1110
1111void do_c_mask(int i,
1112 char *unchecked_keyword,
1113 struct client_debug_mask **sane_mask)
1114{
1115
1116 if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
1117 (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
1118 (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
1119 }
1120}
1121
1122void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
1123{
1124
1125 if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
1126 **sane_mask = (**sane_mask) |
1127 s_kmod_keyword_mask_map[i].mask_val;
1128}
This page took 0.06403 seconds and 5 git commands to generate.