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 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 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 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 */ 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 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 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 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 */ 22426662633SMartin Brandenburg if (type == -1 || !(inode->i_mode & 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 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)) || 250afd9fb2aSMartin Brandenburg orangefs_inode->attr_valid) { 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)) || 284afd9fb2aSMartin Brandenburg orangefs_inode->attr_valid) { 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 } 2905e4f606eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n", 2915e4f606eSMartin Brandenburg __func__); 2925e4f606eSMartin Brandenburg ret = 0; 2935e4f606eSMartin Brandenburg goto out_unlock; 2945e4f606eSMartin Brandenburg } 2955e4f606eSMartin Brandenburg 2968b60785cSMartin Brandenburg if (!(flags & ORANGEFS_GETATTR_NEW)) { 297480e5ae9SMartin Brandenburg ret = orangefs_inode_is_stale(inode, 29826662633SMartin Brandenburg &new_op->downcall.resp.getattr.attributes, 29926662633SMartin Brandenburg new_op->downcall.resp.getattr.link_target); 30026662633SMartin Brandenburg if (ret) { 3013c9cf98dSMartin Brandenburg ret = -ESTALE; 3025e4f606eSMartin Brandenburg goto out_unlock; 3033c9cf98dSMartin Brandenburg } 304480e5ae9SMartin Brandenburg } 3053c9cf98dSMartin Brandenburg 306480e5ae9SMartin Brandenburg type = orangefs_inode_type(new_op-> 307480e5ae9SMartin Brandenburg downcall.resp.getattr.attributes.objtype); 30826662633SMartin Brandenburg switch (type) { 3093c9cf98dSMartin Brandenburg case S_IFREG: 3103c9cf98dSMartin Brandenburg inode->i_flags = orangefs_inode_flags(&new_op-> 3113c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes); 3128b60785cSMartin Brandenburg if (flags) { 3133c9cf98dSMartin Brandenburg inode_size = (loff_t)new_op-> 3143c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.size; 3153c9cf98dSMartin Brandenburg inode->i_size = inode_size; 3169f8fd53cSMartin Brandenburg inode->i_blkbits = ffs(new_op->downcall.resp.getattr. 3179f8fd53cSMartin Brandenburg attributes.blksize); 3183c9cf98dSMartin Brandenburg inode->i_bytes = inode_size; 3193c9cf98dSMartin Brandenburg inode->i_blocks = 3209f8fd53cSMartin Brandenburg (inode_size + 512 - inode_size % 512)/512; 32168a24a6cSMartin Brandenburg } 3223c9cf98dSMartin Brandenburg break; 3233c9cf98dSMartin Brandenburg case S_IFDIR: 3248b60785cSMartin Brandenburg if (flags) { 32509cbfeafSKirill A. Shutemov inode->i_size = PAGE_SIZE; 3263c9cf98dSMartin Brandenburg inode_set_bytes(inode, inode->i_size); 32768a24a6cSMartin Brandenburg } 3283c9cf98dSMartin Brandenburg set_nlink(inode, 1); 3293c9cf98dSMartin Brandenburg break; 3303c9cf98dSMartin Brandenburg case S_IFLNK: 3318b60785cSMartin Brandenburg if (flags & ORANGEFS_GETATTR_NEW) { 3323c9cf98dSMartin Brandenburg inode->i_size = (loff_t)strlen(new_op-> 3333c9cf98dSMartin Brandenburg downcall.resp.getattr.link_target); 3342eacea74SMartin Brandenburg ret = strscpy(orangefs_inode->link_target, 3353c9cf98dSMartin Brandenburg new_op->downcall.resp.getattr.link_target, 3363c9cf98dSMartin Brandenburg ORANGEFS_NAME_MAX); 3372eacea74SMartin Brandenburg if (ret == -E2BIG) { 3382eacea74SMartin Brandenburg ret = -EIO; 3395e4f606eSMartin Brandenburg goto out_unlock; 3402eacea74SMartin Brandenburg } 341e8da254cSMartin Brandenburg inode->i_link = orangefs_inode->link_target; 3423c9cf98dSMartin Brandenburg } 3433c9cf98dSMartin Brandenburg break; 344480e5ae9SMartin Brandenburg /* i.e. -1 */ 345480e5ae9SMartin Brandenburg default: 346480e5ae9SMartin Brandenburg /* XXX: ESTALE? This is what is done if it is not new. */ 347480e5ae9SMartin Brandenburg orangefs_make_bad_inode(inode); 348480e5ae9SMartin Brandenburg ret = -ESTALE; 3495e4f606eSMartin Brandenburg goto out_unlock; 3503c9cf98dSMartin Brandenburg } 3513c9cf98dSMartin Brandenburg 3523c9cf98dSMartin Brandenburg inode->i_uid = make_kuid(&init_user_ns, new_op-> 3533c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.owner); 3543c9cf98dSMartin Brandenburg inode->i_gid = make_kgid(&init_user_ns, new_op-> 3553c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.group); 3563c9cf98dSMartin Brandenburg inode->i_atime.tv_sec = (time64_t)new_op-> 3573c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.atime; 3583c9cf98dSMartin Brandenburg inode->i_mtime.tv_sec = (time64_t)new_op-> 3593c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.mtime; 3603c9cf98dSMartin Brandenburg inode->i_ctime.tv_sec = (time64_t)new_op-> 3613c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.ctime; 3623c9cf98dSMartin Brandenburg inode->i_atime.tv_nsec = 0; 3633c9cf98dSMartin Brandenburg inode->i_mtime.tv_nsec = 0; 3643c9cf98dSMartin Brandenburg inode->i_ctime.tv_nsec = 0; 3653c9cf98dSMartin Brandenburg 3663c9cf98dSMartin Brandenburg /* special case: mark the root inode as sticky */ 36726662633SMartin Brandenburg inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) | 3683c9cf98dSMartin Brandenburg orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes); 3693c9cf98dSMartin Brandenburg 3701d503617SMartin Brandenburg orangefs_inode->getattr_time = jiffies + 3711d503617SMartin Brandenburg orangefs_getattr_timeout_msecs*HZ/1000; 3723c9cf98dSMartin Brandenburg ret = 0; 3735e4f606eSMartin Brandenburg out_unlock: 3745e4f606eSMartin Brandenburg spin_unlock(&inode->i_lock); 3753c9cf98dSMartin Brandenburg out: 3763c9cf98dSMartin Brandenburg op_release(new_op); 3773c9cf98dSMartin Brandenburg return ret; 3783c9cf98dSMartin Brandenburg } 3793c9cf98dSMartin Brandenburg 3805859d77eSMartin Brandenburg int orangefs_inode_check_changed(struct inode *inode) 3815859d77eSMartin Brandenburg { 3825859d77eSMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 3835859d77eSMartin Brandenburg struct orangefs_kernel_op_s *new_op; 3845859d77eSMartin Brandenburg int ret; 3855859d77eSMartin Brandenburg 3865859d77eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__, 3875859d77eSMartin Brandenburg get_khandle_from_ino(inode)); 3885859d77eSMartin Brandenburg 3895859d77eSMartin Brandenburg new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); 3905859d77eSMartin Brandenburg if (!new_op) 3915859d77eSMartin Brandenburg return -ENOMEM; 3925859d77eSMartin Brandenburg new_op->upcall.req.getattr.refn = orangefs_inode->refn; 3935859d77eSMartin Brandenburg new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE | 3945859d77eSMartin Brandenburg ORANGEFS_ATTR_SYS_LNK_TARGET; 3955859d77eSMartin Brandenburg 3965859d77eSMartin Brandenburg ret = service_operation(new_op, __func__, 3975859d77eSMartin Brandenburg get_interruptible_flag(inode)); 3985859d77eSMartin Brandenburg if (ret != 0) 3995859d77eSMartin Brandenburg goto out; 4005859d77eSMartin Brandenburg 401480e5ae9SMartin Brandenburg ret = orangefs_inode_is_stale(inode, 40226662633SMartin Brandenburg &new_op->downcall.resp.getattr.attributes, 40326662633SMartin Brandenburg new_op->downcall.resp.getattr.link_target); 4045859d77eSMartin Brandenburg out: 4055859d77eSMartin Brandenburg op_release(new_op); 4065859d77eSMartin Brandenburg return ret; 4075859d77eSMartin Brandenburg } 4085859d77eSMartin Brandenburg 409575e9461SMike Marshall /* 410575e9461SMike Marshall * issues a orangefs setattr request to make sure the new attribute values 411575e9461SMike Marshall * take effect if successful. returns 0 on success; -errno otherwise 412575e9461SMike Marshall */ 413afd9fb2aSMartin Brandenburg int orangefs_inode_setattr(struct inode *inode) 414575e9461SMike Marshall { 415575e9461SMike Marshall struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 416575e9461SMike Marshall struct orangefs_kernel_op_s *new_op; 417575e9461SMike Marshall int ret; 418575e9461SMike Marshall 419575e9461SMike Marshall new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR); 420575e9461SMike Marshall if (!new_op) 421575e9461SMike Marshall return -ENOMEM; 422575e9461SMike Marshall 423afd9fb2aSMartin Brandenburg spin_lock(&inode->i_lock); 424afd9fb2aSMartin Brandenburg new_op->upcall.uid = from_kuid(&init_user_ns, orangefs_inode->attr_uid); 425afd9fb2aSMartin Brandenburg new_op->upcall.gid = from_kgid(&init_user_ns, orangefs_inode->attr_gid); 426575e9461SMike Marshall new_op->upcall.req.setattr.refn = orangefs_inode->refn; 427afd9fb2aSMartin Brandenburg copy_attributes_from_inode(inode, 428afd9fb2aSMartin Brandenburg &new_op->upcall.req.setattr.attributes); 429afd9fb2aSMartin Brandenburg orangefs_inode->attr_valid = 0; 430afd9fb2aSMartin Brandenburg spin_unlock(&inode->i_lock); 431afd9fb2aSMartin Brandenburg 432575e9461SMike Marshall ret = service_operation(new_op, __func__, 433575e9461SMike Marshall get_interruptible_flag(inode)); 434575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 435afd9fb2aSMartin Brandenburg "orangefs_inode_setattr: returning %d\n", ret); 436afd9fb2aSMartin Brandenburg if (ret) 437afd9fb2aSMartin Brandenburg orangefs_make_bad_inode(inode); 438575e9461SMike Marshall 439575e9461SMike Marshall op_release(new_op); 440575e9461SMike Marshall 441a55f2d86SMartin Brandenburg if (ret == 0) 4428bbb20a8SMartin Brandenburg orangefs_inode->getattr_time = jiffies - 1; 443575e9461SMike Marshall return ret; 444575e9461SMike Marshall } 445575e9461SMike Marshall 446575e9461SMike Marshall /* 447575e9461SMike Marshall * The following is a very dirty hack that is now a permanent part of the 448575e9461SMike Marshall * ORANGEFS protocol. See protocol.h for more error definitions. 449575e9461SMike Marshall */ 450575e9461SMike Marshall 451575e9461SMike Marshall /* The order matches include/orangefs-types.h in the OrangeFS source. */ 452575e9461SMike Marshall static int PINT_errno_mapping[] = { 453575e9461SMike Marshall 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM, 454575e9461SMike Marshall EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE, 455575e9461SMike Marshall EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG, 456575e9461SMike Marshall ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH, 457575e9461SMike Marshall EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM, 458575e9461SMike Marshall EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE, 459575e9461SMike Marshall ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE, 460575e9461SMike Marshall EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS, 461575e9461SMike Marshall ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY, 462575e9461SMike Marshall EACCES, ECONNRESET, ERANGE 463575e9461SMike Marshall }; 464575e9461SMike Marshall 465575e9461SMike Marshall int orangefs_normalize_to_errno(__s32 error_code) 466575e9461SMike Marshall { 467575e9461SMike Marshall __u32 i; 468575e9461SMike Marshall 469575e9461SMike Marshall /* Success */ 470575e9461SMike Marshall if (error_code == 0) { 471575e9461SMike Marshall return 0; 472575e9461SMike Marshall /* 473575e9461SMike Marshall * This shouldn't ever happen. If it does it should be fixed on the 474575e9461SMike Marshall * server. 475575e9461SMike Marshall */ 476575e9461SMike Marshall } else if (error_code > 0) { 477bc8282a7SMasanari Iida gossip_err("orangefs: error status received.\n"); 478575e9461SMike Marshall gossip_err("orangefs: assuming error code is inverted.\n"); 479575e9461SMike Marshall error_code = -error_code; 480575e9461SMike Marshall } 481575e9461SMike Marshall 482575e9461SMike Marshall /* 483575e9461SMike Marshall * XXX: This is very bad since error codes from ORANGEFS may not be 484575e9461SMike Marshall * suitable for return into userspace. 485575e9461SMike Marshall */ 486575e9461SMike Marshall 487575e9461SMike Marshall /* 488575e9461SMike Marshall * Convert ORANGEFS error values into errno values suitable for return 489575e9461SMike Marshall * from the kernel. 490575e9461SMike Marshall */ 491575e9461SMike Marshall if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) { 492575e9461SMike Marshall if (((-error_code) & 493575e9461SMike Marshall (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT| 494575e9461SMike Marshall ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) { 495575e9461SMike Marshall /* 496575e9461SMike Marshall * cancellation error codes generally correspond to 497575e9461SMike Marshall * a timeout from the client's perspective 498575e9461SMike Marshall */ 499575e9461SMike Marshall error_code = -ETIMEDOUT; 500575e9461SMike Marshall } else { 501575e9461SMike Marshall /* assume a default error code */ 50295f5f88fSMike Marshall gossip_err("%s: bad error code :%d:.\n", 50395f5f88fSMike Marshall __func__, 50495f5f88fSMike Marshall error_code); 505575e9461SMike Marshall error_code = -EINVAL; 506575e9461SMike Marshall } 507575e9461SMike Marshall 508575e9461SMike Marshall /* Convert ORANGEFS encoded errno values into regular errno values. */ 509575e9461SMike Marshall } else if ((-error_code) & ORANGEFS_ERROR_BIT) { 510575e9461SMike Marshall i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS); 511296200d3SJérémy Lefaure if (i < ARRAY_SIZE(PINT_errno_mapping)) 512575e9461SMike Marshall error_code = -PINT_errno_mapping[i]; 513575e9461SMike Marshall else 514575e9461SMike Marshall error_code = -EINVAL; 515575e9461SMike Marshall 516575e9461SMike Marshall /* 517575e9461SMike Marshall * Only ORANGEFS protocol error codes should ever come here. Otherwise 518575e9461SMike Marshall * there is a bug somewhere. 519575e9461SMike Marshall */ 520575e9461SMike Marshall } else { 52195f5f88fSMike Marshall gossip_err("%s: unknown error code.\n", __func__); 522cf546ab6SMike Marshall error_code = -EINVAL; 523575e9461SMike Marshall } 524575e9461SMike Marshall return error_code; 525575e9461SMike Marshall } 526575e9461SMike Marshall 527575e9461SMike Marshall #define NUM_MODES 11 528575e9461SMike Marshall __s32 ORANGEFS_util_translate_mode(int mode) 529575e9461SMike Marshall { 530575e9461SMike Marshall int ret = 0; 531575e9461SMike Marshall int i = 0; 532575e9461SMike Marshall static int modes[NUM_MODES] = { 533575e9461SMike Marshall S_IXOTH, S_IWOTH, S_IROTH, 534575e9461SMike Marshall S_IXGRP, S_IWGRP, S_IRGRP, 535575e9461SMike Marshall S_IXUSR, S_IWUSR, S_IRUSR, 536575e9461SMike Marshall S_ISGID, S_ISUID 537575e9461SMike Marshall }; 538575e9461SMike Marshall static int orangefs_modes[NUM_MODES] = { 539575e9461SMike Marshall ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ, 540575e9461SMike Marshall ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ, 541575e9461SMike Marshall ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ, 542575e9461SMike Marshall ORANGEFS_G_SGID, ORANGEFS_U_SUID 543575e9461SMike Marshall }; 544575e9461SMike Marshall 545575e9461SMike Marshall for (i = 0; i < NUM_MODES; i++) 546575e9461SMike Marshall if (mode & modes[i]) 547575e9461SMike Marshall ret |= orangefs_modes[i]; 548575e9461SMike Marshall 549575e9461SMike Marshall return ret; 550575e9461SMike Marshall } 551575e9461SMike Marshall #undef NUM_MODES 552