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