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