orangefs-utils.c 16 KB

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