orangefs-utils.c 15 KB

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