1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2575e9461SMike Marshall /* 3575e9461SMike Marshall * (C) 2001 Clemson University and The University of Chicago 4575e9461SMike Marshall * 5575e9461SMike Marshall * See COPYING in top-level directory. 6575e9461SMike Marshall */ 7296200d3SJérémy Lefaure #include <linux/kernel.h> 8575e9461SMike Marshall #include "protocol.h" 9575e9461SMike Marshall #include "orangefs-kernel.h" 10575e9461SMike Marshall #include "orangefs-dev-proto.h" 11575e9461SMike Marshall #include "orangefs-bufmap.h" 12575e9461SMike Marshall 13575e9461SMike Marshall __s32 fsid_of_op(struct orangefs_kernel_op_s *op) 14575e9461SMike Marshall { 15575e9461SMike Marshall __s32 fsid = ORANGEFS_FS_ID_NULL; 16575e9461SMike Marshall 17575e9461SMike Marshall if (op) { 18575e9461SMike Marshall switch (op->upcall.type) { 19575e9461SMike Marshall case ORANGEFS_VFS_OP_FILE_IO: 20575e9461SMike Marshall fsid = op->upcall.req.io.refn.fs_id; 21575e9461SMike Marshall break; 22575e9461SMike Marshall case ORANGEFS_VFS_OP_LOOKUP: 23575e9461SMike Marshall fsid = op->upcall.req.lookup.parent_refn.fs_id; 24575e9461SMike Marshall break; 25575e9461SMike Marshall case ORANGEFS_VFS_OP_CREATE: 26575e9461SMike Marshall fsid = op->upcall.req.create.parent_refn.fs_id; 27575e9461SMike Marshall break; 28575e9461SMike Marshall case ORANGEFS_VFS_OP_GETATTR: 29575e9461SMike Marshall fsid = op->upcall.req.getattr.refn.fs_id; 30575e9461SMike Marshall break; 31575e9461SMike Marshall case ORANGEFS_VFS_OP_REMOVE: 32575e9461SMike Marshall fsid = op->upcall.req.remove.parent_refn.fs_id; 33575e9461SMike Marshall break; 34575e9461SMike Marshall case ORANGEFS_VFS_OP_MKDIR: 35575e9461SMike Marshall fsid = op->upcall.req.mkdir.parent_refn.fs_id; 36575e9461SMike Marshall break; 37575e9461SMike Marshall case ORANGEFS_VFS_OP_READDIR: 38575e9461SMike Marshall fsid = op->upcall.req.readdir.refn.fs_id; 39575e9461SMike Marshall break; 40575e9461SMike Marshall case ORANGEFS_VFS_OP_SETATTR: 41575e9461SMike Marshall fsid = op->upcall.req.setattr.refn.fs_id; 42575e9461SMike Marshall break; 43575e9461SMike Marshall case ORANGEFS_VFS_OP_SYMLINK: 44575e9461SMike Marshall fsid = op->upcall.req.sym.parent_refn.fs_id; 45575e9461SMike Marshall break; 46575e9461SMike Marshall case ORANGEFS_VFS_OP_RENAME: 47575e9461SMike Marshall fsid = op->upcall.req.rename.old_parent_refn.fs_id; 48575e9461SMike Marshall break; 49575e9461SMike Marshall case ORANGEFS_VFS_OP_STATFS: 50575e9461SMike Marshall fsid = op->upcall.req.statfs.fs_id; 51575e9461SMike Marshall break; 52575e9461SMike Marshall case ORANGEFS_VFS_OP_TRUNCATE: 53575e9461SMike Marshall fsid = op->upcall.req.truncate.refn.fs_id; 54575e9461SMike Marshall break; 556eaff8c7SMartin Brandenburg case ORANGEFS_VFS_OP_RA_FLUSH: 56575e9461SMike Marshall fsid = op->upcall.req.ra_cache_flush.refn.fs_id; 57575e9461SMike Marshall break; 58575e9461SMike Marshall case ORANGEFS_VFS_OP_FS_UMOUNT: 59575e9461SMike Marshall fsid = op->upcall.req.fs_umount.fs_id; 60575e9461SMike Marshall break; 61575e9461SMike Marshall case ORANGEFS_VFS_OP_GETXATTR: 62575e9461SMike Marshall fsid = op->upcall.req.getxattr.refn.fs_id; 63575e9461SMike Marshall break; 64575e9461SMike Marshall case ORANGEFS_VFS_OP_SETXATTR: 65575e9461SMike Marshall fsid = op->upcall.req.setxattr.refn.fs_id; 66575e9461SMike Marshall break; 67575e9461SMike Marshall case ORANGEFS_VFS_OP_LISTXATTR: 68575e9461SMike Marshall fsid = op->upcall.req.listxattr.refn.fs_id; 69575e9461SMike Marshall break; 70575e9461SMike Marshall case ORANGEFS_VFS_OP_REMOVEXATTR: 71575e9461SMike Marshall fsid = op->upcall.req.removexattr.refn.fs_id; 72575e9461SMike Marshall break; 73575e9461SMike Marshall case ORANGEFS_VFS_OP_FSYNC: 74575e9461SMike Marshall fsid = op->upcall.req.fsync.refn.fs_id; 75575e9461SMike Marshall break; 76575e9461SMike Marshall default: 77575e9461SMike Marshall break; 78575e9461SMike Marshall } 79575e9461SMike Marshall } 80575e9461SMike Marshall return fsid; 81575e9461SMike Marshall } 82575e9461SMike Marshall 83394f647eSMartin Brandenburg static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs) 84575e9461SMike Marshall { 85394f647eSMartin Brandenburg int flags = 0; 86575e9461SMike Marshall if (attrs->flags & ORANGEFS_IMMUTABLE_FL) 87394f647eSMartin Brandenburg flags |= S_IMMUTABLE; 88575e9461SMike Marshall else 89394f647eSMartin Brandenburg flags &= ~S_IMMUTABLE; 90575e9461SMike Marshall if (attrs->flags & ORANGEFS_APPEND_FL) 91394f647eSMartin Brandenburg flags |= S_APPEND; 92575e9461SMike Marshall else 93394f647eSMartin Brandenburg flags &= ~S_APPEND; 94575e9461SMike Marshall if (attrs->flags & ORANGEFS_NOATIME_FL) 95394f647eSMartin Brandenburg flags |= S_NOATIME; 96575e9461SMike Marshall else 97394f647eSMartin Brandenburg flags &= ~S_NOATIME; 98394f647eSMartin Brandenburg return flags; 99394f647eSMartin Brandenburg } 100575e9461SMike Marshall 101394f647eSMartin Brandenburg static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs) 102394f647eSMartin Brandenburg { 103394f647eSMartin Brandenburg int perm_mode = 0; 104394f647eSMartin Brandenburg 105394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_EXECUTE) 106394f647eSMartin Brandenburg perm_mode |= S_IXOTH; 107394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_WRITE) 108394f647eSMartin Brandenburg perm_mode |= S_IWOTH; 109394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_READ) 110394f647eSMartin Brandenburg perm_mode |= S_IROTH; 111394f647eSMartin Brandenburg 112394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_EXECUTE) 113394f647eSMartin Brandenburg perm_mode |= S_IXGRP; 114394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_WRITE) 115394f647eSMartin Brandenburg perm_mode |= S_IWGRP; 116394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_READ) 117394f647eSMartin Brandenburg perm_mode |= S_IRGRP; 118394f647eSMartin Brandenburg 119394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_EXECUTE) 120394f647eSMartin Brandenburg perm_mode |= S_IXUSR; 121394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_WRITE) 122394f647eSMartin Brandenburg perm_mode |= S_IWUSR; 123394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_READ) 124394f647eSMartin Brandenburg perm_mode |= S_IRUSR; 125394f647eSMartin Brandenburg 126394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_SGID) 127394f647eSMartin Brandenburg perm_mode |= S_ISGID; 128394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_SUID) 129394f647eSMartin Brandenburg perm_mode |= S_ISUID; 130394f647eSMartin Brandenburg 131394f647eSMartin Brandenburg return perm_mode; 132575e9461SMike Marshall } 133575e9461SMike Marshall 134575e9461SMike Marshall /* 135575e9461SMike Marshall * NOTE: in kernel land, we never use the sys_attr->link_target for 136575e9461SMike Marshall * anything, so don't bother copying it into the sys_attr object here. 137575e9461SMike Marshall */ 138575e9461SMike Marshall static inline int copy_attributes_from_inode(struct inode *inode, 139575e9461SMike Marshall struct ORANGEFS_sys_attr_s *attrs, 140575e9461SMike Marshall struct iattr *iattr) 141575e9461SMike Marshall { 142575e9461SMike Marshall umode_t tmp_mode; 143575e9461SMike Marshall 144575e9461SMike Marshall if (!iattr || !inode || !attrs) { 145575e9461SMike Marshall gossip_err("NULL iattr (%p), inode (%p), attrs (%p) " 146575e9461SMike Marshall "in copy_attributes_from_inode!\n", 147575e9461SMike Marshall iattr, 148575e9461SMike Marshall inode, 149575e9461SMike Marshall attrs); 150575e9461SMike Marshall return -EINVAL; 151575e9461SMike Marshall } 152575e9461SMike Marshall /* 153575e9461SMike Marshall * We need to be careful to only copy the attributes out of the 154575e9461SMike Marshall * iattr object that we know are valid. 155575e9461SMike Marshall */ 156575e9461SMike Marshall attrs->mask = 0; 157575e9461SMike Marshall if (iattr->ia_valid & ATTR_UID) { 15878fee0b6SJann Horn attrs->owner = from_kuid(&init_user_ns, iattr->ia_uid); 159575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_UID; 160575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner); 161575e9461SMike Marshall } 162575e9461SMike Marshall if (iattr->ia_valid & ATTR_GID) { 16378fee0b6SJann Horn attrs->group = from_kgid(&init_user_ns, iattr->ia_gid); 164575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_GID; 165575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group); 166575e9461SMike Marshall } 167575e9461SMike Marshall 168575e9461SMike Marshall if (iattr->ia_valid & ATTR_ATIME) { 169575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_ATIME; 170575e9461SMike Marshall if (iattr->ia_valid & ATTR_ATIME_SET) { 171be81ce48SArnd Bergmann attrs->atime = (time64_t)iattr->ia_atime.tv_sec; 172575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET; 173575e9461SMike Marshall } 174575e9461SMike Marshall } 175575e9461SMike Marshall if (iattr->ia_valid & ATTR_MTIME) { 176575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_MTIME; 177575e9461SMike Marshall if (iattr->ia_valid & ATTR_MTIME_SET) { 178be81ce48SArnd Bergmann attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec; 179575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET; 180575e9461SMike Marshall } 181575e9461SMike Marshall } 182575e9461SMike Marshall if (iattr->ia_valid & ATTR_CTIME) 183575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_CTIME; 184575e9461SMike Marshall 185575e9461SMike Marshall /* 186575e9461SMike Marshall * ORANGEFS cannot set size with a setattr operation. Probably not likely 187575e9461SMike Marshall * to be requested through the VFS, but just in case, don't worry about 188575e9461SMike Marshall * ATTR_SIZE 189575e9461SMike Marshall */ 190575e9461SMike Marshall 191575e9461SMike Marshall if (iattr->ia_valid & ATTR_MODE) { 192575e9461SMike Marshall tmp_mode = iattr->ia_mode; 193575e9461SMike Marshall if (tmp_mode & (S_ISVTX)) { 194575e9461SMike Marshall if (is_root_handle(inode)) { 195575e9461SMike Marshall /* 196575e9461SMike Marshall * allow sticky bit to be set on root (since 197575e9461SMike Marshall * it shows up that way by default anyhow), 198575e9461SMike Marshall * but don't show it to the server 199575e9461SMike Marshall */ 200575e9461SMike Marshall tmp_mode -= S_ISVTX; 201575e9461SMike Marshall } else { 202575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 203575e9461SMike Marshall "User attempted to set sticky bit on non-root directory; returning EINVAL.\n"); 204575e9461SMike Marshall return -EINVAL; 205575e9461SMike Marshall } 206575e9461SMike Marshall } 207575e9461SMike Marshall 208575e9461SMike Marshall if (tmp_mode & (S_ISUID)) { 209575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 210575e9461SMike Marshall "Attempting to set setuid bit (not supported); returning EINVAL.\n"); 211575e9461SMike Marshall return -EINVAL; 212575e9461SMike Marshall } 213575e9461SMike Marshall 214575e9461SMike Marshall attrs->perms = ORANGEFS_util_translate_mode(tmp_mode); 215575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_PERM; 216575e9461SMike Marshall } 217575e9461SMike Marshall 218575e9461SMike Marshall return 0; 219575e9461SMike Marshall } 220575e9461SMike Marshall 2213c9cf98dSMartin Brandenburg static int orangefs_inode_type(enum orangefs_ds_type objtype) 2223c9cf98dSMartin Brandenburg { 2233c9cf98dSMartin Brandenburg if (objtype == ORANGEFS_TYPE_METAFILE) 2243c9cf98dSMartin Brandenburg return S_IFREG; 2253c9cf98dSMartin Brandenburg else if (objtype == ORANGEFS_TYPE_DIRECTORY) 2263c9cf98dSMartin Brandenburg return S_IFDIR; 2273c9cf98dSMartin Brandenburg else if (objtype == ORANGEFS_TYPE_SYMLINK) 2283c9cf98dSMartin Brandenburg return S_IFLNK; 2293c9cf98dSMartin Brandenburg else 2303c9cf98dSMartin Brandenburg return -1; 2313c9cf98dSMartin Brandenburg } 2323c9cf98dSMartin Brandenburg 2334d0cac7eSMartin Brandenburg static void orangefs_make_bad_inode(struct inode *inode) 2344d0cac7eSMartin Brandenburg { 2354d0cac7eSMartin Brandenburg if (is_root_handle(inode)) { 2364d0cac7eSMartin Brandenburg /* 2374d0cac7eSMartin Brandenburg * if this occurs, the pvfs2-client-core was killed but we 2384d0cac7eSMartin Brandenburg * can't afford to lose the inode operations and such 2394d0cac7eSMartin Brandenburg * associated with the root handle in any case. 2404d0cac7eSMartin Brandenburg */ 2414d0cac7eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, 2424d0cac7eSMartin Brandenburg "*** NOT making bad root inode %pU\n", 2434d0cac7eSMartin Brandenburg get_khandle_from_ino(inode)); 2444d0cac7eSMartin Brandenburg } else { 2454d0cac7eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, 2464d0cac7eSMartin Brandenburg "*** making bad inode %pU\n", 2474d0cac7eSMartin Brandenburg get_khandle_from_ino(inode)); 2484d0cac7eSMartin Brandenburg make_bad_inode(inode); 2494d0cac7eSMartin Brandenburg } 2504d0cac7eSMartin Brandenburg } 2514d0cac7eSMartin Brandenburg 25226662633SMartin Brandenburg static int orangefs_inode_is_stale(struct inode *inode, int new, 25326662633SMartin Brandenburg struct ORANGEFS_sys_attr_s *attrs, char *link_target) 25426662633SMartin Brandenburg { 25526662633SMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 25626662633SMartin Brandenburg int type = orangefs_inode_type(attrs->objtype); 25726662633SMartin Brandenburg if (!new) { 25826662633SMartin Brandenburg /* 25926662633SMartin Brandenburg * If the inode type or symlink target have changed then this 26026662633SMartin Brandenburg * inode is stale. 26126662633SMartin Brandenburg */ 26226662633SMartin Brandenburg if (type == -1 || !(inode->i_mode & type)) { 26326662633SMartin Brandenburg orangefs_make_bad_inode(inode); 26426662633SMartin Brandenburg return 1; 26526662633SMartin Brandenburg } 26626662633SMartin Brandenburg if (type == S_IFLNK && strncmp(orangefs_inode->link_target, 26726662633SMartin Brandenburg link_target, ORANGEFS_NAME_MAX)) { 26826662633SMartin Brandenburg orangefs_make_bad_inode(inode); 26926662633SMartin Brandenburg return 1; 27026662633SMartin Brandenburg } 27126662633SMartin Brandenburg } 27226662633SMartin Brandenburg return 0; 27326662633SMartin Brandenburg } 27426662633SMartin Brandenburg 27568a24a6cSMartin Brandenburg int orangefs_inode_getattr(struct inode *inode, int new, int bypass, 27668a24a6cSMartin Brandenburg u32 request_mask) 2773c9cf98dSMartin Brandenburg { 2783c9cf98dSMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 2793c9cf98dSMartin Brandenburg struct orangefs_kernel_op_s *new_op; 2803c9cf98dSMartin Brandenburg loff_t inode_size, rounded_up_size; 28126662633SMartin Brandenburg int ret, type; 2823c9cf98dSMartin Brandenburg 2833c9cf98dSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__, 2843c9cf98dSMartin Brandenburg get_khandle_from_ino(inode)); 2853c9cf98dSMartin Brandenburg 28671680c18SMartin Brandenburg if (!new && !bypass) { 28768a24a6cSMartin Brandenburg /* 28868a24a6cSMartin Brandenburg * Must have all the attributes in the mask and be within cache 28968a24a6cSMartin Brandenburg * time. 29068a24a6cSMartin Brandenburg */ 29168a24a6cSMartin Brandenburg if ((request_mask & orangefs_inode->getattr_mask) == 29268a24a6cSMartin Brandenburg request_mask && 29368a24a6cSMartin Brandenburg time_before(jiffies, orangefs_inode->getattr_time)) 29471680c18SMartin Brandenburg return 0; 29571680c18SMartin Brandenburg } 29671680c18SMartin Brandenburg 2973c9cf98dSMartin Brandenburg new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); 2983c9cf98dSMartin Brandenburg if (!new_op) 2993c9cf98dSMartin Brandenburg return -ENOMEM; 3003c9cf98dSMartin Brandenburg new_op->upcall.req.getattr.refn = orangefs_inode->refn; 30168a24a6cSMartin Brandenburg /* 30268a24a6cSMartin Brandenburg * Size is the hardest attribute to get. The incremental cost of any 30368a24a6cSMartin Brandenburg * other attribute is essentially zero. 30468a24a6cSMartin Brandenburg */ 30568a24a6cSMartin Brandenburg if (request_mask & STATX_SIZE || new) 30671680c18SMartin Brandenburg new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT; 30768a24a6cSMartin Brandenburg else 30868a24a6cSMartin Brandenburg new_op->upcall.req.getattr.mask = 30968a24a6cSMartin Brandenburg ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE; 3103c9cf98dSMartin Brandenburg 3113c9cf98dSMartin Brandenburg ret = service_operation(new_op, __func__, 3123c9cf98dSMartin Brandenburg get_interruptible_flag(inode)); 3133c9cf98dSMartin Brandenburg if (ret != 0) 3143c9cf98dSMartin Brandenburg goto out; 3153c9cf98dSMartin Brandenburg 31626662633SMartin Brandenburg type = orangefs_inode_type(new_op-> 3173c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.objtype); 31826662633SMartin Brandenburg ret = orangefs_inode_is_stale(inode, new, 31926662633SMartin Brandenburg &new_op->downcall.resp.getattr.attributes, 32026662633SMartin Brandenburg new_op->downcall.resp.getattr.link_target); 32126662633SMartin Brandenburg if (ret) { 3223c9cf98dSMartin Brandenburg ret = -ESTALE; 3233c9cf98dSMartin Brandenburg goto out; 3243c9cf98dSMartin Brandenburg } 3253c9cf98dSMartin Brandenburg 32626662633SMartin Brandenburg switch (type) { 3273c9cf98dSMartin Brandenburg case S_IFREG: 3283c9cf98dSMartin Brandenburg inode->i_flags = orangefs_inode_flags(&new_op-> 3293c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes); 33068a24a6cSMartin Brandenburg if (request_mask & STATX_SIZE || new) { 3313c9cf98dSMartin Brandenburg inode_size = (loff_t)new_op-> 3323c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.size; 3333c9cf98dSMartin Brandenburg rounded_up_size = 3343c9cf98dSMartin Brandenburg (inode_size + (4096 - (inode_size % 4096))); 3353c9cf98dSMartin Brandenburg inode->i_size = inode_size; 3363c9cf98dSMartin Brandenburg orangefs_inode->blksize = 3373c9cf98dSMartin Brandenburg new_op->downcall.resp.getattr.attributes.blksize; 3383c9cf98dSMartin Brandenburg spin_lock(&inode->i_lock); 3393c9cf98dSMartin Brandenburg inode->i_bytes = inode_size; 3403c9cf98dSMartin Brandenburg inode->i_blocks = 3413c9cf98dSMartin Brandenburg (unsigned long)(rounded_up_size / 512); 3423c9cf98dSMartin Brandenburg spin_unlock(&inode->i_lock); 34368a24a6cSMartin Brandenburg } 3443c9cf98dSMartin Brandenburg break; 3453c9cf98dSMartin Brandenburg case S_IFDIR: 34668a24a6cSMartin Brandenburg if (request_mask & STATX_SIZE || new) { 34709cbfeafSKirill A. Shutemov inode->i_size = PAGE_SIZE; 34893407472SFabian Frederick orangefs_inode->blksize = i_blocksize(inode); 3493c9cf98dSMartin Brandenburg spin_lock(&inode->i_lock); 3503c9cf98dSMartin Brandenburg inode_set_bytes(inode, inode->i_size); 3513c9cf98dSMartin Brandenburg spin_unlock(&inode->i_lock); 35268a24a6cSMartin Brandenburg } 3533c9cf98dSMartin Brandenburg set_nlink(inode, 1); 3543c9cf98dSMartin Brandenburg break; 3553c9cf98dSMartin Brandenburg case S_IFLNK: 3563c9cf98dSMartin Brandenburg if (new) { 3573c9cf98dSMartin Brandenburg inode->i_size = (loff_t)strlen(new_op-> 3583c9cf98dSMartin Brandenburg downcall.resp.getattr.link_target); 35993407472SFabian Frederick orangefs_inode->blksize = i_blocksize(inode); 3602eacea74SMartin Brandenburg ret = strscpy(orangefs_inode->link_target, 3613c9cf98dSMartin Brandenburg new_op->downcall.resp.getattr.link_target, 3623c9cf98dSMartin Brandenburg ORANGEFS_NAME_MAX); 3632eacea74SMartin Brandenburg if (ret == -E2BIG) { 3642eacea74SMartin Brandenburg ret = -EIO; 3652eacea74SMartin Brandenburg goto out; 3662eacea74SMartin Brandenburg } 367e8da254cSMartin Brandenburg inode->i_link = orangefs_inode->link_target; 3683c9cf98dSMartin Brandenburg } 3693c9cf98dSMartin Brandenburg break; 3703c9cf98dSMartin Brandenburg } 3713c9cf98dSMartin Brandenburg 3723c9cf98dSMartin Brandenburg inode->i_uid = make_kuid(&init_user_ns, new_op-> 3733c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.owner); 3743c9cf98dSMartin Brandenburg inode->i_gid = make_kgid(&init_user_ns, new_op-> 3753c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.group); 3763c9cf98dSMartin Brandenburg inode->i_atime.tv_sec = (time64_t)new_op-> 3773c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.atime; 3783c9cf98dSMartin Brandenburg inode->i_mtime.tv_sec = (time64_t)new_op-> 3793c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.mtime; 3803c9cf98dSMartin Brandenburg inode->i_ctime.tv_sec = (time64_t)new_op-> 3813c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.ctime; 3823c9cf98dSMartin Brandenburg inode->i_atime.tv_nsec = 0; 3833c9cf98dSMartin Brandenburg inode->i_mtime.tv_nsec = 0; 3843c9cf98dSMartin Brandenburg inode->i_ctime.tv_nsec = 0; 3853c9cf98dSMartin Brandenburg 3863c9cf98dSMartin Brandenburg /* special case: mark the root inode as sticky */ 38726662633SMartin Brandenburg inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) | 3883c9cf98dSMartin Brandenburg orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes); 3893c9cf98dSMartin Brandenburg 3901d503617SMartin Brandenburg orangefs_inode->getattr_time = jiffies + 3911d503617SMartin Brandenburg orangefs_getattr_timeout_msecs*HZ/1000; 39268a24a6cSMartin Brandenburg if (request_mask & STATX_SIZE || new) 39368a24a6cSMartin Brandenburg orangefs_inode->getattr_mask = STATX_BASIC_STATS; 39468a24a6cSMartin Brandenburg else 39568a24a6cSMartin Brandenburg orangefs_inode->getattr_mask = STATX_BASIC_STATS & ~STATX_SIZE; 3963c9cf98dSMartin Brandenburg ret = 0; 3973c9cf98dSMartin Brandenburg out: 3983c9cf98dSMartin Brandenburg op_release(new_op); 3993c9cf98dSMartin Brandenburg return ret; 4003c9cf98dSMartin Brandenburg } 4013c9cf98dSMartin Brandenburg 4025859d77eSMartin Brandenburg int orangefs_inode_check_changed(struct inode *inode) 4035859d77eSMartin Brandenburg { 4045859d77eSMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 4055859d77eSMartin Brandenburg struct orangefs_kernel_op_s *new_op; 4065859d77eSMartin Brandenburg int ret; 4075859d77eSMartin Brandenburg 4085859d77eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__, 4095859d77eSMartin Brandenburg get_khandle_from_ino(inode)); 4105859d77eSMartin Brandenburg 4115859d77eSMartin Brandenburg new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); 4125859d77eSMartin Brandenburg if (!new_op) 4135859d77eSMartin Brandenburg return -ENOMEM; 4145859d77eSMartin Brandenburg new_op->upcall.req.getattr.refn = orangefs_inode->refn; 4155859d77eSMartin Brandenburg new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE | 4165859d77eSMartin Brandenburg ORANGEFS_ATTR_SYS_LNK_TARGET; 4175859d77eSMartin Brandenburg 4185859d77eSMartin Brandenburg ret = service_operation(new_op, __func__, 4195859d77eSMartin Brandenburg get_interruptible_flag(inode)); 4205859d77eSMartin Brandenburg if (ret != 0) 4215859d77eSMartin Brandenburg goto out; 4225859d77eSMartin Brandenburg 42326662633SMartin Brandenburg ret = orangefs_inode_is_stale(inode, 0, 42426662633SMartin Brandenburg &new_op->downcall.resp.getattr.attributes, 42526662633SMartin Brandenburg new_op->downcall.resp.getattr.link_target); 4265859d77eSMartin Brandenburg out: 4275859d77eSMartin Brandenburg op_release(new_op); 4285859d77eSMartin Brandenburg return ret; 4295859d77eSMartin Brandenburg } 4305859d77eSMartin Brandenburg 431575e9461SMike Marshall /* 432575e9461SMike Marshall * issues a orangefs setattr request to make sure the new attribute values 433575e9461SMike Marshall * take effect if successful. returns 0 on success; -errno otherwise 434575e9461SMike Marshall */ 435575e9461SMike Marshall int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr) 436575e9461SMike Marshall { 437575e9461SMike Marshall struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 438575e9461SMike Marshall struct orangefs_kernel_op_s *new_op; 439575e9461SMike Marshall int ret; 440575e9461SMike Marshall 441575e9461SMike Marshall new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR); 442575e9461SMike Marshall if (!new_op) 443575e9461SMike Marshall return -ENOMEM; 444575e9461SMike Marshall 445575e9461SMike Marshall new_op->upcall.req.setattr.refn = orangefs_inode->refn; 446575e9461SMike Marshall ret = copy_attributes_from_inode(inode, 447575e9461SMike Marshall &new_op->upcall.req.setattr.attributes, 448575e9461SMike Marshall iattr); 449ed42fe05SAl Viro if (ret >= 0) { 450575e9461SMike Marshall ret = service_operation(new_op, __func__, 451575e9461SMike Marshall get_interruptible_flag(inode)); 452575e9461SMike Marshall 453575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 454575e9461SMike Marshall "orangefs_inode_setattr: returning %d\n", 455575e9461SMike Marshall ret); 456ed42fe05SAl Viro } 457575e9461SMike Marshall 458575e9461SMike Marshall op_release(new_op); 459575e9461SMike Marshall 460a55f2d86SMartin Brandenburg if (ret == 0) 4618bbb20a8SMartin Brandenburg orangefs_inode->getattr_time = jiffies - 1; 462575e9461SMike Marshall 463575e9461SMike Marshall return ret; 464575e9461SMike Marshall } 465575e9461SMike Marshall 466575e9461SMike Marshall /* 467575e9461SMike Marshall * The following is a very dirty hack that is now a permanent part of the 468575e9461SMike Marshall * ORANGEFS protocol. See protocol.h for more error definitions. 469575e9461SMike Marshall */ 470575e9461SMike Marshall 471575e9461SMike Marshall /* The order matches include/orangefs-types.h in the OrangeFS source. */ 472575e9461SMike Marshall static int PINT_errno_mapping[] = { 473575e9461SMike Marshall 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM, 474575e9461SMike Marshall EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE, 475575e9461SMike Marshall EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG, 476575e9461SMike Marshall ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH, 477575e9461SMike Marshall EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM, 478575e9461SMike Marshall EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE, 479575e9461SMike Marshall ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE, 480575e9461SMike Marshall EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS, 481575e9461SMike Marshall ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY, 482575e9461SMike Marshall EACCES, ECONNRESET, ERANGE 483575e9461SMike Marshall }; 484575e9461SMike Marshall 485575e9461SMike Marshall int orangefs_normalize_to_errno(__s32 error_code) 486575e9461SMike Marshall { 487575e9461SMike Marshall __u32 i; 488575e9461SMike Marshall 489575e9461SMike Marshall /* Success */ 490575e9461SMike Marshall if (error_code == 0) { 491575e9461SMike Marshall return 0; 492575e9461SMike Marshall /* 493575e9461SMike Marshall * This shouldn't ever happen. If it does it should be fixed on the 494575e9461SMike Marshall * server. 495575e9461SMike Marshall */ 496575e9461SMike Marshall } else if (error_code > 0) { 497575e9461SMike Marshall gossip_err("orangefs: error status receieved.\n"); 498575e9461SMike Marshall gossip_err("orangefs: assuming error code is inverted.\n"); 499575e9461SMike Marshall error_code = -error_code; 500575e9461SMike Marshall } 501575e9461SMike Marshall 502575e9461SMike Marshall /* 503575e9461SMike Marshall * XXX: This is very bad since error codes from ORANGEFS may not be 504575e9461SMike Marshall * suitable for return into userspace. 505575e9461SMike Marshall */ 506575e9461SMike Marshall 507575e9461SMike Marshall /* 508575e9461SMike Marshall * Convert ORANGEFS error values into errno values suitable for return 509575e9461SMike Marshall * from the kernel. 510575e9461SMike Marshall */ 511575e9461SMike Marshall if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) { 512575e9461SMike Marshall if (((-error_code) & 513575e9461SMike Marshall (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT| 514575e9461SMike Marshall ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) { 515575e9461SMike Marshall /* 516575e9461SMike Marshall * cancellation error codes generally correspond to 517575e9461SMike Marshall * a timeout from the client's perspective 518575e9461SMike Marshall */ 519575e9461SMike Marshall error_code = -ETIMEDOUT; 520575e9461SMike Marshall } else { 521575e9461SMike Marshall /* assume a default error code */ 522575e9461SMike Marshall gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code); 523575e9461SMike Marshall error_code = -EINVAL; 524575e9461SMike Marshall } 525575e9461SMike Marshall 526575e9461SMike Marshall /* Convert ORANGEFS encoded errno values into regular errno values. */ 527575e9461SMike Marshall } else if ((-error_code) & ORANGEFS_ERROR_BIT) { 528575e9461SMike Marshall i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS); 529296200d3SJérémy Lefaure if (i < ARRAY_SIZE(PINT_errno_mapping)) 530575e9461SMike Marshall error_code = -PINT_errno_mapping[i]; 531575e9461SMike Marshall else 532575e9461SMike Marshall error_code = -EINVAL; 533575e9461SMike Marshall 534575e9461SMike Marshall /* 535575e9461SMike Marshall * Only ORANGEFS protocol error codes should ever come here. Otherwise 536575e9461SMike Marshall * there is a bug somewhere. 537575e9461SMike Marshall */ 538575e9461SMike Marshall } else { 539575e9461SMike Marshall gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n"); 540575e9461SMike Marshall } 541575e9461SMike Marshall return error_code; 542575e9461SMike Marshall } 543575e9461SMike Marshall 544575e9461SMike Marshall #define NUM_MODES 11 545575e9461SMike Marshall __s32 ORANGEFS_util_translate_mode(int mode) 546575e9461SMike Marshall { 547575e9461SMike Marshall int ret = 0; 548575e9461SMike Marshall int i = 0; 549575e9461SMike Marshall static int modes[NUM_MODES] = { 550575e9461SMike Marshall S_IXOTH, S_IWOTH, S_IROTH, 551575e9461SMike Marshall S_IXGRP, S_IWGRP, S_IRGRP, 552575e9461SMike Marshall S_IXUSR, S_IWUSR, S_IRUSR, 553575e9461SMike Marshall S_ISGID, S_ISUID 554575e9461SMike Marshall }; 555575e9461SMike Marshall static int orangefs_modes[NUM_MODES] = { 556575e9461SMike Marshall ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ, 557575e9461SMike Marshall ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ, 558575e9461SMike Marshall ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ, 559575e9461SMike Marshall ORANGEFS_G_SGID, ORANGEFS_U_SUID 560575e9461SMike Marshall }; 561575e9461SMike Marshall 562575e9461SMike Marshall for (i = 0; i < NUM_MODES; i++) 563575e9461SMike Marshall if (mode & modes[i]) 564575e9461SMike Marshall ret |= orangefs_modes[i]; 565575e9461SMike Marshall 566575e9461SMike Marshall return ret; 567575e9461SMike Marshall } 568575e9461SMike Marshall #undef NUM_MODES 569