]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/orangefs/orangefs-utils.c
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
[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_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(&init_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(&init_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 bypass,
255     u32 request_mask)
256 {
257         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
258         struct orangefs_kernel_op_s *new_op;
259         loff_t inode_size, rounded_up_size;
260         int ret, type;
261
262         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
263             get_khandle_from_ino(inode));
264
265         if (!new && !bypass) {
266                 /*
267                  * Must have all the attributes in the mask and be within cache
268                  * time.
269                  */
270                 if ((request_mask & orangefs_inode->getattr_mask) ==
271                     request_mask &&
272                     time_before(jiffies, orangefs_inode->getattr_time))
273                         return 0;
274         }
275
276         new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
277         if (!new_op)
278                 return -ENOMEM;
279         new_op->upcall.req.getattr.refn = orangefs_inode->refn;
280         /*
281          * Size is the hardest attribute to get.  The incremental cost of any
282          * other attribute is essentially zero.
283          */
284         if (request_mask & STATX_SIZE || new)
285                 new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
286         else
287                 new_op->upcall.req.getattr.mask =
288                     ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
289
290         ret = service_operation(new_op, __func__,
291             get_interruptible_flag(inode));
292         if (ret != 0)
293                 goto out;
294
295         type = orangefs_inode_type(new_op->
296             downcall.resp.getattr.attributes.objtype);
297         ret = orangefs_inode_is_stale(inode, new,
298             &new_op->downcall.resp.getattr.attributes,
299             new_op->downcall.resp.getattr.link_target);
300         if (ret) {
301                 ret = -ESTALE;
302                 goto out;
303         }
304
305         switch (type) {
306         case S_IFREG:
307                 inode->i_flags = orangefs_inode_flags(&new_op->
308                     downcall.resp.getattr.attributes);
309                 if (request_mask & STATX_SIZE || new) {
310                         inode_size = (loff_t)new_op->
311                             downcall.resp.getattr.attributes.size;
312                         rounded_up_size =
313                             (inode_size + (4096 - (inode_size % 4096)));
314                         inode->i_size = inode_size;
315                         orangefs_inode->blksize =
316                             new_op->downcall.resp.getattr.attributes.blksize;
317                         spin_lock(&inode->i_lock);
318                         inode->i_bytes = inode_size;
319                         inode->i_blocks =
320                             (unsigned long)(rounded_up_size / 512);
321                         spin_unlock(&inode->i_lock);
322                 }
323                 break;
324         case S_IFDIR:
325                 if (request_mask & STATX_SIZE || new) {
326                         inode->i_size = PAGE_SIZE;
327                         orangefs_inode->blksize = i_blocksize(inode);
328                         spin_lock(&inode->i_lock);
329                         inode_set_bytes(inode, inode->i_size);
330                         spin_unlock(&inode->i_lock);
331                 }
332                 set_nlink(inode, 1);
333                 break;
334         case S_IFLNK:
335                 if (new) {
336                         inode->i_size = (loff_t)strlen(new_op->
337                             downcall.resp.getattr.link_target);
338                         orangefs_inode->blksize = i_blocksize(inode);
339                         ret = strscpy(orangefs_inode->link_target,
340                             new_op->downcall.resp.getattr.link_target,
341                             ORANGEFS_NAME_MAX);
342                         if (ret == -E2BIG) {
343                                 ret = -EIO;
344                                 goto out;
345                         }
346                         inode->i_link = orangefs_inode->link_target;
347                 }
348                 break;
349         }
350
351         inode->i_uid = make_kuid(&init_user_ns, new_op->
352             downcall.resp.getattr.attributes.owner);
353         inode->i_gid = make_kgid(&init_user_ns, new_op->
354             downcall.resp.getattr.attributes.group);
355         inode->i_atime.tv_sec = (time64_t)new_op->
356             downcall.resp.getattr.attributes.atime;
357         inode->i_mtime.tv_sec = (time64_t)new_op->
358             downcall.resp.getattr.attributes.mtime;
359         inode->i_ctime.tv_sec = (time64_t)new_op->
360             downcall.resp.getattr.attributes.ctime;
361         inode->i_atime.tv_nsec = 0;
362         inode->i_mtime.tv_nsec = 0;
363         inode->i_ctime.tv_nsec = 0;
364
365         /* special case: mark the root inode as sticky */
366         inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
367             orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
368
369         orangefs_inode->getattr_time = jiffies +
370             orangefs_getattr_timeout_msecs*HZ/1000;
371         if (request_mask & STATX_SIZE || new)
372                 orangefs_inode->getattr_mask = STATX_BASIC_STATS;
373         else
374                 orangefs_inode->getattr_mask = STATX_BASIC_STATS & ~STATX_SIZE;
375         ret = 0;
376 out:
377         op_release(new_op);
378         return ret;
379 }
380
381 int orangefs_inode_check_changed(struct inode *inode)
382 {
383         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
384         struct orangefs_kernel_op_s *new_op;
385         int ret;
386
387         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
388             get_khandle_from_ino(inode));
389
390         new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
391         if (!new_op)
392                 return -ENOMEM;
393         new_op->upcall.req.getattr.refn = orangefs_inode->refn;
394         new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
395             ORANGEFS_ATTR_SYS_LNK_TARGET;
396
397         ret = service_operation(new_op, __func__,
398             get_interruptible_flag(inode));
399         if (ret != 0)
400                 goto out;
401
402         ret = orangefs_inode_is_stale(inode, 0,
403             &new_op->downcall.resp.getattr.attributes,
404             new_op->downcall.resp.getattr.link_target);
405 out:
406         op_release(new_op);
407         return ret;
408 }
409
410 /*
411  * issues a orangefs setattr request to make sure the new attribute values
412  * take effect if successful.  returns 0 on success; -errno otherwise
413  */
414 int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
415 {
416         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
417         struct orangefs_kernel_op_s *new_op;
418         int ret;
419
420         new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
421         if (!new_op)
422                 return -ENOMEM;
423
424         new_op->upcall.req.setattr.refn = orangefs_inode->refn;
425         ret = copy_attributes_from_inode(inode,
426                        &new_op->upcall.req.setattr.attributes,
427                        iattr);
428         if (ret >= 0) {
429                 ret = service_operation(new_op, __func__,
430                                 get_interruptible_flag(inode));
431
432                 gossip_debug(GOSSIP_UTILS_DEBUG,
433                              "orangefs_inode_setattr: returning %d\n",
434                              ret);
435         }
436
437         op_release(new_op);
438
439         /*
440          * successful setattr should clear the atime, mtime and
441          * ctime flags.
442          */
443         if (ret == 0) {
444                 ClearAtimeFlag(orangefs_inode);
445                 ClearMtimeFlag(orangefs_inode);
446                 ClearCtimeFlag(orangefs_inode);
447                 ClearModeFlag(orangefs_inode);
448                 orangefs_inode->getattr_time = jiffies - 1;
449         }
450
451         return ret;
452 }
453
454 int orangefs_flush_inode(struct inode *inode)
455 {
456         /*
457          * If it is a dirty inode, this function gets called.
458          * Gather all the information that needs to be setattr'ed
459          * Right now, this will only be used for mode, atime, mtime
460          * and/or ctime.
461          */
462         struct iattr wbattr;
463         int ret;
464         int mtime_flag;
465         int ctime_flag;
466         int atime_flag;
467         int mode_flag;
468         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
469
470         memset(&wbattr, 0, sizeof(wbattr));
471
472         /*
473          * check inode flags up front, and clear them if they are set.  This
474          * will prevent multiple processes from all trying to flush the same
475          * inode if they call close() simultaneously
476          */
477         mtime_flag = MtimeFlag(orangefs_inode);
478         ClearMtimeFlag(orangefs_inode);
479         ctime_flag = CtimeFlag(orangefs_inode);
480         ClearCtimeFlag(orangefs_inode);
481         atime_flag = AtimeFlag(orangefs_inode);
482         ClearAtimeFlag(orangefs_inode);
483         mode_flag = ModeFlag(orangefs_inode);
484         ClearModeFlag(orangefs_inode);
485
486         /*  -- Lazy atime,mtime and ctime update --
487          * Note: all times are dictated by server in the new scheme
488          * and not by the clients
489          *
490          * Also mode updates are being handled now..
491          */
492
493         if (mtime_flag)
494                 wbattr.ia_valid |= ATTR_MTIME;
495         if (ctime_flag)
496                 wbattr.ia_valid |= ATTR_CTIME;
497         if (atime_flag)
498                 wbattr.ia_valid |= ATTR_ATIME;
499
500         if (mode_flag) {
501                 wbattr.ia_mode = inode->i_mode;
502                 wbattr.ia_valid |= ATTR_MODE;
503         }
504
505         gossip_debug(GOSSIP_UTILS_DEBUG,
506                      "*********** orangefs_flush_inode: %pU "
507                      "(ia_valid %d)\n",
508                      get_khandle_from_ino(inode),
509                      wbattr.ia_valid);
510         if (wbattr.ia_valid == 0) {
511                 gossip_debug(GOSSIP_UTILS_DEBUG,
512                              "orangefs_flush_inode skipping setattr()\n");
513                 return 0;
514         }
515
516         gossip_debug(GOSSIP_UTILS_DEBUG,
517                      "orangefs_flush_inode (%pU) writing mode %o\n",
518                      get_khandle_from_ino(inode),
519                      inode->i_mode);
520
521         ret = orangefs_inode_setattr(inode, &wbattr);
522
523         return ret;
524 }
525
526 void orangefs_make_bad_inode(struct inode *inode)
527 {
528         if (is_root_handle(inode)) {
529                 /*
530                  * if this occurs, the pvfs2-client-core was killed but we
531                  * can't afford to lose the inode operations and such
532                  * associated with the root handle in any case.
533                  */
534                 gossip_debug(GOSSIP_UTILS_DEBUG,
535                              "*** NOT making bad root inode %pU\n",
536                              get_khandle_from_ino(inode));
537         } else {
538                 gossip_debug(GOSSIP_UTILS_DEBUG,
539                              "*** making bad inode %pU\n",
540                              get_khandle_from_ino(inode));
541                 make_bad_inode(inode);
542         }
543 }
544
545 /*
546  * The following is a very dirty hack that is now a permanent part of the
547  * ORANGEFS protocol. See protocol.h for more error definitions.
548  */
549
550 /* The order matches include/orangefs-types.h in the OrangeFS source. */
551 static int PINT_errno_mapping[] = {
552         0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
553         EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
554         EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
555         ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
556         EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
557         EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
558         ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
559         EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
560         ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
561         EACCES, ECONNRESET, ERANGE
562 };
563
564 int orangefs_normalize_to_errno(__s32 error_code)
565 {
566         __u32 i;
567
568         /* Success */
569         if (error_code == 0) {
570                 return 0;
571         /*
572          * This shouldn't ever happen. If it does it should be fixed on the
573          * server.
574          */
575         } else if (error_code > 0) {
576                 gossip_err("orangefs: error status receieved.\n");
577                 gossip_err("orangefs: assuming error code is inverted.\n");
578                 error_code = -error_code;
579         }
580
581         /*
582          * XXX: This is very bad since error codes from ORANGEFS may not be
583          * suitable for return into userspace.
584          */
585
586         /*
587          * Convert ORANGEFS error values into errno values suitable for return
588          * from the kernel.
589          */
590         if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
591                 if (((-error_code) &
592                     (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
593                     ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
594                         /*
595                          * cancellation error codes generally correspond to
596                          * a timeout from the client's perspective
597                          */
598                         error_code = -ETIMEDOUT;
599                 } else {
600                         /* assume a default error code */
601                         gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
602                         error_code = -EINVAL;
603                 }
604
605         /* Convert ORANGEFS encoded errno values into regular errno values. */
606         } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
607                 i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
608                 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
609                         error_code = -PINT_errno_mapping[i];
610                 else
611                         error_code = -EINVAL;
612
613         /*
614          * Only ORANGEFS protocol error codes should ever come here. Otherwise
615          * there is a bug somewhere.
616          */
617         } else {
618                 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
619         }
620         return error_code;
621 }
622
623 #define NUM_MODES 11
624 __s32 ORANGEFS_util_translate_mode(int mode)
625 {
626         int ret = 0;
627         int i = 0;
628         static int modes[NUM_MODES] = {
629                 S_IXOTH, S_IWOTH, S_IROTH,
630                 S_IXGRP, S_IWGRP, S_IRGRP,
631                 S_IXUSR, S_IWUSR, S_IRUSR,
632                 S_ISGID, S_ISUID
633         };
634         static int orangefs_modes[NUM_MODES] = {
635                 ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
636                 ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
637                 ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
638                 ORANGEFS_G_SGID, ORANGEFS_U_SUID
639         };
640
641         for (i = 0; i < NUM_MODES; i++)
642                 if (mode & modes[i])
643                         ret |= orangefs_modes[i];
644
645         return ret;
646 }
647 #undef NUM_MODES