1575e9461SMike Marshall /* 2575e9461SMike Marshall * (C) 2001 Clemson University and The University of Chicago 3575e9461SMike Marshall * 4575e9461SMike Marshall * See COPYING in top-level directory. 5575e9461SMike Marshall */ 6575e9461SMike Marshall #include "protocol.h" 7575e9461SMike Marshall #include "orangefs-kernel.h" 8575e9461SMike Marshall #include "orangefs-dev-proto.h" 9575e9461SMike Marshall #include "orangefs-bufmap.h" 10575e9461SMike Marshall 11575e9461SMike Marshall __s32 fsid_of_op(struct orangefs_kernel_op_s *op) 12575e9461SMike Marshall { 13575e9461SMike Marshall __s32 fsid = ORANGEFS_FS_ID_NULL; 14575e9461SMike Marshall 15575e9461SMike Marshall if (op) { 16575e9461SMike Marshall switch (op->upcall.type) { 17575e9461SMike Marshall case ORANGEFS_VFS_OP_FILE_IO: 18575e9461SMike Marshall fsid = op->upcall.req.io.refn.fs_id; 19575e9461SMike Marshall break; 20575e9461SMike Marshall case ORANGEFS_VFS_OP_LOOKUP: 21575e9461SMike Marshall fsid = op->upcall.req.lookup.parent_refn.fs_id; 22575e9461SMike Marshall break; 23575e9461SMike Marshall case ORANGEFS_VFS_OP_CREATE: 24575e9461SMike Marshall fsid = op->upcall.req.create.parent_refn.fs_id; 25575e9461SMike Marshall break; 26575e9461SMike Marshall case ORANGEFS_VFS_OP_GETATTR: 27575e9461SMike Marshall fsid = op->upcall.req.getattr.refn.fs_id; 28575e9461SMike Marshall break; 29575e9461SMike Marshall case ORANGEFS_VFS_OP_REMOVE: 30575e9461SMike Marshall fsid = op->upcall.req.remove.parent_refn.fs_id; 31575e9461SMike Marshall break; 32575e9461SMike Marshall case ORANGEFS_VFS_OP_MKDIR: 33575e9461SMike Marshall fsid = op->upcall.req.mkdir.parent_refn.fs_id; 34575e9461SMike Marshall break; 35575e9461SMike Marshall case ORANGEFS_VFS_OP_READDIR: 36575e9461SMike Marshall fsid = op->upcall.req.readdir.refn.fs_id; 37575e9461SMike Marshall break; 38575e9461SMike Marshall case ORANGEFS_VFS_OP_SETATTR: 39575e9461SMike Marshall fsid = op->upcall.req.setattr.refn.fs_id; 40575e9461SMike Marshall break; 41575e9461SMike Marshall case ORANGEFS_VFS_OP_SYMLINK: 42575e9461SMike Marshall fsid = op->upcall.req.sym.parent_refn.fs_id; 43575e9461SMike Marshall break; 44575e9461SMike Marshall case ORANGEFS_VFS_OP_RENAME: 45575e9461SMike Marshall fsid = op->upcall.req.rename.old_parent_refn.fs_id; 46575e9461SMike Marshall break; 47575e9461SMike Marshall case ORANGEFS_VFS_OP_STATFS: 48575e9461SMike Marshall fsid = op->upcall.req.statfs.fs_id; 49575e9461SMike Marshall break; 50575e9461SMike Marshall case ORANGEFS_VFS_OP_TRUNCATE: 51575e9461SMike Marshall fsid = op->upcall.req.truncate.refn.fs_id; 52575e9461SMike Marshall break; 53575e9461SMike Marshall case ORANGEFS_VFS_OP_MMAP_RA_FLUSH: 54575e9461SMike Marshall fsid = op->upcall.req.ra_cache_flush.refn.fs_id; 55575e9461SMike Marshall break; 56575e9461SMike Marshall case ORANGEFS_VFS_OP_FS_UMOUNT: 57575e9461SMike Marshall fsid = op->upcall.req.fs_umount.fs_id; 58575e9461SMike Marshall break; 59575e9461SMike Marshall case ORANGEFS_VFS_OP_GETXATTR: 60575e9461SMike Marshall fsid = op->upcall.req.getxattr.refn.fs_id; 61575e9461SMike Marshall break; 62575e9461SMike Marshall case ORANGEFS_VFS_OP_SETXATTR: 63575e9461SMike Marshall fsid = op->upcall.req.setxattr.refn.fs_id; 64575e9461SMike Marshall break; 65575e9461SMike Marshall case ORANGEFS_VFS_OP_LISTXATTR: 66575e9461SMike Marshall fsid = op->upcall.req.listxattr.refn.fs_id; 67575e9461SMike Marshall break; 68575e9461SMike Marshall case ORANGEFS_VFS_OP_REMOVEXATTR: 69575e9461SMike Marshall fsid = op->upcall.req.removexattr.refn.fs_id; 70575e9461SMike Marshall break; 71575e9461SMike Marshall case ORANGEFS_VFS_OP_FSYNC: 72575e9461SMike Marshall fsid = op->upcall.req.fsync.refn.fs_id; 73575e9461SMike Marshall break; 74575e9461SMike Marshall default: 75575e9461SMike Marshall break; 76575e9461SMike Marshall } 77575e9461SMike Marshall } 78575e9461SMike Marshall return fsid; 79575e9461SMike Marshall } 80575e9461SMike Marshall 81394f647eSMartin Brandenburg static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs) 82575e9461SMike Marshall { 83394f647eSMartin Brandenburg int flags = 0; 84575e9461SMike Marshall if (attrs->flags & ORANGEFS_IMMUTABLE_FL) 85394f647eSMartin Brandenburg flags |= S_IMMUTABLE; 86575e9461SMike Marshall else 87394f647eSMartin Brandenburg flags &= ~S_IMMUTABLE; 88575e9461SMike Marshall if (attrs->flags & ORANGEFS_APPEND_FL) 89394f647eSMartin Brandenburg flags |= S_APPEND; 90575e9461SMike Marshall else 91394f647eSMartin Brandenburg flags &= ~S_APPEND; 92575e9461SMike Marshall if (attrs->flags & ORANGEFS_NOATIME_FL) 93394f647eSMartin Brandenburg flags |= S_NOATIME; 94575e9461SMike Marshall else 95394f647eSMartin Brandenburg flags &= ~S_NOATIME; 96394f647eSMartin Brandenburg return flags; 97394f647eSMartin Brandenburg } 98575e9461SMike Marshall 99394f647eSMartin Brandenburg static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs) 100394f647eSMartin Brandenburg { 101394f647eSMartin Brandenburg int perm_mode = 0; 102394f647eSMartin Brandenburg 103394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_EXECUTE) 104394f647eSMartin Brandenburg perm_mode |= S_IXOTH; 105394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_WRITE) 106394f647eSMartin Brandenburg perm_mode |= S_IWOTH; 107394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_O_READ) 108394f647eSMartin Brandenburg perm_mode |= S_IROTH; 109394f647eSMartin Brandenburg 110394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_EXECUTE) 111394f647eSMartin Brandenburg perm_mode |= S_IXGRP; 112394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_WRITE) 113394f647eSMartin Brandenburg perm_mode |= S_IWGRP; 114394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_READ) 115394f647eSMartin Brandenburg perm_mode |= S_IRGRP; 116394f647eSMartin Brandenburg 117394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_EXECUTE) 118394f647eSMartin Brandenburg perm_mode |= S_IXUSR; 119394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_WRITE) 120394f647eSMartin Brandenburg perm_mode |= S_IWUSR; 121394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_READ) 122394f647eSMartin Brandenburg perm_mode |= S_IRUSR; 123394f647eSMartin Brandenburg 124394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_G_SGID) 125394f647eSMartin Brandenburg perm_mode |= S_ISGID; 126394f647eSMartin Brandenburg if (attrs->perms & ORANGEFS_U_SUID) 127394f647eSMartin Brandenburg perm_mode |= S_ISUID; 128394f647eSMartin Brandenburg 129394f647eSMartin Brandenburg return perm_mode; 130575e9461SMike Marshall } 131575e9461SMike Marshall 132575e9461SMike Marshall /* 133575e9461SMike Marshall * NOTE: in kernel land, we never use the sys_attr->link_target for 134575e9461SMike Marshall * anything, so don't bother copying it into the sys_attr object here. 135575e9461SMike Marshall */ 136575e9461SMike Marshall static inline int copy_attributes_from_inode(struct inode *inode, 137575e9461SMike Marshall struct ORANGEFS_sys_attr_s *attrs, 138575e9461SMike Marshall struct iattr *iattr) 139575e9461SMike Marshall { 140575e9461SMike Marshall umode_t tmp_mode; 141575e9461SMike Marshall 142575e9461SMike Marshall if (!iattr || !inode || !attrs) { 143575e9461SMike Marshall gossip_err("NULL iattr (%p), inode (%p), attrs (%p) " 144575e9461SMike Marshall "in copy_attributes_from_inode!\n", 145575e9461SMike Marshall iattr, 146575e9461SMike Marshall inode, 147575e9461SMike Marshall attrs); 148575e9461SMike Marshall return -EINVAL; 149575e9461SMike Marshall } 150575e9461SMike Marshall /* 151575e9461SMike Marshall * We need to be careful to only copy the attributes out of the 152575e9461SMike Marshall * iattr object that we know are valid. 153575e9461SMike Marshall */ 154575e9461SMike Marshall attrs->mask = 0; 155575e9461SMike Marshall if (iattr->ia_valid & ATTR_UID) { 156575e9461SMike Marshall attrs->owner = from_kuid(current_user_ns(), iattr->ia_uid); 157575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_UID; 158575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner); 159575e9461SMike Marshall } 160575e9461SMike Marshall if (iattr->ia_valid & ATTR_GID) { 161575e9461SMike Marshall attrs->group = from_kgid(current_user_ns(), iattr->ia_gid); 162575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_GID; 163575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group); 164575e9461SMike Marshall } 165575e9461SMike Marshall 166575e9461SMike Marshall if (iattr->ia_valid & ATTR_ATIME) { 167575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_ATIME; 168575e9461SMike Marshall if (iattr->ia_valid & ATTR_ATIME_SET) { 169be81ce48SArnd Bergmann attrs->atime = (time64_t)iattr->ia_atime.tv_sec; 170575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET; 171575e9461SMike Marshall } 172575e9461SMike Marshall } 173575e9461SMike Marshall if (iattr->ia_valid & ATTR_MTIME) { 174575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_MTIME; 175575e9461SMike Marshall if (iattr->ia_valid & ATTR_MTIME_SET) { 176be81ce48SArnd Bergmann attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec; 177575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET; 178575e9461SMike Marshall } 179575e9461SMike Marshall } 180575e9461SMike Marshall if (iattr->ia_valid & ATTR_CTIME) 181575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_CTIME; 182575e9461SMike Marshall 183575e9461SMike Marshall /* 184575e9461SMike Marshall * ORANGEFS cannot set size with a setattr operation. Probably not likely 185575e9461SMike Marshall * to be requested through the VFS, but just in case, don't worry about 186575e9461SMike Marshall * ATTR_SIZE 187575e9461SMike Marshall */ 188575e9461SMike Marshall 189575e9461SMike Marshall if (iattr->ia_valid & ATTR_MODE) { 190575e9461SMike Marshall tmp_mode = iattr->ia_mode; 191575e9461SMike Marshall if (tmp_mode & (S_ISVTX)) { 192575e9461SMike Marshall if (is_root_handle(inode)) { 193575e9461SMike Marshall /* 194575e9461SMike Marshall * allow sticky bit to be set on root (since 195575e9461SMike Marshall * it shows up that way by default anyhow), 196575e9461SMike Marshall * but don't show it to the server 197575e9461SMike Marshall */ 198575e9461SMike Marshall tmp_mode -= S_ISVTX; 199575e9461SMike Marshall } else { 200575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 201575e9461SMike Marshall "User attempted to set sticky bit on non-root directory; returning EINVAL.\n"); 202575e9461SMike Marshall return -EINVAL; 203575e9461SMike Marshall } 204575e9461SMike Marshall } 205575e9461SMike Marshall 206575e9461SMike Marshall if (tmp_mode & (S_ISUID)) { 207575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 208575e9461SMike Marshall "Attempting to set setuid bit (not supported); returning EINVAL.\n"); 209575e9461SMike Marshall return -EINVAL; 210575e9461SMike Marshall } 211575e9461SMike Marshall 212575e9461SMike Marshall attrs->perms = ORANGEFS_util_translate_mode(tmp_mode); 213575e9461SMike Marshall attrs->mask |= ORANGEFS_ATTR_SYS_PERM; 214575e9461SMike Marshall } 215575e9461SMike Marshall 216575e9461SMike Marshall return 0; 217575e9461SMike Marshall } 218575e9461SMike Marshall 2193c9cf98dSMartin Brandenburg static int orangefs_inode_type(enum orangefs_ds_type objtype) 2203c9cf98dSMartin Brandenburg { 2213c9cf98dSMartin Brandenburg if (objtype == ORANGEFS_TYPE_METAFILE) 2223c9cf98dSMartin Brandenburg return S_IFREG; 2233c9cf98dSMartin Brandenburg else if (objtype == ORANGEFS_TYPE_DIRECTORY) 2243c9cf98dSMartin Brandenburg return S_IFDIR; 2253c9cf98dSMartin Brandenburg else if (objtype == ORANGEFS_TYPE_SYMLINK) 2263c9cf98dSMartin Brandenburg return S_IFLNK; 2273c9cf98dSMartin Brandenburg else 2283c9cf98dSMartin Brandenburg return -1; 2293c9cf98dSMartin Brandenburg } 2303c9cf98dSMartin Brandenburg 23126662633SMartin Brandenburg static int orangefs_inode_is_stale(struct inode *inode, int new, 23226662633SMartin Brandenburg struct ORANGEFS_sys_attr_s *attrs, char *link_target) 23326662633SMartin Brandenburg { 23426662633SMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 23526662633SMartin Brandenburg int type = orangefs_inode_type(attrs->objtype); 23626662633SMartin Brandenburg if (!new) { 23726662633SMartin Brandenburg /* 23826662633SMartin Brandenburg * If the inode type or symlink target have changed then this 23926662633SMartin Brandenburg * inode is stale. 24026662633SMartin Brandenburg */ 24126662633SMartin Brandenburg if (type == -1 || !(inode->i_mode & type)) { 24226662633SMartin Brandenburg orangefs_make_bad_inode(inode); 24326662633SMartin Brandenburg return 1; 24426662633SMartin Brandenburg } 24526662633SMartin Brandenburg if (type == S_IFLNK && strncmp(orangefs_inode->link_target, 24626662633SMartin Brandenburg link_target, ORANGEFS_NAME_MAX)) { 24726662633SMartin Brandenburg orangefs_make_bad_inode(inode); 24826662633SMartin Brandenburg return 1; 24926662633SMartin Brandenburg } 25026662633SMartin Brandenburg } 25126662633SMartin Brandenburg return 0; 25226662633SMartin Brandenburg } 25326662633SMartin Brandenburg 2543c9cf98dSMartin Brandenburg int orangefs_inode_getattr(struct inode *inode, int new, int size) 2553c9cf98dSMartin Brandenburg { 2563c9cf98dSMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 2573c9cf98dSMartin Brandenburg struct orangefs_kernel_op_s *new_op; 2583c9cf98dSMartin Brandenburg loff_t inode_size, rounded_up_size; 25926662633SMartin Brandenburg int ret, type; 2603c9cf98dSMartin Brandenburg 2613c9cf98dSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__, 2623c9cf98dSMartin Brandenburg get_khandle_from_ino(inode)); 2633c9cf98dSMartin Brandenburg 2643c9cf98dSMartin Brandenburg new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); 2653c9cf98dSMartin Brandenburg if (!new_op) 2663c9cf98dSMartin Brandenburg return -ENOMEM; 2673c9cf98dSMartin Brandenburg new_op->upcall.req.getattr.refn = orangefs_inode->refn; 2683c9cf98dSMartin Brandenburg new_op->upcall.req.getattr.mask = size ? 2693c9cf98dSMartin Brandenburg ORANGEFS_ATTR_SYS_ALL_NOHINT : ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE; 2703c9cf98dSMartin Brandenburg 2713c9cf98dSMartin Brandenburg ret = service_operation(new_op, __func__, 2723c9cf98dSMartin Brandenburg get_interruptible_flag(inode)); 2733c9cf98dSMartin Brandenburg if (ret != 0) 2743c9cf98dSMartin Brandenburg goto out; 2753c9cf98dSMartin Brandenburg 27626662633SMartin Brandenburg type = orangefs_inode_type(new_op-> 2773c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.objtype); 27826662633SMartin Brandenburg ret = orangefs_inode_is_stale(inode, new, 27926662633SMartin Brandenburg &new_op->downcall.resp.getattr.attributes, 28026662633SMartin Brandenburg new_op->downcall.resp.getattr.link_target); 28126662633SMartin Brandenburg if (ret) { 2823c9cf98dSMartin Brandenburg ret = -ESTALE; 2833c9cf98dSMartin Brandenburg goto out; 2843c9cf98dSMartin Brandenburg } 2853c9cf98dSMartin Brandenburg 28626662633SMartin Brandenburg switch (type) { 2873c9cf98dSMartin Brandenburg case S_IFREG: 2883c9cf98dSMartin Brandenburg inode->i_flags = orangefs_inode_flags(&new_op-> 2893c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes); 2903c9cf98dSMartin Brandenburg if (size) { 2913c9cf98dSMartin Brandenburg inode_size = (loff_t)new_op-> 2923c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.size; 2933c9cf98dSMartin Brandenburg rounded_up_size = 2943c9cf98dSMartin Brandenburg (inode_size + (4096 - (inode_size % 4096))); 2953c9cf98dSMartin Brandenburg inode->i_size = inode_size; 2963c9cf98dSMartin Brandenburg orangefs_inode->blksize = 2973c9cf98dSMartin Brandenburg new_op->downcall.resp.getattr.attributes.blksize; 2983c9cf98dSMartin Brandenburg spin_lock(&inode->i_lock); 2993c9cf98dSMartin Brandenburg inode->i_bytes = inode_size; 3003c9cf98dSMartin Brandenburg inode->i_blocks = 3013c9cf98dSMartin Brandenburg (unsigned long)(rounded_up_size / 512); 3023c9cf98dSMartin Brandenburg spin_unlock(&inode->i_lock); 3033c9cf98dSMartin Brandenburg } 3043c9cf98dSMartin Brandenburg break; 3053c9cf98dSMartin Brandenburg case S_IFDIR: 3063c9cf98dSMartin Brandenburg inode->i_size = PAGE_CACHE_SIZE; 3073c9cf98dSMartin Brandenburg orangefs_inode->blksize = (1 << inode->i_blkbits); 3083c9cf98dSMartin Brandenburg spin_lock(&inode->i_lock); 3093c9cf98dSMartin Brandenburg inode_set_bytes(inode, inode->i_size); 3103c9cf98dSMartin Brandenburg spin_unlock(&inode->i_lock); 3113c9cf98dSMartin Brandenburg set_nlink(inode, 1); 3123c9cf98dSMartin Brandenburg break; 3133c9cf98dSMartin Brandenburg case S_IFLNK: 3143c9cf98dSMartin Brandenburg if (new) { 3153c9cf98dSMartin Brandenburg inode->i_size = (loff_t)strlen(new_op-> 3163c9cf98dSMartin Brandenburg downcall.resp.getattr.link_target); 3173c9cf98dSMartin Brandenburg orangefs_inode->blksize = (1 << inode->i_blkbits); 3182eacea74SMartin Brandenburg ret = strscpy(orangefs_inode->link_target, 3193c9cf98dSMartin Brandenburg new_op->downcall.resp.getattr.link_target, 3203c9cf98dSMartin Brandenburg ORANGEFS_NAME_MAX); 3212eacea74SMartin Brandenburg if (ret == -E2BIG) { 3222eacea74SMartin Brandenburg ret = -EIO; 3232eacea74SMartin Brandenburg goto out; 3242eacea74SMartin Brandenburg } 325e8da254cSMartin Brandenburg inode->i_link = orangefs_inode->link_target; 3263c9cf98dSMartin Brandenburg } 3273c9cf98dSMartin Brandenburg break; 3283c9cf98dSMartin Brandenburg } 3293c9cf98dSMartin Brandenburg 3303c9cf98dSMartin Brandenburg inode->i_uid = make_kuid(&init_user_ns, new_op-> 3313c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.owner); 3323c9cf98dSMartin Brandenburg inode->i_gid = make_kgid(&init_user_ns, new_op-> 3333c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.group); 3343c9cf98dSMartin Brandenburg inode->i_atime.tv_sec = (time64_t)new_op-> 3353c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.atime; 3363c9cf98dSMartin Brandenburg inode->i_mtime.tv_sec = (time64_t)new_op-> 3373c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.mtime; 3383c9cf98dSMartin Brandenburg inode->i_ctime.tv_sec = (time64_t)new_op-> 3393c9cf98dSMartin Brandenburg downcall.resp.getattr.attributes.ctime; 3403c9cf98dSMartin Brandenburg inode->i_atime.tv_nsec = 0; 3413c9cf98dSMartin Brandenburg inode->i_mtime.tv_nsec = 0; 3423c9cf98dSMartin Brandenburg inode->i_ctime.tv_nsec = 0; 3433c9cf98dSMartin Brandenburg 3443c9cf98dSMartin Brandenburg /* special case: mark the root inode as sticky */ 34526662633SMartin Brandenburg inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) | 3463c9cf98dSMartin Brandenburg orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes); 3473c9cf98dSMartin Brandenburg 3483c9cf98dSMartin Brandenburg ret = 0; 3493c9cf98dSMartin Brandenburg out: 3503c9cf98dSMartin Brandenburg op_release(new_op); 3513c9cf98dSMartin Brandenburg return ret; 3523c9cf98dSMartin Brandenburg } 3533c9cf98dSMartin Brandenburg 3545859d77eSMartin Brandenburg int orangefs_inode_check_changed(struct inode *inode) 3555859d77eSMartin Brandenburg { 3565859d77eSMartin Brandenburg struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 3575859d77eSMartin Brandenburg struct orangefs_kernel_op_s *new_op; 3585859d77eSMartin Brandenburg int ret; 3595859d77eSMartin Brandenburg 3605859d77eSMartin Brandenburg gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__, 3615859d77eSMartin Brandenburg get_khandle_from_ino(inode)); 3625859d77eSMartin Brandenburg 3635859d77eSMartin Brandenburg new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); 3645859d77eSMartin Brandenburg if (!new_op) 3655859d77eSMartin Brandenburg return -ENOMEM; 3665859d77eSMartin Brandenburg new_op->upcall.req.getattr.refn = orangefs_inode->refn; 3675859d77eSMartin Brandenburg new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE | 3685859d77eSMartin Brandenburg ORANGEFS_ATTR_SYS_LNK_TARGET; 3695859d77eSMartin Brandenburg 3705859d77eSMartin Brandenburg ret = service_operation(new_op, __func__, 3715859d77eSMartin Brandenburg get_interruptible_flag(inode)); 3725859d77eSMartin Brandenburg if (ret != 0) 3735859d77eSMartin Brandenburg goto out; 3745859d77eSMartin Brandenburg 37526662633SMartin Brandenburg ret = orangefs_inode_is_stale(inode, 0, 37626662633SMartin Brandenburg &new_op->downcall.resp.getattr.attributes, 37726662633SMartin Brandenburg new_op->downcall.resp.getattr.link_target); 3785859d77eSMartin Brandenburg out: 3795859d77eSMartin Brandenburg op_release(new_op); 3805859d77eSMartin Brandenburg return ret; 3815859d77eSMartin Brandenburg } 3825859d77eSMartin Brandenburg 383575e9461SMike Marshall /* 384575e9461SMike Marshall * issues a orangefs setattr request to make sure the new attribute values 385575e9461SMike Marshall * take effect if successful. returns 0 on success; -errno otherwise 386575e9461SMike Marshall */ 387575e9461SMike Marshall int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr) 388575e9461SMike Marshall { 389575e9461SMike Marshall struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 390575e9461SMike Marshall struct orangefs_kernel_op_s *new_op; 391575e9461SMike Marshall int ret; 392575e9461SMike Marshall 393575e9461SMike Marshall new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR); 394575e9461SMike Marshall if (!new_op) 395575e9461SMike Marshall return -ENOMEM; 396575e9461SMike Marshall 397575e9461SMike Marshall new_op->upcall.req.setattr.refn = orangefs_inode->refn; 398575e9461SMike Marshall ret = copy_attributes_from_inode(inode, 399575e9461SMike Marshall &new_op->upcall.req.setattr.attributes, 400575e9461SMike Marshall iattr); 401ed42fe05SAl Viro if (ret >= 0) { 402575e9461SMike Marshall ret = service_operation(new_op, __func__, 403575e9461SMike Marshall get_interruptible_flag(inode)); 404575e9461SMike Marshall 405575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 406575e9461SMike Marshall "orangefs_inode_setattr: returning %d\n", 407575e9461SMike Marshall ret); 408ed42fe05SAl Viro } 409575e9461SMike Marshall 410575e9461SMike Marshall op_release(new_op); 411575e9461SMike Marshall 412575e9461SMike Marshall /* 413575e9461SMike Marshall * successful setattr should clear the atime, mtime and 414575e9461SMike Marshall * ctime flags. 415575e9461SMike Marshall */ 416575e9461SMike Marshall if (ret == 0) { 417575e9461SMike Marshall ClearAtimeFlag(orangefs_inode); 418575e9461SMike Marshall ClearMtimeFlag(orangefs_inode); 419575e9461SMike Marshall ClearCtimeFlag(orangefs_inode); 420575e9461SMike Marshall ClearModeFlag(orangefs_inode); 421575e9461SMike Marshall } 422575e9461SMike Marshall 423575e9461SMike Marshall return ret; 424575e9461SMike Marshall } 425575e9461SMike Marshall 426575e9461SMike Marshall int orangefs_flush_inode(struct inode *inode) 427575e9461SMike Marshall { 428575e9461SMike Marshall /* 429575e9461SMike Marshall * If it is a dirty inode, this function gets called. 430575e9461SMike Marshall * Gather all the information that needs to be setattr'ed 431575e9461SMike Marshall * Right now, this will only be used for mode, atime, mtime 432575e9461SMike Marshall * and/or ctime. 433575e9461SMike Marshall */ 434575e9461SMike Marshall struct iattr wbattr; 435575e9461SMike Marshall int ret; 436575e9461SMike Marshall int mtime_flag; 437575e9461SMike Marshall int ctime_flag; 438575e9461SMike Marshall int atime_flag; 439575e9461SMike Marshall int mode_flag; 440575e9461SMike Marshall struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 441575e9461SMike Marshall 442575e9461SMike Marshall memset(&wbattr, 0, sizeof(wbattr)); 443575e9461SMike Marshall 444575e9461SMike Marshall /* 445575e9461SMike Marshall * check inode flags up front, and clear them if they are set. This 446575e9461SMike Marshall * will prevent multiple processes from all trying to flush the same 447575e9461SMike Marshall * inode if they call close() simultaneously 448575e9461SMike Marshall */ 449575e9461SMike Marshall mtime_flag = MtimeFlag(orangefs_inode); 450575e9461SMike Marshall ClearMtimeFlag(orangefs_inode); 451575e9461SMike Marshall ctime_flag = CtimeFlag(orangefs_inode); 452575e9461SMike Marshall ClearCtimeFlag(orangefs_inode); 453575e9461SMike Marshall atime_flag = AtimeFlag(orangefs_inode); 454575e9461SMike Marshall ClearAtimeFlag(orangefs_inode); 455575e9461SMike Marshall mode_flag = ModeFlag(orangefs_inode); 456575e9461SMike Marshall ClearModeFlag(orangefs_inode); 457575e9461SMike Marshall 458575e9461SMike Marshall /* -- Lazy atime,mtime and ctime update -- 459575e9461SMike Marshall * Note: all times are dictated by server in the new scheme 460575e9461SMike Marshall * and not by the clients 461575e9461SMike Marshall * 462575e9461SMike Marshall * Also mode updates are being handled now.. 463575e9461SMike Marshall */ 464575e9461SMike Marshall 465575e9461SMike Marshall if (mtime_flag) 466575e9461SMike Marshall wbattr.ia_valid |= ATTR_MTIME; 467575e9461SMike Marshall if (ctime_flag) 468575e9461SMike Marshall wbattr.ia_valid |= ATTR_CTIME; 469575e9461SMike Marshall if (atime_flag) 470575e9461SMike Marshall wbattr.ia_valid |= ATTR_ATIME; 471575e9461SMike Marshall 472575e9461SMike Marshall if (mode_flag) { 473575e9461SMike Marshall wbattr.ia_mode = inode->i_mode; 474575e9461SMike Marshall wbattr.ia_valid |= ATTR_MODE; 475575e9461SMike Marshall } 476575e9461SMike Marshall 477575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 478575e9461SMike Marshall "*********** orangefs_flush_inode: %pU " 479575e9461SMike Marshall "(ia_valid %d)\n", 480575e9461SMike Marshall get_khandle_from_ino(inode), 481575e9461SMike Marshall wbattr.ia_valid); 482575e9461SMike Marshall if (wbattr.ia_valid == 0) { 483575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 484575e9461SMike Marshall "orangefs_flush_inode skipping setattr()\n"); 485575e9461SMike Marshall return 0; 486575e9461SMike Marshall } 487575e9461SMike Marshall 488575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 489575e9461SMike Marshall "orangefs_flush_inode (%pU) writing mode %o\n", 490575e9461SMike Marshall get_khandle_from_ino(inode), 491575e9461SMike Marshall inode->i_mode); 492575e9461SMike Marshall 493575e9461SMike Marshall ret = orangefs_inode_setattr(inode, &wbattr); 494575e9461SMike Marshall 495575e9461SMike Marshall return ret; 496575e9461SMike Marshall } 497575e9461SMike Marshall 498575e9461SMike Marshall int orangefs_unmount_sb(struct super_block *sb) 499575e9461SMike Marshall { 500575e9461SMike Marshall int ret = -EINVAL; 501575e9461SMike Marshall struct orangefs_kernel_op_s *new_op = NULL; 502575e9461SMike Marshall 503575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 504575e9461SMike Marshall "orangefs_unmount_sb called on sb %p\n", 505575e9461SMike Marshall sb); 506575e9461SMike Marshall 507575e9461SMike Marshall new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT); 508575e9461SMike Marshall if (!new_op) 509575e9461SMike Marshall return -ENOMEM; 510575e9461SMike Marshall new_op->upcall.req.fs_umount.id = ORANGEFS_SB(sb)->id; 511575e9461SMike Marshall new_op->upcall.req.fs_umount.fs_id = ORANGEFS_SB(sb)->fs_id; 512575e9461SMike Marshall strncpy(new_op->upcall.req.fs_umount.orangefs_config_server, 513575e9461SMike Marshall ORANGEFS_SB(sb)->devname, 514575e9461SMike Marshall ORANGEFS_MAX_SERVER_ADDR_LEN); 515575e9461SMike Marshall 516575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 517575e9461SMike Marshall "Attempting ORANGEFS Unmount via host %s\n", 518575e9461SMike Marshall new_op->upcall.req.fs_umount.orangefs_config_server); 519575e9461SMike Marshall 520575e9461SMike Marshall ret = service_operation(new_op, "orangefs_fs_umount", 0); 521575e9461SMike Marshall 522575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 523575e9461SMike Marshall "orangefs_unmount: got return value of %d\n", ret); 524575e9461SMike Marshall if (ret) 525575e9461SMike Marshall sb = ERR_PTR(ret); 526575e9461SMike Marshall else 527575e9461SMike Marshall ORANGEFS_SB(sb)->mount_pending = 1; 528575e9461SMike Marshall 529575e9461SMike Marshall op_release(new_op); 530575e9461SMike Marshall return ret; 531575e9461SMike Marshall } 532575e9461SMike Marshall 533575e9461SMike Marshall void orangefs_make_bad_inode(struct inode *inode) 534575e9461SMike Marshall { 535575e9461SMike Marshall if (is_root_handle(inode)) { 536575e9461SMike Marshall /* 537575e9461SMike Marshall * if this occurs, the pvfs2-client-core was killed but we 538575e9461SMike Marshall * can't afford to lose the inode operations and such 539575e9461SMike Marshall * associated with the root handle in any case. 540575e9461SMike Marshall */ 541575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 542575e9461SMike Marshall "*** NOT making bad root inode %pU\n", 543575e9461SMike Marshall get_khandle_from_ino(inode)); 544575e9461SMike Marshall } else { 545575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 546575e9461SMike Marshall "*** making bad inode %pU\n", 547575e9461SMike Marshall get_khandle_from_ino(inode)); 548575e9461SMike Marshall make_bad_inode(inode); 549575e9461SMike Marshall } 550575e9461SMike Marshall } 551575e9461SMike Marshall 552575e9461SMike Marshall /* 553575e9461SMike Marshall * The following is a very dirty hack that is now a permanent part of the 554575e9461SMike Marshall * ORANGEFS protocol. See protocol.h for more error definitions. 555575e9461SMike Marshall */ 556575e9461SMike Marshall 557575e9461SMike Marshall /* The order matches include/orangefs-types.h in the OrangeFS source. */ 558575e9461SMike Marshall static int PINT_errno_mapping[] = { 559575e9461SMike Marshall 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM, 560575e9461SMike Marshall EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE, 561575e9461SMike Marshall EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG, 562575e9461SMike Marshall ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH, 563575e9461SMike Marshall EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM, 564575e9461SMike Marshall EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE, 565575e9461SMike Marshall ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE, 566575e9461SMike Marshall EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS, 567575e9461SMike Marshall ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY, 568575e9461SMike Marshall EACCES, ECONNRESET, ERANGE 569575e9461SMike Marshall }; 570575e9461SMike Marshall 571575e9461SMike Marshall int orangefs_normalize_to_errno(__s32 error_code) 572575e9461SMike Marshall { 573575e9461SMike Marshall __u32 i; 574575e9461SMike Marshall 575575e9461SMike Marshall /* Success */ 576575e9461SMike Marshall if (error_code == 0) { 577575e9461SMike Marshall return 0; 578575e9461SMike Marshall /* 579575e9461SMike Marshall * This shouldn't ever happen. If it does it should be fixed on the 580575e9461SMike Marshall * server. 581575e9461SMike Marshall */ 582575e9461SMike Marshall } else if (error_code > 0) { 583575e9461SMike Marshall gossip_err("orangefs: error status receieved.\n"); 584575e9461SMike Marshall gossip_err("orangefs: assuming error code is inverted.\n"); 585575e9461SMike Marshall error_code = -error_code; 586575e9461SMike Marshall } 587575e9461SMike Marshall 588575e9461SMike Marshall /* 589575e9461SMike Marshall * XXX: This is very bad since error codes from ORANGEFS may not be 590575e9461SMike Marshall * suitable for return into userspace. 591575e9461SMike Marshall */ 592575e9461SMike Marshall 593575e9461SMike Marshall /* 594575e9461SMike Marshall * Convert ORANGEFS error values into errno values suitable for return 595575e9461SMike Marshall * from the kernel. 596575e9461SMike Marshall */ 597575e9461SMike Marshall if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) { 598575e9461SMike Marshall if (((-error_code) & 599575e9461SMike Marshall (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT| 600575e9461SMike Marshall ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) { 601575e9461SMike Marshall /* 602575e9461SMike Marshall * cancellation error codes generally correspond to 603575e9461SMike Marshall * a timeout from the client's perspective 604575e9461SMike Marshall */ 605575e9461SMike Marshall error_code = -ETIMEDOUT; 606575e9461SMike Marshall } else { 607575e9461SMike Marshall /* assume a default error code */ 608575e9461SMike Marshall gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code); 609575e9461SMike Marshall error_code = -EINVAL; 610575e9461SMike Marshall } 611575e9461SMike Marshall 612575e9461SMike Marshall /* Convert ORANGEFS encoded errno values into regular errno values. */ 613575e9461SMike Marshall } else if ((-error_code) & ORANGEFS_ERROR_BIT) { 614575e9461SMike Marshall i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS); 615575e9461SMike Marshall if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping)) 616575e9461SMike Marshall error_code = -PINT_errno_mapping[i]; 617575e9461SMike Marshall else 618575e9461SMike Marshall error_code = -EINVAL; 619575e9461SMike Marshall 620575e9461SMike Marshall /* 621575e9461SMike Marshall * Only ORANGEFS protocol error codes should ever come here. Otherwise 622575e9461SMike Marshall * there is a bug somewhere. 623575e9461SMike Marshall */ 624575e9461SMike Marshall } else { 625575e9461SMike Marshall gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n"); 626575e9461SMike Marshall } 627575e9461SMike Marshall return error_code; 628575e9461SMike Marshall } 629575e9461SMike Marshall 630575e9461SMike Marshall #define NUM_MODES 11 631575e9461SMike Marshall __s32 ORANGEFS_util_translate_mode(int mode) 632575e9461SMike Marshall { 633575e9461SMike Marshall int ret = 0; 634575e9461SMike Marshall int i = 0; 635575e9461SMike Marshall static int modes[NUM_MODES] = { 636575e9461SMike Marshall S_IXOTH, S_IWOTH, S_IROTH, 637575e9461SMike Marshall S_IXGRP, S_IWGRP, S_IRGRP, 638575e9461SMike Marshall S_IXUSR, S_IWUSR, S_IRUSR, 639575e9461SMike Marshall S_ISGID, S_ISUID 640575e9461SMike Marshall }; 641575e9461SMike Marshall static int orangefs_modes[NUM_MODES] = { 642575e9461SMike Marshall ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ, 643575e9461SMike Marshall ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ, 644575e9461SMike Marshall ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ, 645575e9461SMike Marshall ORANGEFS_G_SGID, ORANGEFS_U_SUID 646575e9461SMike Marshall }; 647575e9461SMike Marshall 648575e9461SMike Marshall for (i = 0; i < NUM_MODES; i++) 649575e9461SMike Marshall if (mode & modes[i]) 650575e9461SMike Marshall ret |= orangefs_modes[i]; 651575e9461SMike Marshall 652575e9461SMike Marshall return ret; 653575e9461SMike Marshall } 654575e9461SMike Marshall #undef NUM_MODES 655575e9461SMike Marshall 656575e9461SMike Marshall /* 657575e9461SMike Marshall * After obtaining a string representation of the client's debug 658575e9461SMike Marshall * keywords and their associated masks, this function is called to build an 659575e9461SMike Marshall * array of these values. 660575e9461SMike Marshall */ 661575e9461SMike Marshall int orangefs_prepare_cdm_array(char *debug_array_string) 662575e9461SMike Marshall { 663575e9461SMike Marshall int i; 664575e9461SMike Marshall int rc = -EINVAL; 665575e9461SMike Marshall char *cds_head = NULL; 666575e9461SMike Marshall char *cds_delimiter = NULL; 667575e9461SMike Marshall int keyword_len = 0; 668575e9461SMike Marshall 669575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 670575e9461SMike Marshall 671575e9461SMike Marshall /* 672575e9461SMike Marshall * figure out how many elements the cdm_array needs. 673575e9461SMike Marshall */ 674575e9461SMike Marshall for (i = 0; i < strlen(debug_array_string); i++) 675575e9461SMike Marshall if (debug_array_string[i] == '\n') 676575e9461SMike Marshall cdm_element_count++; 677575e9461SMike Marshall 678575e9461SMike Marshall if (!cdm_element_count) { 679575e9461SMike Marshall pr_info("No elements in client debug array string!\n"); 680575e9461SMike Marshall goto out; 681575e9461SMike Marshall } 682575e9461SMike Marshall 683575e9461SMike Marshall cdm_array = 684575e9461SMike Marshall kzalloc(cdm_element_count * sizeof(struct client_debug_mask), 685575e9461SMike Marshall GFP_KERNEL); 686575e9461SMike Marshall if (!cdm_array) { 687575e9461SMike Marshall pr_info("malloc failed for cdm_array!\n"); 688575e9461SMike Marshall rc = -ENOMEM; 689575e9461SMike Marshall goto out; 690575e9461SMike Marshall } 691575e9461SMike Marshall 692575e9461SMike Marshall cds_head = debug_array_string; 693575e9461SMike Marshall 694575e9461SMike Marshall for (i = 0; i < cdm_element_count; i++) { 695575e9461SMike Marshall cds_delimiter = strchr(cds_head, '\n'); 696575e9461SMike Marshall *cds_delimiter = '\0'; 697575e9461SMike Marshall 698575e9461SMike Marshall keyword_len = strcspn(cds_head, " "); 699575e9461SMike Marshall 700575e9461SMike Marshall cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL); 701575e9461SMike Marshall if (!cdm_array[i].keyword) { 702575e9461SMike Marshall rc = -ENOMEM; 703575e9461SMike Marshall goto out; 704575e9461SMike Marshall } 705575e9461SMike Marshall 706575e9461SMike Marshall sscanf(cds_head, 707575e9461SMike Marshall "%s %llx %llx", 708575e9461SMike Marshall cdm_array[i].keyword, 709575e9461SMike Marshall (unsigned long long *)&(cdm_array[i].mask1), 710575e9461SMike Marshall (unsigned long long *)&(cdm_array[i].mask2)); 711575e9461SMike Marshall 712575e9461SMike Marshall if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE)) 713575e9461SMike Marshall client_verbose_index = i; 714575e9461SMike Marshall 715575e9461SMike Marshall if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL)) 716575e9461SMike Marshall client_all_index = i; 717575e9461SMike Marshall 718575e9461SMike Marshall cds_head = cds_delimiter + 1; 719575e9461SMike Marshall } 720575e9461SMike Marshall 721575e9461SMike Marshall rc = cdm_element_count; 722575e9461SMike Marshall 723575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc); 724575e9461SMike Marshall 725575e9461SMike Marshall out: 726575e9461SMike Marshall 727575e9461SMike Marshall return rc; 728575e9461SMike Marshall 729575e9461SMike Marshall } 730575e9461SMike Marshall 731575e9461SMike Marshall /* 732575e9461SMike Marshall * /sys/kernel/debug/orangefs/debug-help can be catted to 733575e9461SMike Marshall * see all the available kernel and client debug keywords. 734575e9461SMike Marshall * 735575e9461SMike Marshall * When the kernel boots, we have no idea what keywords the 736575e9461SMike Marshall * client supports, nor their associated masks. 737575e9461SMike Marshall * 738575e9461SMike Marshall * We pass through this function once at boot and stamp a 739575e9461SMike Marshall * boilerplate "we don't know" message for the client in the 740575e9461SMike Marshall * debug-help file. We pass through here again when the client 741575e9461SMike Marshall * starts and then we can fill out the debug-help file fully. 742575e9461SMike Marshall * 743575e9461SMike Marshall * The client might be restarted any number of times between 744575e9461SMike Marshall * reboots, we only build the debug-help file the first time. 745575e9461SMike Marshall */ 746575e9461SMike Marshall int orangefs_prepare_debugfs_help_string(int at_boot) 747575e9461SMike Marshall { 748575e9461SMike Marshall int rc = -EINVAL; 749575e9461SMike Marshall int i; 750575e9461SMike Marshall int byte_count = 0; 751575e9461SMike Marshall char *client_title = "Client Debug Keywords:\n"; 752575e9461SMike Marshall char *kernel_title = "Kernel Debug Keywords:\n"; 753575e9461SMike Marshall 754575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 755575e9461SMike Marshall 756575e9461SMike Marshall if (at_boot) { 757575e9461SMike Marshall byte_count += strlen(HELP_STRING_UNINITIALIZED); 758575e9461SMike Marshall client_title = HELP_STRING_UNINITIALIZED; 759575e9461SMike Marshall } else { 760575e9461SMike Marshall /* 761575e9461SMike Marshall * fill the client keyword/mask array and remember 762575e9461SMike Marshall * how many elements there were. 763575e9461SMike Marshall */ 764575e9461SMike Marshall cdm_element_count = 765575e9461SMike Marshall orangefs_prepare_cdm_array(client_debug_array_string); 766575e9461SMike Marshall if (cdm_element_count <= 0) 767575e9461SMike Marshall goto out; 768575e9461SMike Marshall 769575e9461SMike Marshall /* Count the bytes destined for debug_help_string. */ 770575e9461SMike Marshall byte_count += strlen(client_title); 771575e9461SMike Marshall 772575e9461SMike Marshall for (i = 0; i < cdm_element_count; i++) { 773575e9461SMike Marshall byte_count += strlen(cdm_array[i].keyword + 2); 774575e9461SMike Marshall if (byte_count >= DEBUG_HELP_STRING_SIZE) { 775575e9461SMike Marshall pr_info("%s: overflow 1!\n", __func__); 776575e9461SMike Marshall goto out; 777575e9461SMike Marshall } 778575e9461SMike Marshall } 779575e9461SMike Marshall 780575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, 781575e9461SMike Marshall "%s: cdm_element_count:%d:\n", 782575e9461SMike Marshall __func__, 783575e9461SMike Marshall cdm_element_count); 784575e9461SMike Marshall } 785575e9461SMike Marshall 786575e9461SMike Marshall byte_count += strlen(kernel_title); 787575e9461SMike Marshall for (i = 0; i < num_kmod_keyword_mask_map; i++) { 788575e9461SMike Marshall byte_count += 789575e9461SMike Marshall strlen(s_kmod_keyword_mask_map[i].keyword + 2); 790575e9461SMike Marshall if (byte_count >= DEBUG_HELP_STRING_SIZE) { 791575e9461SMike Marshall pr_info("%s: overflow 2!\n", __func__); 792575e9461SMike Marshall goto out; 793575e9461SMike Marshall } 794575e9461SMike Marshall } 795575e9461SMike Marshall 796575e9461SMike Marshall /* build debug_help_string. */ 797575e9461SMike Marshall debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); 798575e9461SMike Marshall if (!debug_help_string) { 799575e9461SMike Marshall rc = -ENOMEM; 800575e9461SMike Marshall goto out; 801575e9461SMike Marshall } 802575e9461SMike Marshall 803575e9461SMike Marshall strcat(debug_help_string, client_title); 804575e9461SMike Marshall 805575e9461SMike Marshall if (!at_boot) { 806575e9461SMike Marshall for (i = 0; i < cdm_element_count; i++) { 807575e9461SMike Marshall strcat(debug_help_string, "\t"); 808575e9461SMike Marshall strcat(debug_help_string, cdm_array[i].keyword); 809575e9461SMike Marshall strcat(debug_help_string, "\n"); 810575e9461SMike Marshall } 811575e9461SMike Marshall } 812575e9461SMike Marshall 813575e9461SMike Marshall strcat(debug_help_string, "\n"); 814575e9461SMike Marshall strcat(debug_help_string, kernel_title); 815575e9461SMike Marshall 816575e9461SMike Marshall for (i = 0; i < num_kmod_keyword_mask_map; i++) { 817575e9461SMike Marshall strcat(debug_help_string, "\t"); 818575e9461SMike Marshall strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword); 819575e9461SMike Marshall strcat(debug_help_string, "\n"); 820575e9461SMike Marshall } 821575e9461SMike Marshall 822575e9461SMike Marshall rc = 0; 823575e9461SMike Marshall 824575e9461SMike Marshall out: 825575e9461SMike Marshall 826575e9461SMike Marshall return rc; 827575e9461SMike Marshall 828575e9461SMike Marshall } 829575e9461SMike Marshall 830575e9461SMike Marshall /* 831575e9461SMike Marshall * kernel = type 0 832575e9461SMike Marshall * client = type 1 833575e9461SMike Marshall */ 834575e9461SMike Marshall void debug_mask_to_string(void *mask, int type) 835575e9461SMike Marshall { 836575e9461SMike Marshall int i; 837575e9461SMike Marshall int len = 0; 838575e9461SMike Marshall char *debug_string; 839575e9461SMike Marshall int element_count = 0; 840575e9461SMike Marshall 841575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 842575e9461SMike Marshall 843575e9461SMike Marshall if (type) { 844575e9461SMike Marshall debug_string = client_debug_string; 845575e9461SMike Marshall element_count = cdm_element_count; 846575e9461SMike Marshall } else { 847575e9461SMike Marshall debug_string = kernel_debug_string; 848575e9461SMike Marshall element_count = num_kmod_keyword_mask_map; 849575e9461SMike Marshall } 850575e9461SMike Marshall 851575e9461SMike Marshall memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); 852575e9461SMike Marshall 853575e9461SMike Marshall /* 854575e9461SMike Marshall * Some keywords, like "all" or "verbose", are amalgams of 855575e9461SMike Marshall * numerous other keywords. Make a special check for those 856575e9461SMike Marshall * before grinding through the whole mask only to find out 857575e9461SMike Marshall * later... 858575e9461SMike Marshall */ 859575e9461SMike Marshall if (check_amalgam_keyword(mask, type)) 860575e9461SMike Marshall goto out; 861575e9461SMike Marshall 862575e9461SMike Marshall /* Build the debug string. */ 863575e9461SMike Marshall for (i = 0; i < element_count; i++) 864575e9461SMike Marshall if (type) 865575e9461SMike Marshall do_c_string(mask, i); 866575e9461SMike Marshall else 867575e9461SMike Marshall do_k_string(mask, i); 868575e9461SMike Marshall 869575e9461SMike Marshall len = strlen(debug_string); 870575e9461SMike Marshall 871575e9461SMike Marshall if ((len) && (type)) 872575e9461SMike Marshall client_debug_string[len - 1] = '\0'; 873575e9461SMike Marshall else if (len) 874575e9461SMike Marshall kernel_debug_string[len - 1] = '\0'; 875575e9461SMike Marshall else if (type) 876575e9461SMike Marshall strcpy(client_debug_string, "none"); 877575e9461SMike Marshall else 878575e9461SMike Marshall strcpy(kernel_debug_string, "none"); 879575e9461SMike Marshall 880575e9461SMike Marshall out: 881575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string); 882575e9461SMike Marshall 883575e9461SMike Marshall return; 884575e9461SMike Marshall 885575e9461SMike Marshall } 886575e9461SMike Marshall 887575e9461SMike Marshall void do_k_string(void *k_mask, int index) 888575e9461SMike Marshall { 889575e9461SMike Marshall __u64 *mask = (__u64 *) k_mask; 890575e9461SMike Marshall 891575e9461SMike Marshall if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword)) 892575e9461SMike Marshall goto out; 893575e9461SMike Marshall 894575e9461SMike Marshall if (*mask & s_kmod_keyword_mask_map[index].mask_val) { 895575e9461SMike Marshall if ((strlen(kernel_debug_string) + 896575e9461SMike Marshall strlen(s_kmod_keyword_mask_map[index].keyword)) 897575e9461SMike Marshall < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) { 898575e9461SMike Marshall strcat(kernel_debug_string, 899575e9461SMike Marshall s_kmod_keyword_mask_map[index].keyword); 900575e9461SMike Marshall strcat(kernel_debug_string, ","); 901575e9461SMike Marshall } else { 902575e9461SMike Marshall gossip_err("%s: overflow!\n", __func__); 903575e9461SMike Marshall strcpy(kernel_debug_string, ORANGEFS_ALL); 904575e9461SMike Marshall goto out; 905575e9461SMike Marshall } 906575e9461SMike Marshall } 907575e9461SMike Marshall 908575e9461SMike Marshall out: 909575e9461SMike Marshall 910575e9461SMike Marshall return; 911575e9461SMike Marshall } 912575e9461SMike Marshall 913575e9461SMike Marshall void do_c_string(void *c_mask, int index) 914575e9461SMike Marshall { 915575e9461SMike Marshall struct client_debug_mask *mask = (struct client_debug_mask *) c_mask; 916575e9461SMike Marshall 917575e9461SMike Marshall if (keyword_is_amalgam(cdm_array[index].keyword)) 918575e9461SMike Marshall goto out; 919575e9461SMike Marshall 920575e9461SMike Marshall if ((mask->mask1 & cdm_array[index].mask1) || 921575e9461SMike Marshall (mask->mask2 & cdm_array[index].mask2)) { 922575e9461SMike Marshall if ((strlen(client_debug_string) + 923575e9461SMike Marshall strlen(cdm_array[index].keyword) + 1) 924575e9461SMike Marshall < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) { 925575e9461SMike Marshall strcat(client_debug_string, 926575e9461SMike Marshall cdm_array[index].keyword); 927575e9461SMike Marshall strcat(client_debug_string, ","); 928575e9461SMike Marshall } else { 929575e9461SMike Marshall gossip_err("%s: overflow!\n", __func__); 930575e9461SMike Marshall strcpy(client_debug_string, ORANGEFS_ALL); 931575e9461SMike Marshall goto out; 932575e9461SMike Marshall } 933575e9461SMike Marshall } 934575e9461SMike Marshall out: 935575e9461SMike Marshall return; 936575e9461SMike Marshall } 937575e9461SMike Marshall 938575e9461SMike Marshall int keyword_is_amalgam(char *keyword) 939575e9461SMike Marshall { 940575e9461SMike Marshall int rc = 0; 941575e9461SMike Marshall 942575e9461SMike Marshall if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE))) 943575e9461SMike Marshall rc = 1; 944575e9461SMike Marshall 945575e9461SMike Marshall return rc; 946575e9461SMike Marshall } 947575e9461SMike Marshall 948575e9461SMike Marshall /* 949575e9461SMike Marshall * kernel = type 0 950575e9461SMike Marshall * client = type 1 951575e9461SMike Marshall * 952575e9461SMike Marshall * return 1 if we found an amalgam. 953575e9461SMike Marshall */ 954575e9461SMike Marshall int check_amalgam_keyword(void *mask, int type) 955575e9461SMike Marshall { 956575e9461SMike Marshall __u64 *k_mask; 957575e9461SMike Marshall struct client_debug_mask *c_mask; 958575e9461SMike Marshall int k_all_index = num_kmod_keyword_mask_map - 1; 959575e9461SMike Marshall int rc = 0; 960575e9461SMike Marshall 961575e9461SMike Marshall if (type) { 962575e9461SMike Marshall c_mask = (struct client_debug_mask *) mask; 963575e9461SMike Marshall 964575e9461SMike Marshall if ((c_mask->mask1 == cdm_array[client_all_index].mask1) && 965575e9461SMike Marshall (c_mask->mask2 == cdm_array[client_all_index].mask2)) { 966575e9461SMike Marshall strcpy(client_debug_string, ORANGEFS_ALL); 967575e9461SMike Marshall rc = 1; 968575e9461SMike Marshall goto out; 969575e9461SMike Marshall } 970575e9461SMike Marshall 971575e9461SMike Marshall if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) && 972575e9461SMike Marshall (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) { 973575e9461SMike Marshall strcpy(client_debug_string, ORANGEFS_VERBOSE); 974575e9461SMike Marshall rc = 1; 975575e9461SMike Marshall goto out; 976575e9461SMike Marshall } 977575e9461SMike Marshall 978575e9461SMike Marshall } else { 979575e9461SMike Marshall k_mask = (__u64 *) mask; 980575e9461SMike Marshall 981575e9461SMike Marshall if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) { 982575e9461SMike Marshall strcpy(kernel_debug_string, ORANGEFS_ALL); 983575e9461SMike Marshall rc = 1; 984575e9461SMike Marshall goto out; 985575e9461SMike Marshall } 986575e9461SMike Marshall } 987575e9461SMike Marshall 988575e9461SMike Marshall out: 989575e9461SMike Marshall 990575e9461SMike Marshall return rc; 991575e9461SMike Marshall } 992575e9461SMike Marshall 993575e9461SMike Marshall /* 994575e9461SMike Marshall * kernel = type 0 995575e9461SMike Marshall * client = type 1 996575e9461SMike Marshall */ 997575e9461SMike Marshall void debug_string_to_mask(char *debug_string, void *mask, int type) 998575e9461SMike Marshall { 999575e9461SMike Marshall char *unchecked_keyword; 1000575e9461SMike Marshall int i; 1001575e9461SMike Marshall char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL); 1002575e9461SMike Marshall char *original_pointer; 1003575e9461SMike Marshall int element_count = 0; 1004575e9461SMike Marshall struct client_debug_mask *c_mask; 1005575e9461SMike Marshall __u64 *k_mask; 1006575e9461SMike Marshall 1007575e9461SMike Marshall gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); 1008575e9461SMike Marshall 1009575e9461SMike Marshall if (type) { 1010575e9461SMike Marshall c_mask = (struct client_debug_mask *)mask; 1011575e9461SMike Marshall element_count = cdm_element_count; 1012575e9461SMike Marshall } else { 1013575e9461SMike Marshall k_mask = (__u64 *)mask; 1014575e9461SMike Marshall *k_mask = 0; 1015575e9461SMike Marshall element_count = num_kmod_keyword_mask_map; 1016575e9461SMike Marshall } 1017575e9461SMike Marshall 1018575e9461SMike Marshall original_pointer = strsep_fodder; 1019575e9461SMike Marshall while ((unchecked_keyword = strsep(&strsep_fodder, ","))) 1020575e9461SMike Marshall if (strlen(unchecked_keyword)) { 1021575e9461SMike Marshall for (i = 0; i < element_count; i++) 1022575e9461SMike Marshall if (type) 1023575e9461SMike Marshall do_c_mask(i, 1024575e9461SMike Marshall unchecked_keyword, 1025575e9461SMike Marshall &c_mask); 1026575e9461SMike Marshall else 1027575e9461SMike Marshall do_k_mask(i, 1028575e9461SMike Marshall unchecked_keyword, 1029575e9461SMike Marshall &k_mask); 1030575e9461SMike Marshall } 1031575e9461SMike Marshall 1032575e9461SMike Marshall kfree(original_pointer); 1033575e9461SMike Marshall } 1034575e9461SMike Marshall 1035575e9461SMike Marshall void do_c_mask(int i, 1036575e9461SMike Marshall char *unchecked_keyword, 1037575e9461SMike Marshall struct client_debug_mask **sane_mask) 1038575e9461SMike Marshall { 1039575e9461SMike Marshall 1040575e9461SMike Marshall if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) { 1041575e9461SMike Marshall (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1; 1042575e9461SMike Marshall (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2; 1043575e9461SMike Marshall } 1044575e9461SMike Marshall } 1045575e9461SMike Marshall 1046575e9461SMike Marshall void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask) 1047575e9461SMike Marshall { 1048575e9461SMike Marshall 1049575e9461SMike Marshall if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword)) 1050575e9461SMike Marshall **sane_mask = (**sane_mask) | 1051575e9461SMike Marshall s_kmod_keyword_mask_map[i].mask_val; 1052575e9461SMike Marshall } 1053