License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-block.git] / fs / orangefs / orangefs-utils.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) 2001 Clemson University and The University of Chicago
4  *
5  * See COPYING in top-level directory.
6  */
7 #include "protocol.h"
8 #include "orangefs-kernel.h"
9 #include "orangefs-dev-proto.h"
10 #include "orangefs-bufmap.h"
11
12 __s32 fsid_of_op(struct orangefs_kernel_op_s *op)
13 {
14         __s32 fsid = ORANGEFS_FS_ID_NULL;
15
16         if (op) {
17                 switch (op->upcall.type) {
18                 case ORANGEFS_VFS_OP_FILE_IO:
19                         fsid = op->upcall.req.io.refn.fs_id;
20                         break;
21                 case ORANGEFS_VFS_OP_LOOKUP:
22                         fsid = op->upcall.req.lookup.parent_refn.fs_id;
23                         break;
24                 case ORANGEFS_VFS_OP_CREATE:
25                         fsid = op->upcall.req.create.parent_refn.fs_id;
26                         break;
27                 case ORANGEFS_VFS_OP_GETATTR:
28                         fsid = op->upcall.req.getattr.refn.fs_id;
29                         break;
30                 case ORANGEFS_VFS_OP_REMOVE:
31                         fsid = op->upcall.req.remove.parent_refn.fs_id;
32                         break;
33                 case ORANGEFS_VFS_OP_MKDIR:
34                         fsid = op->upcall.req.mkdir.parent_refn.fs_id;
35                         break;
36                 case ORANGEFS_VFS_OP_READDIR:
37                         fsid = op->upcall.req.readdir.refn.fs_id;
38                         break;
39                 case ORANGEFS_VFS_OP_SETATTR:
40                         fsid = op->upcall.req.setattr.refn.fs_id;
41                         break;
42                 case ORANGEFS_VFS_OP_SYMLINK:
43                         fsid = op->upcall.req.sym.parent_refn.fs_id;
44                         break;
45                 case ORANGEFS_VFS_OP_RENAME:
46                         fsid = op->upcall.req.rename.old_parent_refn.fs_id;
47                         break;
48                 case ORANGEFS_VFS_OP_STATFS:
49                         fsid = op->upcall.req.statfs.fs_id;
50                         break;
51                 case ORANGEFS_VFS_OP_TRUNCATE:
52                         fsid = op->upcall.req.truncate.refn.fs_id;
53                         break;
54                 case ORANGEFS_VFS_OP_RA_FLUSH:
55                         fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
56                         break;
57                 case ORANGEFS_VFS_OP_FS_UMOUNT:
58                         fsid = op->upcall.req.fs_umount.fs_id;
59                         break;
60                 case ORANGEFS_VFS_OP_GETXATTR:
61                         fsid = op->upcall.req.getxattr.refn.fs_id;
62                         break;
63                 case ORANGEFS_VFS_OP_SETXATTR:
64                         fsid = op->upcall.req.setxattr.refn.fs_id;
65                         break;
66                 case ORANGEFS_VFS_OP_LISTXATTR:
67                         fsid = op->upcall.req.listxattr.refn.fs_id;
68                         break;
69                 case ORANGEFS_VFS_OP_REMOVEXATTR:
70                         fsid = op->upcall.req.removexattr.refn.fs_id;
71                         break;
72                 case ORANGEFS_VFS_OP_FSYNC:
73                         fsid = op->upcall.req.fsync.refn.fs_id;
74                         break;
75                 default:
76                         break;
77                 }
78         }
79         return fsid;
80 }
81
82 static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
83 {
84         int flags = 0;
85         if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
86                 flags |= S_IMMUTABLE;
87         else
88                 flags &= ~S_IMMUTABLE;
89         if (attrs->flags & ORANGEFS_APPEND_FL)
90                 flags |= S_APPEND;
91         else
92                 flags &= ~S_APPEND;
93         if (attrs->flags & ORANGEFS_NOATIME_FL)
94                 flags |= S_NOATIME;
95         else
96                 flags &= ~S_NOATIME;
97         return flags;
98 }
99
100 static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
101 {
102         int perm_mode = 0;
103
104         if (attrs->perms & ORANGEFS_O_EXECUTE)
105                 perm_mode |= S_IXOTH;
106         if (attrs->perms & ORANGEFS_O_WRITE)
107                 perm_mode |= S_IWOTH;
108         if (attrs->perms & ORANGEFS_O_READ)
109                 perm_mode |= S_IROTH;
110
111         if (attrs->perms & ORANGEFS_G_EXECUTE)
112                 perm_mode |= S_IXGRP;
113         if (attrs->perms & ORANGEFS_G_WRITE)
114                 perm_mode |= S_IWGRP;
115         if (attrs->perms & ORANGEFS_G_READ)
116                 perm_mode |= S_IRGRP;
117
118         if (attrs->perms & ORANGEFS_U_EXECUTE)
119                 perm_mode |= S_IXUSR;
120         if (attrs->perms & ORANGEFS_U_WRITE)
121                 perm_mode |= S_IWUSR;
122         if (attrs->perms & ORANGEFS_U_READ)
123                 perm_mode |= S_IRUSR;
124
125         if (attrs->perms & ORANGEFS_G_SGID)
126                 perm_mode |= S_ISGID;
127         if (attrs->perms & ORANGEFS_U_SUID)
128                 perm_mode |= S_ISUID;
129
130         return perm_mode;
131 }
132
133 /*
134  * NOTE: in kernel land, we never use the sys_attr->link_target for
135  * anything, so don't bother copying it into the sys_attr object here.
136  */
137 static inline int copy_attributes_from_inode(struct inode *inode,
138                                              struct ORANGEFS_sys_attr_s *attrs,
139                                              struct iattr *iattr)
140 {
141         umode_t tmp_mode;
142
143         if (!iattr || !inode || !attrs) {
144                 gossip_err("NULL iattr (%p), inode (%p), attrs (%p) "
145                            "in copy_attributes_from_inode!\n",
146                            iattr,
147                            inode,
148                            attrs);
149                 return -EINVAL;
150         }
151         /*
152          * We need to be careful to only copy the attributes out of the
153          * iattr object that we know are valid.
154          */
155         attrs->mask = 0;
156         if (iattr->ia_valid & ATTR_UID) {
157                 attrs->owner = from_kuid(&init_user_ns, iattr->ia_uid);
158                 attrs->mask |= ORANGEFS_ATTR_SYS_UID;
159                 gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
160         }
161         if (iattr->ia_valid & ATTR_GID) {
162                 attrs->group = from_kgid(&init_user_ns, iattr->ia_gid);
163                 attrs->mask |= ORANGEFS_ATTR_SYS_GID;
164                 gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
165         }
166
167         if (iattr->ia_valid & ATTR_ATIME) {
168                 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
169                 if (iattr->ia_valid & ATTR_ATIME_SET) {
170                         attrs->atime = (time64_t)iattr->ia_atime.tv_sec;
171                         attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
172                 }
173         }
174         if (iattr->ia_valid & ATTR_MTIME) {
175                 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
176                 if (iattr->ia_valid & ATTR_MTIME_SET) {
177                         attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec;
178                         attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
179                 }
180         }
181         if (iattr->ia_valid & ATTR_CTIME)
182                 attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
183
184         /*
185          * ORANGEFS cannot set size with a setattr operation.  Probably not likely
186          * to be requested through the VFS, but just in case, don't worry about
187          * ATTR_SIZE
188          */
189
190         if (iattr->ia_valid & ATTR_MODE) {
191                 tmp_mode = iattr->ia_mode;
192                 if (tmp_mode & (S_ISVTX)) {
193                         if (is_root_handle(inode)) {
194                                 /*
195                                  * allow sticky bit to be set on root (since
196                                  * it shows up that way by default anyhow),
197                                  * but don't show it to the server
198                                  */
199                                 tmp_mode -= S_ISVTX;
200                         } else {
201                                 gossip_debug(GOSSIP_UTILS_DEBUG,
202                                              "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
203                                 return -EINVAL;
204                         }
205                 }
206
207                 if (tmp_mode & (S_ISUID)) {
208                         gossip_debug(GOSSIP_UTILS_DEBUG,
209                                      "Attempting to set setuid bit (not supported); returning EINVAL.\n");
210                         return -EINVAL;
211                 }
212
213                 attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
214                 attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
215         }
216
217         return 0;
218 }
219
220 static int orangefs_inode_type(enum orangefs_ds_type objtype)
221 {
222         if (objtype == ORANGEFS_TYPE_METAFILE)
223                 return S_IFREG;
224         else if (objtype == ORANGEFS_TYPE_DIRECTORY)
225                 return S_IFDIR;
226         else if (objtype == ORANGEFS_TYPE_SYMLINK)
227                 return S_IFLNK;
228         else
229                 return -1;
230 }
231
232 static int orangefs_inode_is_stale(struct inode *inode, int new,
233     struct ORANGEFS_sys_attr_s *attrs, char *link_target)
234 {
235         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
236         int type = orangefs_inode_type(attrs->objtype);
237         if (!new) {
238                 /*
239                  * If the inode type or symlink target have changed then this
240                  * inode is stale.
241                  */
242                 if (type == -1 || !(inode->i_mode & type)) {
243                         orangefs_make_bad_inode(inode);
244                         return 1;
245                 }
246                 if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
247                     link_target, ORANGEFS_NAME_MAX)) {
248                         orangefs_make_bad_inode(inode);
249                         return 1;
250                 }
251         }
252         return 0;
253 }
254
255 int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
256     u32 request_mask)
257 {
258         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
259         struct orangefs_kernel_op_s *new_op;
260         loff_t inode_size, rounded_up_size;
261         int ret, type;
262
263         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
264             get_khandle_from_ino(inode));
265
266         if (!new && !bypass) {
267                 /*
268                  * Must have all the attributes in the mask and be within cache
269                  * time.
270                  */
271                 if ((request_mask & orangefs_inode->getattr_mask) ==
272                     request_mask &&
273                     time_before(jiffies, orangefs_inode->getattr_time))
274                         return 0;
275         }
276
277         new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
278         if (!new_op)
279                 return -ENOMEM;
280         new_op->upcall.req.getattr.refn = orangefs_inode->refn;
281         /*
282          * Size is the hardest attribute to get.  The incremental cost of any
283          * other attribute is essentially zero.
284          */
285         if (request_mask & STATX_SIZE || new)
286                 new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
287         else
288                 new_op->upcall.req.getattr.mask =
289                     ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
290
291         ret = service_operation(new_op, __func__,
292             get_interruptible_flag(inode));
293         if (ret != 0)
294                 goto out;
295
296         type = orangefs_inode_type(new_op->
297             downcall.resp.getattr.attributes.objtype);
298         ret = orangefs_inode_is_stale(inode, new,
299             &new_op->downcall.resp.getattr.attributes,
300             new_op->downcall.resp.getattr.link_target);
301         if (ret) {
302                 ret = -ESTALE;
303                 goto out;
304         }
305
306         switch (type) {
307         case S_IFREG:
308                 inode->i_flags = orangefs_inode_flags(&new_op->
309                     downcall.resp.getattr.attributes);
310                 if (request_mask & STATX_SIZE || new) {
311                         inode_size = (loff_t)new_op->
312                             downcall.resp.getattr.attributes.size;
313                         rounded_up_size =
314                             (inode_size + (4096 - (inode_size % 4096)));
315                         inode->i_size = inode_size;
316                         orangefs_inode->blksize =
317                             new_op->downcall.resp.getattr.attributes.blksize;
318                         spin_lock(&inode->i_lock);
319                         inode->i_bytes = inode_size;
320                         inode->i_blocks =
321                             (unsigned long)(rounded_up_size / 512);
322                         spin_unlock(&inode->i_lock);
323                 }
324                 break;
325         case S_IFDIR:
326                 if (request_mask & STATX_SIZE || new) {
327                         inode->i_size = PAGE_SIZE;
328                         orangefs_inode->blksize = i_blocksize(inode);
329                         spin_lock(&inode->i_lock);
330                         inode_set_bytes(inode, inode->i_size);
331                         spin_unlock(&inode->i_lock);
332                 }
333                 set_nlink(inode, 1);
334                 break;
335         case S_IFLNK:
336                 if (new) {
337                         inode->i_size = (loff_t)strlen(new_op->
338                             downcall.resp.getattr.link_target);
339                         orangefs_inode->blksize = i_blocksize(inode);
340                         ret = strscpy(orangefs_inode->link_target,
341                             new_op->downcall.resp.getattr.link_target,
342                             ORANGEFS_NAME_MAX);
343                         if (ret == -E2BIG) {
344                                 ret = -EIO;
345                                 goto out;
346                         }
347                         inode->i_link = orangefs_inode->link_target;
348                 }
349                 break;
350         }
351
352         inode->i_uid = make_kuid(&init_user_ns, new_op->
353             downcall.resp.getattr.attributes.owner);
354         inode->i_gid = make_kgid(&init_user_ns, new_op->
355             downcall.resp.getattr.attributes.group);
356         inode->i_atime.tv_sec = (time64_t)new_op->
357             downcall.resp.getattr.attributes.atime;
358         inode->i_mtime.tv_sec = (time64_t)new_op->
359             downcall.resp.getattr.attributes.mtime;
360         inode->i_ctime.tv_sec = (time64_t)new_op->
361             downcall.resp.getattr.attributes.ctime;
362         inode->i_atime.tv_nsec = 0;
363         inode->i_mtime.tv_nsec = 0;
364         inode->i_ctime.tv_nsec = 0;
365
366         /* special case: mark the root inode as sticky */
367         inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
368             orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
369
370         orangefs_inode->getattr_time = jiffies +
371             orangefs_getattr_timeout_msecs*HZ/1000;
372         if (request_mask & STATX_SIZE || new)
373                 orangefs_inode->getattr_mask = STATX_BASIC_STATS;
374         else
375                 orangefs_inode->getattr_mask = STATX_BASIC_STATS & ~STATX_SIZE;
376         ret = 0;
377 out:
378         op_release(new_op);
379         return ret;
380 }
381
382 int orangefs_inode_check_changed(struct inode *inode)
383 {
384         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
385         struct orangefs_kernel_op_s *new_op;
386         int ret;
387
388         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
389             get_khandle_from_ino(inode));
390
391         new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
392         if (!new_op)
393                 return -ENOMEM;
394         new_op->upcall.req.getattr.refn = orangefs_inode->refn;
395         new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
396             ORANGEFS_ATTR_SYS_LNK_TARGET;
397
398         ret = service_operation(new_op, __func__,
399             get_interruptible_flag(inode));
400         if (ret != 0)
401                 goto out;
402
403         ret = orangefs_inode_is_stale(inode, 0,
404             &new_op->downcall.resp.getattr.attributes,
405             new_op->downcall.resp.getattr.link_target);
406 out:
407         op_release(new_op);
408         return ret;
409 }
410
411 /*
412  * issues a orangefs setattr request to make sure the new attribute values
413  * take effect if successful.  returns 0 on success; -errno otherwise
414  */
415 int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
416 {
417         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
418         struct orangefs_kernel_op_s *new_op;
419         int ret;
420
421         new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
422         if (!new_op)
423                 return -ENOMEM;
424
425         new_op->upcall.req.setattr.refn = orangefs_inode->refn;
426         ret = copy_attributes_from_inode(inode,
427                        &new_op->upcall.req.setattr.attributes,
428                        iattr);
429         if (ret >= 0) {
430                 ret = service_operation(new_op, __func__,
431                                 get_interruptible_flag(inode));
432
433                 gossip_debug(GOSSIP_UTILS_DEBUG,
434                              "orangefs_inode_setattr: returning %d\n",
435                              ret);
436         }
437
438         op_release(new_op);
439
440         /*
441          * successful setattr should clear the atime, mtime and
442          * ctime flags.
443          */
444         if (ret == 0) {
445                 ClearAtimeFlag(orangefs_inode);
446                 ClearMtimeFlag(orangefs_inode);
447                 ClearCtimeFlag(orangefs_inode);
448                 ClearModeFlag(orangefs_inode);
449                 orangefs_inode->getattr_time = jiffies - 1;
450         }
451
452         return ret;
453 }
454
455 int orangefs_flush_inode(struct inode *inode)
456 {
457         /*
458          * If it is a dirty inode, this function gets called.
459          * Gather all the information that needs to be setattr'ed
460          * Right now, this will only be used for mode, atime, mtime
461          * and/or ctime.
462          */
463         struct iattr wbattr;
464         int ret;
465         int mtime_flag;
466         int ctime_flag;
467         int atime_flag;
468         int mode_flag;
469         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
470
471         memset(&wbattr, 0, sizeof(wbattr));
472
473         /*
474          * check inode flags up front, and clear them if they are set.  This
475          * will prevent multiple processes from all trying to flush the same
476          * inode if they call close() simultaneously
477          */
478         mtime_flag = MtimeFlag(orangefs_inode);
479         ClearMtimeFlag(orangefs_inode);
480         ctime_flag = CtimeFlag(orangefs_inode);
481         ClearCtimeFlag(orangefs_inode);
482         atime_flag = AtimeFlag(orangefs_inode);
483         ClearAtimeFlag(orangefs_inode);
484         mode_flag = ModeFlag(orangefs_inode);
485         ClearModeFlag(orangefs_inode);
486
487         /*  -- Lazy atime,mtime and ctime update --
488          * Note: all times are dictated by server in the new scheme
489          * and not by the clients
490          *
491          * Also mode updates are being handled now..
492          */
493
494         if (mtime_flag)
495                 wbattr.ia_valid |= ATTR_MTIME;
496         if (ctime_flag)
497                 wbattr.ia_valid |= ATTR_CTIME;
498         if (atime_flag)
499                 wbattr.ia_valid |= ATTR_ATIME;
500
501         if (mode_flag) {
502                 wbattr.ia_mode = inode->i_mode;
503                 wbattr.ia_valid |= ATTR_MODE;
504         }
505
506         gossip_debug(GOSSIP_UTILS_DEBUG,
507                      "*********** orangefs_flush_inode: %pU "
508                      "(ia_valid %d)\n",
509                      get_khandle_from_ino(inode),
510                      wbattr.ia_valid);
511         if (wbattr.ia_valid == 0) {
512                 gossip_debug(GOSSIP_UTILS_DEBUG,
513                              "orangefs_flush_inode skipping setattr()\n");
514                 return 0;
515         }
516
517         gossip_debug(GOSSIP_UTILS_DEBUG,
518                      "orangefs_flush_inode (%pU) writing mode %o\n",
519                      get_khandle_from_ino(inode),
520                      inode->i_mode);
521
522         ret = orangefs_inode_setattr(inode, &wbattr);
523
524         return ret;
525 }
526
527 void orangefs_make_bad_inode(struct inode *inode)
528 {
529         if (is_root_handle(inode)) {
530                 /*
531                  * if this occurs, the pvfs2-client-core was killed but we
532                  * can't afford to lose the inode operations and such
533                  * associated with the root handle in any case.
534                  */
535                 gossip_debug(GOSSIP_UTILS_DEBUG,
536                              "*** NOT making bad root inode %pU\n",
537                              get_khandle_from_ino(inode));
538         } else {
539                 gossip_debug(GOSSIP_UTILS_DEBUG,
540                              "*** making bad inode %pU\n",
541                              get_khandle_from_ino(inode));
542                 make_bad_inode(inode);
543         }
544 }
545
546 /*
547  * The following is a very dirty hack that is now a permanent part of the
548  * ORANGEFS protocol. See protocol.h for more error definitions.
549  */
550
551 /* The order matches include/orangefs-types.h in the OrangeFS source. */
552 static int PINT_errno_mapping[] = {
553         0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
554         EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
555         EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
556         ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
557         EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
558         EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
559         ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
560         EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
561         ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
562         EACCES, ECONNRESET, ERANGE
563 };
564
565 int orangefs_normalize_to_errno(__s32 error_code)
566 {
567         __u32 i;
568
569         /* Success */
570         if (error_code == 0) {
571                 return 0;
572         /*
573          * This shouldn't ever happen. If it does it should be fixed on the
574          * server.
575          */
576         } else if (error_code > 0) {
577                 gossip_err("orangefs: error status receieved.\n");
578                 gossip_err("orangefs: assuming error code is inverted.\n");
579                 error_code = -error_code;
580         }
581
582         /*
583          * XXX: This is very bad since error codes from ORANGEFS may not be
584          * suitable for return into userspace.
585          */
586
587         /*
588          * Convert ORANGEFS error values into errno values suitable for return
589          * from the kernel.
590          */
591         if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
592                 if (((-error_code) &
593                     (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
594                     ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
595                         /*
596                          * cancellation error codes generally correspond to
597                          * a timeout from the client's perspective
598                          */
599                         error_code = -ETIMEDOUT;
600                 } else {
601                         /* assume a default error code */
602                         gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
603                         error_code = -EINVAL;
604                 }
605
606         /* Convert ORANGEFS encoded errno values into regular errno values. */
607         } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
608                 i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
609                 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
610                         error_code = -PINT_errno_mapping[i];
611                 else
612                         error_code = -EINVAL;
613
614         /*
615          * Only ORANGEFS protocol error codes should ever come here. Otherwise
616          * there is a bug somewhere.
617          */
618         } else {
619                 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
620         }
621         return error_code;
622 }
623
624 #define NUM_MODES 11
625 __s32 ORANGEFS_util_translate_mode(int mode)
626 {
627         int ret = 0;
628         int i = 0;
629         static int modes[NUM_MODES] = {
630                 S_IXOTH, S_IWOTH, S_IROTH,
631                 S_IXGRP, S_IWGRP, S_IRGRP,
632                 S_IXUSR, S_IWUSR, S_IRUSR,
633                 S_ISGID, S_ISUID
634         };
635         static int orangefs_modes[NUM_MODES] = {
636                 ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
637                 ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
638                 ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
639                 ORANGEFS_G_SGID, ORANGEFS_U_SUID
640         };
641
642         for (i = 0; i < NUM_MODES; i++)
643                 if (mode & modes[i])
644                         ret |= orangefs_modes[i];
645
646         return ret;
647 }
648 #undef NUM_MODES