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