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