1 // SPDX-License-Identifier: GPL-2.0
3 * (C) 2001 Clemson University and The University of Chicago
4 * Copyright 2018 Omnibond Systems, L.L.C.
6 * See COPYING in top-level directory.
8 #include <linux/kernel.h>
10 #include "orangefs-kernel.h"
11 #include "orangefs-dev-proto.h"
12 #include "orangefs-bufmap.h"
14 __s32
fsid_of_op(struct orangefs_kernel_op_s
*op
)
16 __s32 fsid
= ORANGEFS_FS_ID_NULL
;
19 switch (op
->upcall
.type
) {
20 case ORANGEFS_VFS_OP_FILE_IO
:
21 fsid
= op
->upcall
.req
.io
.refn
.fs_id
;
23 case ORANGEFS_VFS_OP_LOOKUP
:
24 fsid
= op
->upcall
.req
.lookup
.parent_refn
.fs_id
;
26 case ORANGEFS_VFS_OP_CREATE
:
27 fsid
= op
->upcall
.req
.create
.parent_refn
.fs_id
;
29 case ORANGEFS_VFS_OP_GETATTR
:
30 fsid
= op
->upcall
.req
.getattr
.refn
.fs_id
;
32 case ORANGEFS_VFS_OP_REMOVE
:
33 fsid
= op
->upcall
.req
.remove
.parent_refn
.fs_id
;
35 case ORANGEFS_VFS_OP_MKDIR
:
36 fsid
= op
->upcall
.req
.mkdir
.parent_refn
.fs_id
;
38 case ORANGEFS_VFS_OP_READDIR
:
39 fsid
= op
->upcall
.req
.readdir
.refn
.fs_id
;
41 case ORANGEFS_VFS_OP_SETATTR
:
42 fsid
= op
->upcall
.req
.setattr
.refn
.fs_id
;
44 case ORANGEFS_VFS_OP_SYMLINK
:
45 fsid
= op
->upcall
.req
.sym
.parent_refn
.fs_id
;
47 case ORANGEFS_VFS_OP_RENAME
:
48 fsid
= op
->upcall
.req
.rename
.old_parent_refn
.fs_id
;
50 case ORANGEFS_VFS_OP_STATFS
:
51 fsid
= op
->upcall
.req
.statfs
.fs_id
;
53 case ORANGEFS_VFS_OP_TRUNCATE
:
54 fsid
= op
->upcall
.req
.truncate
.refn
.fs_id
;
56 case ORANGEFS_VFS_OP_RA_FLUSH
:
57 fsid
= op
->upcall
.req
.ra_cache_flush
.refn
.fs_id
;
59 case ORANGEFS_VFS_OP_FS_UMOUNT
:
60 fsid
= op
->upcall
.req
.fs_umount
.fs_id
;
62 case ORANGEFS_VFS_OP_GETXATTR
:
63 fsid
= op
->upcall
.req
.getxattr
.refn
.fs_id
;
65 case ORANGEFS_VFS_OP_SETXATTR
:
66 fsid
= op
->upcall
.req
.setxattr
.refn
.fs_id
;
68 case ORANGEFS_VFS_OP_LISTXATTR
:
69 fsid
= op
->upcall
.req
.listxattr
.refn
.fs_id
;
71 case ORANGEFS_VFS_OP_REMOVEXATTR
:
72 fsid
= op
->upcall
.req
.removexattr
.refn
.fs_id
;
74 case ORANGEFS_VFS_OP_FSYNC
:
75 fsid
= op
->upcall
.req
.fsync
.refn
.fs_id
;
84 static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s
*attrs
)
87 if (attrs
->flags
& ORANGEFS_IMMUTABLE_FL
)
90 flags
&= ~S_IMMUTABLE
;
91 if (attrs
->flags
& ORANGEFS_APPEND_FL
)
95 if (attrs
->flags
& ORANGEFS_NOATIME_FL
)
102 static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s
*attrs
)
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
;
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
;
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
;
127 if (attrs
->perms
& ORANGEFS_G_SGID
)
128 perm_mode
|= S_ISGID
;
129 if (attrs
->perms
& ORANGEFS_U_SUID
)
130 perm_mode
|= S_ISUID
;
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.
139 static inline void copy_attributes_from_inode(struct inode
*inode
,
140 struct ORANGEFS_sys_attr_s
*attrs
)
142 struct orangefs_inode_s
*orangefs_inode
= ORANGEFS_I(inode
);
144 if (orangefs_inode
->attr_valid
& ATTR_UID
) {
145 attrs
->owner
= from_kuid(&init_user_ns
, inode
->i_uid
);
146 attrs
->mask
|= ORANGEFS_ATTR_SYS_UID
;
147 gossip_debug(GOSSIP_UTILS_DEBUG
, "(UID) %d\n", attrs
->owner
);
149 if (orangefs_inode
->attr_valid
& ATTR_GID
) {
150 attrs
->group
= from_kgid(&init_user_ns
, inode
->i_gid
);
151 attrs
->mask
|= ORANGEFS_ATTR_SYS_GID
;
152 gossip_debug(GOSSIP_UTILS_DEBUG
, "(GID) %d\n", attrs
->group
);
155 if (orangefs_inode
->attr_valid
& ATTR_ATIME
) {
156 attrs
->mask
|= ORANGEFS_ATTR_SYS_ATIME
;
157 if (orangefs_inode
->attr_valid
& ATTR_ATIME_SET
) {
158 attrs
->atime
= (time64_t
)inode
->i_atime
.tv_sec
;
159 attrs
->mask
|= ORANGEFS_ATTR_SYS_ATIME_SET
;
162 if (orangefs_inode
->attr_valid
& ATTR_MTIME
) {
163 attrs
->mask
|= ORANGEFS_ATTR_SYS_MTIME
;
164 if (orangefs_inode
->attr_valid
& ATTR_MTIME_SET
) {
165 attrs
->mtime
= (time64_t
)inode
->i_mtime
.tv_sec
;
166 attrs
->mask
|= ORANGEFS_ATTR_SYS_MTIME_SET
;
169 if (orangefs_inode
->attr_valid
& ATTR_CTIME
)
170 attrs
->mask
|= ORANGEFS_ATTR_SYS_CTIME
;
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
178 if (orangefs_inode
->attr_valid
& ATTR_MODE
) {
179 attrs
->perms
= ORANGEFS_util_translate_mode(inode
->i_mode
);
180 attrs
->mask
|= ORANGEFS_ATTR_SYS_PERM
;
184 static int orangefs_inode_type(enum orangefs_ds_type objtype
)
186 if (objtype
== ORANGEFS_TYPE_METAFILE
)
188 else if (objtype
== ORANGEFS_TYPE_DIRECTORY
)
190 else if (objtype
== ORANGEFS_TYPE_SYMLINK
)
196 static void orangefs_make_bad_inode(struct inode
*inode
)
198 if (is_root_handle(inode
)) {
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.
204 gossip_debug(GOSSIP_UTILS_DEBUG
,
205 "*** NOT making bad root inode %pU\n",
206 get_khandle_from_ino(inode
));
208 gossip_debug(GOSSIP_UTILS_DEBUG
,
209 "*** making bad inode %pU\n",
210 get_khandle_from_ino(inode
));
211 make_bad_inode(inode
);
215 static int orangefs_inode_is_stale(struct inode
*inode
,
216 struct ORANGEFS_sys_attr_s
*attrs
, char *link_target
)
218 struct orangefs_inode_s
*orangefs_inode
= ORANGEFS_I(inode
);
219 int type
= orangefs_inode_type(attrs
->objtype
);
221 * If the inode type or symlink target have changed then this
224 if (type
== -1 || !(inode
->i_mode
& type
)) {
225 orangefs_make_bad_inode(inode
);
228 if (type
== S_IFLNK
&& strncmp(orangefs_inode
->link_target
,
229 link_target
, ORANGEFS_NAME_MAX
)) {
230 orangefs_make_bad_inode(inode
);
236 int orangefs_inode_getattr(struct inode
*inode
, int flags
)
238 struct orangefs_inode_s
*orangefs_inode
= ORANGEFS_I(inode
);
239 struct orangefs_kernel_op_s
*new_op
;
243 gossip_debug(GOSSIP_UTILS_DEBUG
, "%s: called on inode %pU flags %d\n",
244 __func__
, get_khandle_from_ino(inode
), flags
);
247 spin_lock(&inode
->i_lock
);
248 /* Must have all the attributes in the mask and be within cache time. */
249 if ((!flags
&& time_before(jiffies
, orangefs_inode
->getattr_time
)) ||
250 orangefs_inode
->attr_valid
|| inode
->i_state
& I_DIRTY_PAGES
) {
251 if (orangefs_inode
->attr_valid
) {
252 spin_unlock(&inode
->i_lock
);
253 write_inode_now(inode
, 1);
256 spin_unlock(&inode
->i_lock
);
259 spin_unlock(&inode
->i_lock
);
261 new_op
= op_alloc(ORANGEFS_VFS_OP_GETATTR
);
264 new_op
->upcall
.req
.getattr
.refn
= orangefs_inode
->refn
;
266 * Size is the hardest attribute to get. The incremental cost of any
267 * other attribute is essentially zero.
270 new_op
->upcall
.req
.getattr
.mask
= ORANGEFS_ATTR_SYS_ALL_NOHINT
;
272 new_op
->upcall
.req
.getattr
.mask
=
273 ORANGEFS_ATTR_SYS_ALL_NOHINT
& ~ORANGEFS_ATTR_SYS_SIZE
;
275 ret
= service_operation(new_op
, __func__
,
276 get_interruptible_flag(inode
));
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
)) ||
284 orangefs_inode
->attr_valid
|| inode
->i_state
& I_DIRTY_PAGES
) {
285 if (orangefs_inode
->attr_valid
) {
286 spin_unlock(&inode
->i_lock
);
287 write_inode_now(inode
, 1);
290 if (inode
->i_state
& I_DIRTY_PAGES
) {
294 gossip_debug(GOSSIP_UTILS_DEBUG
, "%s: in cache or dirty\n",
300 if (!(flags
& ORANGEFS_GETATTR_NEW
)) {
301 ret
= orangefs_inode_is_stale(inode
,
302 &new_op
->downcall
.resp
.getattr
.attributes
,
303 new_op
->downcall
.resp
.getattr
.link_target
);
310 type
= orangefs_inode_type(new_op
->
311 downcall
.resp
.getattr
.attributes
.objtype
);
314 inode
->i_flags
= orangefs_inode_flags(&new_op
->
315 downcall
.resp
.getattr
.attributes
);
317 inode_size
= (loff_t
)new_op
->
318 downcall
.resp
.getattr
.attributes
.size
;
319 inode
->i_size
= inode_size
;
320 inode
->i_blkbits
= ffs(new_op
->downcall
.resp
.getattr
.
322 inode
->i_bytes
= inode_size
;
324 (inode_size
+ 512 - inode_size
% 512)/512;
329 inode
->i_size
= PAGE_SIZE
;
330 inode_set_bytes(inode
, inode
->i_size
);
335 if (flags
& ORANGEFS_GETATTR_NEW
) {
336 inode
->i_size
= (loff_t
)strlen(new_op
->
337 downcall
.resp
.getattr
.link_target
);
338 ret
= strscpy(orangefs_inode
->link_target
,
339 new_op
->downcall
.resp
.getattr
.link_target
,
345 inode
->i_link
= orangefs_inode
->link_target
;
350 /* XXX: ESTALE? This is what is done if it is not new. */
351 orangefs_make_bad_inode(inode
);
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;
370 /* special case: mark the root inode as sticky */
371 inode
->i_mode
= type
| (is_root_handle(inode
) ? S_ISVTX
: 0) |
372 orangefs_inode_perms(&new_op
->downcall
.resp
.getattr
.attributes
);
374 orangefs_inode
->getattr_time
= jiffies
+
375 orangefs_getattr_timeout_msecs
*HZ
/1000;
378 spin_unlock(&inode
->i_lock
);
384 int orangefs_inode_check_changed(struct inode
*inode
)
386 struct orangefs_inode_s
*orangefs_inode
= ORANGEFS_I(inode
);
387 struct orangefs_kernel_op_s
*new_op
;
390 gossip_debug(GOSSIP_UTILS_DEBUG
, "%s: called on inode %pU\n", __func__
,
391 get_khandle_from_ino(inode
));
393 new_op
= op_alloc(ORANGEFS_VFS_OP_GETATTR
);
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
;
400 ret
= service_operation(new_op
, __func__
,
401 get_interruptible_flag(inode
));
405 ret
= orangefs_inode_is_stale(inode
,
406 &new_op
->downcall
.resp
.getattr
.attributes
,
407 new_op
->downcall
.resp
.getattr
.link_target
);
414 * issues a orangefs setattr request to make sure the new attribute values
415 * take effect if successful. returns 0 on success; -errno otherwise
417 int orangefs_inode_setattr(struct inode
*inode
)
419 struct orangefs_inode_s
*orangefs_inode
= ORANGEFS_I(inode
);
420 struct orangefs_kernel_op_s
*new_op
;
423 new_op
= op_alloc(ORANGEFS_VFS_OP_SETATTR
);
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
);
430 new_op
->upcall
.req
.setattr
.refn
= orangefs_inode
->refn
;
431 copy_attributes_from_inode(inode
,
432 &new_op
->upcall
.req
.setattr
.attributes
);
433 orangefs_inode
->attr_valid
= 0;
434 if (!new_op
->upcall
.req
.setattr
.attributes
.mask
) {
435 spin_unlock(&inode
->i_lock
);
439 spin_unlock(&inode
->i_lock
);
441 ret
= service_operation(new_op
, __func__
,
442 get_interruptible_flag(inode
) | ORANGEFS_OP_WRITEBACK
);
443 gossip_debug(GOSSIP_UTILS_DEBUG
,
444 "orangefs_inode_setattr: returning %d\n", ret
);
446 orangefs_make_bad_inode(inode
);
451 orangefs_inode
->getattr_time
= jiffies
- 1;
456 * The following is a very dirty hack that is now a permanent part of the
457 * ORANGEFS protocol. See protocol.h for more error definitions.
460 /* The order matches include/orangefs-types.h in the OrangeFS source. */
461 static int PINT_errno_mapping
[] = {
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
474 int orangefs_normalize_to_errno(__s32 error_code
)
479 if (error_code
== 0) {
482 * This shouldn't ever happen. If it does it should be fixed on the
485 } else if (error_code
> 0) {
486 gossip_err("orangefs: error status received.\n");
487 gossip_err("orangefs: assuming error code is inverted.\n");
488 error_code
= -error_code
;
492 * XXX: This is very bad since error codes from ORANGEFS may not be
493 * suitable for return into userspace.
497 * Convert ORANGEFS error values into errno values suitable for return
500 if ((-error_code
) & ORANGEFS_NON_ERRNO_ERROR_BIT
) {
502 (ORANGEFS_ERROR_NUMBER_BITS
|ORANGEFS_NON_ERRNO_ERROR_BIT
|
503 ORANGEFS_ERROR_BIT
)) == ORANGEFS_ECANCEL
) {
505 * cancellation error codes generally correspond to
506 * a timeout from the client's perspective
508 error_code
= -ETIMEDOUT
;
510 /* assume a default error code */
511 gossip_err("%s: bad error code :%d:.\n",
514 error_code
= -EINVAL
;
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
);
520 if (i
< ARRAY_SIZE(PINT_errno_mapping
))
521 error_code
= -PINT_errno_mapping
[i
];
523 error_code
= -EINVAL
;
526 * Only ORANGEFS protocol error codes should ever come here. Otherwise
527 * there is a bug somewhere.
530 gossip_err("%s: unknown error code.\n", __func__
);
531 error_code
= -EINVAL
;
537 __s32
ORANGEFS_util_translate_mode(int mode
)
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
,
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
554 for (i
= 0; i
< NUM_MODES
; i
++)
556 ret
|= orangefs_modes
[i
];