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