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