1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2575e9461SMike Marshall /*
3575e9461SMike Marshall * (C) 2001 Clemson University and The University of Chicago
48b60785cSMartin Brandenburg * Copyright 2018 Omnibond Systems, L.L.C.
5575e9461SMike Marshall *
6575e9461SMike Marshall * See COPYING in top-level directory.
7575e9461SMike Marshall */
8296200d3SJérémy Lefaure #include <linux/kernel.h>
9575e9461SMike Marshall #include "protocol.h"
10575e9461SMike Marshall #include "orangefs-kernel.h"
11575e9461SMike Marshall #include "orangefs-dev-proto.h"
12575e9461SMike Marshall #include "orangefs-bufmap.h"
13575e9461SMike Marshall
fsid_of_op(struct orangefs_kernel_op_s * op)14575e9461SMike Marshall __s32 fsid_of_op(struct orangefs_kernel_op_s *op)
15575e9461SMike Marshall {
16575e9461SMike Marshall __s32 fsid = ORANGEFS_FS_ID_NULL;
17575e9461SMike Marshall
18575e9461SMike Marshall if (op) {
19575e9461SMike Marshall switch (op->upcall.type) {
20575e9461SMike Marshall case ORANGEFS_VFS_OP_FILE_IO:
21575e9461SMike Marshall fsid = op->upcall.req.io.refn.fs_id;
22575e9461SMike Marshall break;
23575e9461SMike Marshall case ORANGEFS_VFS_OP_LOOKUP:
24575e9461SMike Marshall fsid = op->upcall.req.lookup.parent_refn.fs_id;
25575e9461SMike Marshall break;
26575e9461SMike Marshall case ORANGEFS_VFS_OP_CREATE:
27575e9461SMike Marshall fsid = op->upcall.req.create.parent_refn.fs_id;
28575e9461SMike Marshall break;
29575e9461SMike Marshall case ORANGEFS_VFS_OP_GETATTR:
30575e9461SMike Marshall fsid = op->upcall.req.getattr.refn.fs_id;
31575e9461SMike Marshall break;
32575e9461SMike Marshall case ORANGEFS_VFS_OP_REMOVE:
33575e9461SMike Marshall fsid = op->upcall.req.remove.parent_refn.fs_id;
34575e9461SMike Marshall break;
35575e9461SMike Marshall case ORANGEFS_VFS_OP_MKDIR:
36575e9461SMike Marshall fsid = op->upcall.req.mkdir.parent_refn.fs_id;
37575e9461SMike Marshall break;
38575e9461SMike Marshall case ORANGEFS_VFS_OP_READDIR:
39575e9461SMike Marshall fsid = op->upcall.req.readdir.refn.fs_id;
40575e9461SMike Marshall break;
41575e9461SMike Marshall case ORANGEFS_VFS_OP_SETATTR:
42575e9461SMike Marshall fsid = op->upcall.req.setattr.refn.fs_id;
43575e9461SMike Marshall break;
44575e9461SMike Marshall case ORANGEFS_VFS_OP_SYMLINK:
45575e9461SMike Marshall fsid = op->upcall.req.sym.parent_refn.fs_id;
46575e9461SMike Marshall break;
47575e9461SMike Marshall case ORANGEFS_VFS_OP_RENAME:
48575e9461SMike Marshall fsid = op->upcall.req.rename.old_parent_refn.fs_id;
49575e9461SMike Marshall break;
50575e9461SMike Marshall case ORANGEFS_VFS_OP_STATFS:
51575e9461SMike Marshall fsid = op->upcall.req.statfs.fs_id;
52575e9461SMike Marshall break;
53575e9461SMike Marshall case ORANGEFS_VFS_OP_TRUNCATE:
54575e9461SMike Marshall fsid = op->upcall.req.truncate.refn.fs_id;
55575e9461SMike Marshall break;
566eaff8c7SMartin Brandenburg case ORANGEFS_VFS_OP_RA_FLUSH:
57575e9461SMike Marshall fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
58575e9461SMike Marshall break;
59575e9461SMike Marshall case ORANGEFS_VFS_OP_FS_UMOUNT:
60575e9461SMike Marshall fsid = op->upcall.req.fs_umount.fs_id;
61575e9461SMike Marshall break;
62575e9461SMike Marshall case ORANGEFS_VFS_OP_GETXATTR:
63575e9461SMike Marshall fsid = op->upcall.req.getxattr.refn.fs_id;
64575e9461SMike Marshall break;
65575e9461SMike Marshall case ORANGEFS_VFS_OP_SETXATTR:
66575e9461SMike Marshall fsid = op->upcall.req.setxattr.refn.fs_id;
67575e9461SMike Marshall break;
68575e9461SMike Marshall case ORANGEFS_VFS_OP_LISTXATTR:
69575e9461SMike Marshall fsid = op->upcall.req.listxattr.refn.fs_id;
70575e9461SMike Marshall break;
71575e9461SMike Marshall case ORANGEFS_VFS_OP_REMOVEXATTR:
72575e9461SMike Marshall fsid = op->upcall.req.removexattr.refn.fs_id;
73575e9461SMike Marshall break;
74575e9461SMike Marshall case ORANGEFS_VFS_OP_FSYNC:
75575e9461SMike Marshall fsid = op->upcall.req.fsync.refn.fs_id;
76575e9461SMike Marshall break;
77575e9461SMike Marshall default:
78575e9461SMike Marshall break;
79575e9461SMike Marshall }
80575e9461SMike Marshall }
81575e9461SMike Marshall return fsid;
82575e9461SMike Marshall }
83575e9461SMike Marshall
orangefs_inode_flags(struct ORANGEFS_sys_attr_s * attrs)84394f647eSMartin Brandenburg static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
85575e9461SMike Marshall {
86394f647eSMartin Brandenburg int flags = 0;
87575e9461SMike Marshall if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
88394f647eSMartin Brandenburg flags |= S_IMMUTABLE;
89575e9461SMike Marshall else
90394f647eSMartin Brandenburg flags &= ~S_IMMUTABLE;
91575e9461SMike Marshall if (attrs->flags & ORANGEFS_APPEND_FL)
92394f647eSMartin Brandenburg flags |= S_APPEND;
93575e9461SMike Marshall else
94394f647eSMartin Brandenburg flags &= ~S_APPEND;
95575e9461SMike Marshall if (attrs->flags & ORANGEFS_NOATIME_FL)
96394f647eSMartin Brandenburg flags |= S_NOATIME;
97575e9461SMike Marshall else
98394f647eSMartin Brandenburg flags &= ~S_NOATIME;
99394f647eSMartin Brandenburg return flags;
100394f647eSMartin Brandenburg }
101575e9461SMike Marshall
orangefs_inode_perms(struct ORANGEFS_sys_attr_s * attrs)102394f647eSMartin Brandenburg static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
103394f647eSMartin Brandenburg {
104394f647eSMartin Brandenburg int perm_mode = 0;
105394f647eSMartin Brandenburg
106394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_EXECUTE)
107394f647eSMartin Brandenburg perm_mode |= S_IXOTH;
108394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_WRITE)
109394f647eSMartin Brandenburg perm_mode |= S_IWOTH;
110394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_READ)
111394f647eSMartin Brandenburg perm_mode |= S_IROTH;
112394f647eSMartin Brandenburg
113394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_EXECUTE)
114394f647eSMartin Brandenburg perm_mode |= S_IXGRP;
115394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_WRITE)
116394f647eSMartin Brandenburg perm_mode |= S_IWGRP;
117394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_READ)
118394f647eSMartin Brandenburg perm_mode |= S_IRGRP;
119394f647eSMartin Brandenburg
120394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_EXECUTE)
121394f647eSMartin Brandenburg perm_mode |= S_IXUSR;
122394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_WRITE)
123394f647eSMartin Brandenburg perm_mode |= S_IWUSR;
124394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_READ)
125394f647eSMartin Brandenburg perm_mode |= S_IRUSR;
126394f647eSMartin Brandenburg
127394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_SGID)
128394f647eSMartin Brandenburg perm_mode |= S_ISGID;
129394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_SUID)
130394f647eSMartin Brandenburg perm_mode |= S_ISUID;
131394f647eSMartin Brandenburg
132394f647eSMartin Brandenburg return perm_mode;
133575e9461SMike Marshall }
134575e9461SMike Marshall
135575e9461SMike Marshall /*
136575e9461SMike Marshall * NOTE: in kernel land, we never use the sys_attr->link_target for
137575e9461SMike Marshall * anything, so don't bother copying it into the sys_attr object here.
138575e9461SMike Marshall */
copy_attributes_from_inode(struct inode * inode,struct ORANGEFS_sys_attr_s * attrs)139afd9fb2aSMartin Brandenburg static inline void copy_attributes_from_inode(struct inode *inode,
140afd9fb2aSMartin Brandenburg struct ORANGEFS_sys_attr_s *attrs)
141575e9461SMike Marshall {
142afd9fb2aSMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
143575e9461SMike Marshall attrs->mask = 0;
144afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid & ATTR_UID) {
145afd9fb2aSMartin Brandenburg attrs->owner = from_kuid(&init_user_ns, inode->i_uid);
146575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_UID;
147575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
148575e9461SMike Marshall }
149afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid & ATTR_GID) {
150afd9fb2aSMartin Brandenburg attrs->group = from_kgid(&init_user_ns, inode->i_gid);
151575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_GID;
152575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
153575e9461SMike Marshall }
154575e9461SMike Marshall
155afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid & ATTR_ATIME) {
156575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
157afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid & ATTR_ATIME_SET) {
158afd9fb2aSMartin Brandenburg attrs->atime = (time64_t)inode->i_atime.tv_sec;
159575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
160575e9461SMike Marshall }
161575e9461SMike Marshall }
162afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid & ATTR_MTIME) {
163575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
164afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid & ATTR_MTIME_SET) {
165afd9fb2aSMartin Brandenburg attrs->mtime = (time64_t)inode->i_mtime.tv_sec;
166575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
167575e9461SMike Marshall }
168575e9461SMike Marshall }
169afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid & ATTR_CTIME)
170575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
171575e9461SMike Marshall
172575e9461SMike Marshall /*
17395f5f88fSMike Marshall * ORANGEFS cannot set size with a setattr operation. Probably not
17495f5f88fSMike Marshall * likely to be requested through the VFS, but just in case, don't
17595f5f88fSMike Marshall * worry about ATTR_SIZE
176575e9461SMike Marshall */
177575e9461SMike Marshall
178afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid & ATTR_MODE) {
179afd9fb2aSMartin Brandenburg attrs->perms = ORANGEFS_util_translate_mode(inode->i_mode);
180575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
181575e9461SMike Marshall }
182575e9461SMike Marshall }
183575e9461SMike Marshall
orangefs_inode_type(enum orangefs_ds_type objtype)1843c9cf98dSMartin Brandenburg static int orangefs_inode_type(enum orangefs_ds_type objtype)
1853c9cf98dSMartin Brandenburg {
1863c9cf98dSMartin Brandenburg if (objtype == ORANGEFS_TYPE_METAFILE)
1873c9cf98dSMartin Brandenburg return S_IFREG;
1883c9cf98dSMartin Brandenburg else if (objtype == ORANGEFS_TYPE_DIRECTORY)
1893c9cf98dSMartin Brandenburg return S_IFDIR;
1903c9cf98dSMartin Brandenburg else if (objtype == ORANGEFS_TYPE_SYMLINK)
1913c9cf98dSMartin Brandenburg return S_IFLNK;
1923c9cf98dSMartin Brandenburg else
1933c9cf98dSMartin Brandenburg return -1;
1943c9cf98dSMartin Brandenburg }
1953c9cf98dSMartin Brandenburg
orangefs_make_bad_inode(struct inode * inode)1964d0cac7eSMartin Brandenburg static void orangefs_make_bad_inode(struct inode *inode)
1974d0cac7eSMartin Brandenburg {
1984d0cac7eSMartin Brandenburg if (is_root_handle(inode)) {
1994d0cac7eSMartin Brandenburg /*
2004d0cac7eSMartin Brandenburg * if this occurs, the pvfs2-client-core was killed but we
2014d0cac7eSMartin Brandenburg * can't afford to lose the inode operations and such
2024d0cac7eSMartin Brandenburg * associated with the root handle in any case.
2034d0cac7eSMartin Brandenburg */
2044d0cac7eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG,
2054d0cac7eSMartin Brandenburg "*** NOT making bad root inode %pU\n",
2064d0cac7eSMartin Brandenburg get_khandle_from_ino(inode));
2074d0cac7eSMartin Brandenburg } else {
2084d0cac7eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG,
2094d0cac7eSMartin Brandenburg "*** making bad inode %pU\n",
2104d0cac7eSMartin Brandenburg get_khandle_from_ino(inode));
2114d0cac7eSMartin Brandenburg make_bad_inode(inode);
2124d0cac7eSMartin Brandenburg }
2134d0cac7eSMartin Brandenburg }
2144d0cac7eSMartin Brandenburg
orangefs_inode_is_stale(struct inode * inode,struct ORANGEFS_sys_attr_s * attrs,char * link_target)215480e5ae9SMartin Brandenburg static int orangefs_inode_is_stale(struct inode *inode,
21626662633SMartin Brandenburg struct ORANGEFS_sys_attr_s *attrs, char *link_target)
21726662633SMartin Brandenburg {
21826662633SMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
21926662633SMartin Brandenburg int type = orangefs_inode_type(attrs->objtype);
22026662633SMartin Brandenburg /*
22126662633SMartin Brandenburg * If the inode type or symlink target have changed then this
22226662633SMartin Brandenburg * inode is stale.
22326662633SMartin Brandenburg */
224e89f00d6SAl Viro if (type == -1 || inode_wrong_type(inode, type)) {
22526662633SMartin Brandenburg orangefs_make_bad_inode(inode);
22626662633SMartin Brandenburg return 1;
22726662633SMartin Brandenburg }
22826662633SMartin Brandenburg if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
22926662633SMartin Brandenburg link_target, ORANGEFS_NAME_MAX)) {
23026662633SMartin Brandenburg orangefs_make_bad_inode(inode);
23126662633SMartin Brandenburg return 1;
23226662633SMartin Brandenburg }
23326662633SMartin Brandenburg return 0;
23426662633SMartin Brandenburg }
23526662633SMartin Brandenburg
orangefs_inode_getattr(struct inode * inode,int flags)2368b60785cSMartin Brandenburg int orangefs_inode_getattr(struct inode *inode, int flags)
2373c9cf98dSMartin Brandenburg {
2383c9cf98dSMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
2393c9cf98dSMartin Brandenburg struct orangefs_kernel_op_s *new_op;
2409f8fd53cSMartin Brandenburg loff_t inode_size;
24126662633SMartin Brandenburg int ret, type;
2423c9cf98dSMartin Brandenburg
2435e4f606eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU flags %d\n",
2445e4f606eSMartin Brandenburg __func__, get_khandle_from_ino(inode), flags);
2453c9cf98dSMartin Brandenburg
246afd9fb2aSMartin Brandenburg again:
2475e4f606eSMartin Brandenburg spin_lock(&inode->i_lock);
2488b60785cSMartin Brandenburg /* Must have all the attributes in the mask and be within cache time. */
2495e4f606eSMartin Brandenburg if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
25085ac799cSMartin Brandenburg orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
251afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid) {
252afd9fb2aSMartin Brandenburg spin_unlock(&inode->i_lock);
253afd9fb2aSMartin Brandenburg write_inode_now(inode, 1);
254afd9fb2aSMartin Brandenburg goto again;
255afd9fb2aSMartin Brandenburg }
2565e4f606eSMartin Brandenburg spin_unlock(&inode->i_lock);
25771680c18SMartin Brandenburg return 0;
2585e4f606eSMartin Brandenburg }
2595e4f606eSMartin Brandenburg spin_unlock(&inode->i_lock);
26071680c18SMartin Brandenburg
2613c9cf98dSMartin Brandenburg new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
2623c9cf98dSMartin Brandenburg if (!new_op)
2633c9cf98dSMartin Brandenburg return -ENOMEM;
2643c9cf98dSMartin Brandenburg new_op->upcall.req.getattr.refn = orangefs_inode->refn;
26568a24a6cSMartin Brandenburg /*
26668a24a6cSMartin Brandenburg * Size is the hardest attribute to get. The incremental cost of any
26768a24a6cSMartin Brandenburg * other attribute is essentially zero.
26868a24a6cSMartin Brandenburg */
2698b60785cSMartin Brandenburg if (flags)
27071680c18SMartin Brandenburg new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
27168a24a6cSMartin Brandenburg else
27268a24a6cSMartin Brandenburg new_op->upcall.req.getattr.mask =
27368a24a6cSMartin Brandenburg ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
2743c9cf98dSMartin Brandenburg
2753c9cf98dSMartin Brandenburg ret = service_operation(new_op, __func__,
2763c9cf98dSMartin Brandenburg get_interruptible_flag(inode));
2773c9cf98dSMartin Brandenburg if (ret != 0)
2783c9cf98dSMartin Brandenburg goto out;
2793c9cf98dSMartin Brandenburg
280afd9fb2aSMartin Brandenburg again2:
2815e4f606eSMartin Brandenburg spin_lock(&inode->i_lock);
2825e4f606eSMartin Brandenburg /* Must have all the attributes in the mask and be within cache time. */
2835e4f606eSMartin Brandenburg if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
28485ac799cSMartin Brandenburg orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
285afd9fb2aSMartin Brandenburg if (orangefs_inode->attr_valid) {
286afd9fb2aSMartin Brandenburg spin_unlock(&inode->i_lock);
287afd9fb2aSMartin Brandenburg write_inode_now(inode, 1);
288afd9fb2aSMartin Brandenburg goto again2;
289afd9fb2aSMartin Brandenburg }
29085ac799cSMartin Brandenburg if (inode->i_state & I_DIRTY_PAGES) {
29185ac799cSMartin Brandenburg ret = 0;
29285ac799cSMartin Brandenburg goto out_unlock;
29385ac799cSMartin Brandenburg }
2945e4f606eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n",
2955e4f606eSMartin Brandenburg __func__);
2965e4f606eSMartin Brandenburg ret = 0;
2975e4f606eSMartin Brandenburg goto out_unlock;
2985e4f606eSMartin Brandenburg }
2995e4f606eSMartin Brandenburg
3008b60785cSMartin Brandenburg if (!(flags & ORANGEFS_GETATTR_NEW)) {
301480e5ae9SMartin Brandenburg ret = orangefs_inode_is_stale(inode,
30226662633SMartin Brandenburg &new_op->downcall.resp.getattr.attributes,
30326662633SMartin Brandenburg new_op->downcall.resp.getattr.link_target);
30426662633SMartin Brandenburg if (ret) {
3053c9cf98dSMartin Brandenburg ret = -ESTALE;
3065e4f606eSMartin Brandenburg goto out_unlock;
3073c9cf98dSMartin Brandenburg }
308480e5ae9SMartin Brandenburg }
3093c9cf98dSMartin Brandenburg
310480e5ae9SMartin Brandenburg type = orangefs_inode_type(new_op->
311480e5ae9SMartin Brandenburg downcall.resp.getattr.attributes.objtype);
31226662633SMartin Brandenburg switch (type) {
3133c9cf98dSMartin Brandenburg case S_IFREG:
3143c9cf98dSMartin Brandenburg inode->i_flags = orangefs_inode_flags(&new_op->
3153c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes);
3168b60785cSMartin Brandenburg if (flags) {
3173c9cf98dSMartin Brandenburg inode_size = (loff_t)new_op->
3183c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.size;
3193c9cf98dSMartin Brandenburg inode->i_size = inode_size;
3209f8fd53cSMartin Brandenburg inode->i_blkbits = ffs(new_op->downcall.resp.getattr.
3219f8fd53cSMartin Brandenburg attributes.blksize);
3223c9cf98dSMartin Brandenburg inode->i_bytes = inode_size;
3233c9cf98dSMartin Brandenburg inode->i_blocks =
3249f8fd53cSMartin Brandenburg (inode_size + 512 - inode_size % 512)/512;
32568a24a6cSMartin Brandenburg }
3263c9cf98dSMartin Brandenburg break;
3273c9cf98dSMartin Brandenburg case S_IFDIR:
3288b60785cSMartin Brandenburg if (flags) {
32909cbfeafSKirill A. Shutemov inode->i_size = PAGE_SIZE;
3303c9cf98dSMartin Brandenburg inode_set_bytes(inode, inode->i_size);
33168a24a6cSMartin Brandenburg }
3323c9cf98dSMartin Brandenburg set_nlink(inode, 1);
3333c9cf98dSMartin Brandenburg break;
3343c9cf98dSMartin Brandenburg case S_IFLNK:
3358b60785cSMartin Brandenburg if (flags & ORANGEFS_GETATTR_NEW) {
3363c9cf98dSMartin Brandenburg inode->i_size = (loff_t)strlen(new_op->
3373c9cf98dSMartin Brandenburg downcall.resp.getattr.link_target);
3382eacea74SMartin Brandenburg ret = strscpy(orangefs_inode->link_target,
3393c9cf98dSMartin Brandenburg new_op->downcall.resp.getattr.link_target,
3403c9cf98dSMartin Brandenburg ORANGEFS_NAME_MAX);
3412eacea74SMartin Brandenburg if (ret == -E2BIG) {
3422eacea74SMartin Brandenburg ret = -EIO;
3435e4f606eSMartin Brandenburg goto out_unlock;
3442eacea74SMartin Brandenburg }
345e8da254cSMartin Brandenburg inode->i_link = orangefs_inode->link_target;
3463c9cf98dSMartin Brandenburg }
3473c9cf98dSMartin Brandenburg break;
348480e5ae9SMartin Brandenburg /* i.e. -1 */
349480e5ae9SMartin Brandenburg default:
350480e5ae9SMartin Brandenburg /* XXX: ESTALE? This is what is done if it is not new. */
351480e5ae9SMartin Brandenburg orangefs_make_bad_inode(inode);
352480e5ae9SMartin Brandenburg ret = -ESTALE;
3535e4f606eSMartin Brandenburg goto out_unlock;
3543c9cf98dSMartin Brandenburg }
3553c9cf98dSMartin Brandenburg
3563c9cf98dSMartin Brandenburg inode->i_uid = make_kuid(&init_user_ns, new_op->
3573c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.owner);
3583c9cf98dSMartin Brandenburg inode->i_gid = make_kgid(&init_user_ns, new_op->
3593c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.group);
3603c9cf98dSMartin Brandenburg inode->i_atime.tv_sec = (time64_t)new_op->
3613c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.atime;
3623c9cf98dSMartin Brandenburg inode->i_mtime.tv_sec = (time64_t)new_op->
3633c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.mtime;
364*0971a799SJeff Layton inode_set_ctime(inode,
365*0971a799SJeff Layton (time64_t)new_op->downcall.resp.getattr.attributes.ctime,
366*0971a799SJeff Layton 0);
3673c9cf98dSMartin Brandenburg inode->i_atime.tv_nsec = 0;
3683c9cf98dSMartin Brandenburg inode->i_mtime.tv_nsec = 0;
3693c9cf98dSMartin Brandenburg
3703c9cf98dSMartin Brandenburg /* special case: mark the root inode as sticky */
37126662633SMartin Brandenburg inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
3723c9cf98dSMartin Brandenburg orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
3733c9cf98dSMartin Brandenburg
3741d503617SMartin Brandenburg orangefs_inode->getattr_time = jiffies +
3751d503617SMartin Brandenburg orangefs_getattr_timeout_msecs*HZ/1000;
3763c9cf98dSMartin Brandenburg ret = 0;
3775e4f606eSMartin Brandenburg out_unlock:
3785e4f606eSMartin Brandenburg spin_unlock(&inode->i_lock);
3793c9cf98dSMartin Brandenburg out:
3803c9cf98dSMartin Brandenburg op_release(new_op);
3813c9cf98dSMartin Brandenburg return ret;
3823c9cf98dSMartin Brandenburg }
3833c9cf98dSMartin Brandenburg
orangefs_inode_check_changed(struct inode * inode)3845859d77eSMartin Brandenburg int orangefs_inode_check_changed(struct inode *inode)
3855859d77eSMartin Brandenburg {
3865859d77eSMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
3875859d77eSMartin Brandenburg struct orangefs_kernel_op_s *new_op;
3885859d77eSMartin Brandenburg int ret;
3895859d77eSMartin Brandenburg
3905859d77eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
3915859d77eSMartin Brandenburg get_khandle_from_ino(inode));
3925859d77eSMartin Brandenburg
3935859d77eSMartin Brandenburg new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
3945859d77eSMartin Brandenburg if (!new_op)
3955859d77eSMartin Brandenburg return -ENOMEM;
3965859d77eSMartin Brandenburg new_op->upcall.req.getattr.refn = orangefs_inode->refn;
3975859d77eSMartin Brandenburg new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
3985859d77eSMartin Brandenburg ORANGEFS_ATTR_SYS_LNK_TARGET;
3995859d77eSMartin Brandenburg
4005859d77eSMartin Brandenburg ret = service_operation(new_op, __func__,
4015859d77eSMartin Brandenburg get_interruptible_flag(inode));
4025859d77eSMartin Brandenburg if (ret != 0)
4035859d77eSMartin Brandenburg goto out;
4045859d77eSMartin Brandenburg
405480e5ae9SMartin Brandenburg ret = orangefs_inode_is_stale(inode,
40626662633SMartin Brandenburg &new_op->downcall.resp.getattr.attributes,
40726662633SMartin Brandenburg new_op->downcall.resp.getattr.link_target);
4085859d77eSMartin Brandenburg out:
4095859d77eSMartin Brandenburg op_release(new_op);
4105859d77eSMartin Brandenburg return ret;
4115859d77eSMartin Brandenburg }
4125859d77eSMartin Brandenburg
413575e9461SMike Marshall /*
414575e9461SMike Marshall * issues a orangefs setattr request to make sure the new attribute values
415575e9461SMike Marshall * take effect if successful. returns 0 on success; -errno otherwise
416575e9461SMike Marshall */
orangefs_inode_setattr(struct inode * inode)417afd9fb2aSMartin Brandenburg int orangefs_inode_setattr(struct inode *inode)
418575e9461SMike Marshall {
419575e9461SMike Marshall struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
420575e9461SMike Marshall struct orangefs_kernel_op_s *new_op;
421575e9461SMike Marshall int ret;
422575e9461SMike Marshall
423575e9461SMike Marshall new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
424575e9461SMike Marshall if (!new_op)
425575e9461SMike Marshall return -ENOMEM;
426575e9461SMike Marshall
427afd9fb2aSMartin Brandenburg spin_lock(&inode->i_lock);
428afd9fb2aSMartin Brandenburg new_op->upcall.uid = from_kuid(&init_user_ns, orangefs_inode->attr_uid);
429afd9fb2aSMartin Brandenburg new_op->upcall.gid = from_kgid(&init_user_ns, orangefs_inode->attr_gid);
430575e9461SMike Marshall new_op->upcall.req.setattr.refn = orangefs_inode->refn;
431afd9fb2aSMartin Brandenburg copy_attributes_from_inode(inode,
432afd9fb2aSMartin Brandenburg &new_op->upcall.req.setattr.attributes);
433afd9fb2aSMartin Brandenburg orangefs_inode->attr_valid = 0;
4348a88bbceSMartin Brandenburg if (!new_op->upcall.req.setattr.attributes.mask) {
4358a88bbceSMartin Brandenburg spin_unlock(&inode->i_lock);
4368a88bbceSMartin Brandenburg op_release(new_op);
4378a88bbceSMartin Brandenburg return 0;
4388a88bbceSMartin Brandenburg }
439afd9fb2aSMartin Brandenburg spin_unlock(&inode->i_lock);
440afd9fb2aSMartin Brandenburg
441575e9461SMike Marshall ret = service_operation(new_op, __func__,
4420dcac0f7SMartin Brandenburg get_interruptible_flag(inode) | ORANGEFS_OP_WRITEBACK);
443575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG,
444afd9fb2aSMartin Brandenburg "orangefs_inode_setattr: returning %d\n", ret);
445afd9fb2aSMartin Brandenburg if (ret)
446afd9fb2aSMartin Brandenburg orangefs_make_bad_inode(inode);
447575e9461SMike Marshall
448575e9461SMike Marshall op_release(new_op);
449575e9461SMike Marshall
450a55f2d86SMartin Brandenburg if (ret == 0)
4518bbb20a8SMartin Brandenburg orangefs_inode->getattr_time = jiffies - 1;
452575e9461SMike Marshall return ret;
453575e9461SMike Marshall }
454575e9461SMike Marshall
455575e9461SMike Marshall /*
456575e9461SMike Marshall * The following is a very dirty hack that is now a permanent part of the
457575e9461SMike Marshall * ORANGEFS protocol. See protocol.h for more error definitions.
458575e9461SMike Marshall */
459575e9461SMike Marshall
460575e9461SMike Marshall /* The order matches include/orangefs-types.h in the OrangeFS source. */
461575e9461SMike Marshall static int PINT_errno_mapping[] = {
462575e9461SMike Marshall 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
463575e9461SMike Marshall EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
464575e9461SMike Marshall EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
465575e9461SMike Marshall ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
466575e9461SMike Marshall EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
467575e9461SMike Marshall EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
468575e9461SMike Marshall ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
469575e9461SMike Marshall EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
470575e9461SMike Marshall ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
471575e9461SMike Marshall EACCES, ECONNRESET, ERANGE
472575e9461SMike Marshall };
473575e9461SMike Marshall
orangefs_normalize_to_errno(__s32 error_code)474575e9461SMike Marshall int orangefs_normalize_to_errno(__s32 error_code)
475575e9461SMike Marshall {
476575e9461SMike Marshall __u32 i;
477575e9461SMike Marshall
478575e9461SMike Marshall /* Success */
479575e9461SMike Marshall if (error_code == 0) {
480575e9461SMike Marshall return 0;
481575e9461SMike Marshall /*
482575e9461SMike Marshall * This shouldn't ever happen. If it does it should be fixed on the
483575e9461SMike Marshall * server.
484575e9461SMike Marshall */
485575e9461SMike Marshall } else if (error_code > 0) {
486bc8282a7SMasanari Iida gossip_err("orangefs: error status received.\n");
487575e9461SMike Marshall gossip_err("orangefs: assuming error code is inverted.\n");
488575e9461SMike Marshall error_code = -error_code;
489575e9461SMike Marshall }
490575e9461SMike Marshall
491575e9461SMike Marshall /*
492575e9461SMike Marshall * XXX: This is very bad since error codes from ORANGEFS may not be
493575e9461SMike Marshall * suitable for return into userspace.
494575e9461SMike Marshall */
495575e9461SMike Marshall
496575e9461SMike Marshall /*
497575e9461SMike Marshall * Convert ORANGEFS error values into errno values suitable for return
498575e9461SMike Marshall * from the kernel.
499575e9461SMike Marshall */
500575e9461SMike Marshall if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
501575e9461SMike Marshall if (((-error_code) &
502575e9461SMike Marshall (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
503575e9461SMike Marshall ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
504575e9461SMike Marshall /*
505575e9461SMike Marshall * cancellation error codes generally correspond to
506575e9461SMike Marshall * a timeout from the client's perspective
507575e9461SMike Marshall */
508575e9461SMike Marshall error_code = -ETIMEDOUT;
509575e9461SMike Marshall } else {
510575e9461SMike Marshall /* assume a default error code */
51195f5f88fSMike Marshall gossip_err("%s: bad error code :%d:.\n",
51295f5f88fSMike Marshall __func__,
51395f5f88fSMike Marshall error_code);
514575e9461SMike Marshall error_code = -EINVAL;
515575e9461SMike Marshall }
516575e9461SMike Marshall
517575e9461SMike Marshall /* Convert ORANGEFS encoded errno values into regular errno values. */
518575e9461SMike Marshall } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
519575e9461SMike Marshall i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
520296200d3SJérémy Lefaure if (i < ARRAY_SIZE(PINT_errno_mapping))
521575e9461SMike Marshall error_code = -PINT_errno_mapping[i];
522575e9461SMike Marshall else
523575e9461SMike Marshall error_code = -EINVAL;
524575e9461SMike Marshall
525575e9461SMike Marshall /*
526575e9461SMike Marshall * Only ORANGEFS protocol error codes should ever come here. Otherwise
527575e9461SMike Marshall * there is a bug somewhere.
528575e9461SMike Marshall */
529575e9461SMike Marshall } else {
53095f5f88fSMike Marshall gossip_err("%s: unknown error code.\n", __func__);
531cf546ab6SMike Marshall error_code = -EINVAL;
532575e9461SMike Marshall }
533575e9461SMike Marshall return error_code;
534575e9461SMike Marshall }
535575e9461SMike Marshall
536575e9461SMike Marshall #define NUM_MODES 11
ORANGEFS_util_translate_mode(int mode)537575e9461SMike Marshall __s32 ORANGEFS_util_translate_mode(int mode)
538575e9461SMike Marshall {
539575e9461SMike Marshall int ret = 0;
540575e9461SMike Marshall int i = 0;
541575e9461SMike Marshall static int modes[NUM_MODES] = {
542575e9461SMike Marshall S_IXOTH, S_IWOTH, S_IROTH,
543575e9461SMike Marshall S_IXGRP, S_IWGRP, S_IRGRP,
544575e9461SMike Marshall S_IXUSR, S_IWUSR, S_IRUSR,
545575e9461SMike Marshall S_ISGID, S_ISUID
546575e9461SMike Marshall };
547575e9461SMike Marshall static int orangefs_modes[NUM_MODES] = {
548575e9461SMike Marshall ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
549575e9461SMike Marshall ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
550575e9461SMike Marshall ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
551575e9461SMike Marshall ORANGEFS_G_SGID, ORANGEFS_U_SUID
552575e9461SMike Marshall };
553575e9461SMike Marshall
554575e9461SMike Marshall for (i = 0; i < NUM_MODES; i++)
555575e9461SMike Marshall if (mode & modes[i])
556575e9461SMike Marshall ret |= orangefs_modes[i];
557575e9461SMike Marshall
558575e9461SMike Marshall return ret;
559575e9461SMike Marshall }
560575e9461SMike Marshall #undef NUM_MODES
561