linux/fs/orangefs/orangefs-utils.c
<<
>>
Prefs
   1/*
   2 * (C) 2001 Clemson University and The University of Chicago
   3 *
   4 * See COPYING in top-level directory.
   5 */
   6#include "protocol.h"
   7#include "orangefs-kernel.h"
   8#include "orangefs-dev-proto.h"
   9#include "orangefs-bufmap.h"
  10
  11__s32 fsid_of_op(struct orangefs_kernel_op_s *op)
  12{
  13        __s32 fsid = ORANGEFS_FS_ID_NULL;
  14
  15        if (op) {
  16                switch (op->upcall.type) {
  17                case ORANGEFS_VFS_OP_FILE_IO:
  18                        fsid = op->upcall.req.io.refn.fs_id;
  19                        break;
  20                case ORANGEFS_VFS_OP_LOOKUP:
  21                        fsid = op->upcall.req.lookup.parent_refn.fs_id;
  22                        break;
  23                case ORANGEFS_VFS_OP_CREATE:
  24                        fsid = op->upcall.req.create.parent_refn.fs_id;
  25                        break;
  26                case ORANGEFS_VFS_OP_GETATTR:
  27                        fsid = op->upcall.req.getattr.refn.fs_id;
  28                        break;
  29                case ORANGEFS_VFS_OP_REMOVE:
  30                        fsid = op->upcall.req.remove.parent_refn.fs_id;
  31                        break;
  32                case ORANGEFS_VFS_OP_MKDIR:
  33                        fsid = op->upcall.req.mkdir.parent_refn.fs_id;
  34                        break;
  35                case ORANGEFS_VFS_OP_READDIR:
  36                        fsid = op->upcall.req.readdir.refn.fs_id;
  37                        break;
  38                case ORANGEFS_VFS_OP_SETATTR:
  39                        fsid = op->upcall.req.setattr.refn.fs_id;
  40                        break;
  41                case ORANGEFS_VFS_OP_SYMLINK:
  42                        fsid = op->upcall.req.sym.parent_refn.fs_id;
  43                        break;
  44                case ORANGEFS_VFS_OP_RENAME:
  45                        fsid = op->upcall.req.rename.old_parent_refn.fs_id;
  46                        break;
  47                case ORANGEFS_VFS_OP_STATFS:
  48                        fsid = op->upcall.req.statfs.fs_id;
  49                        break;
  50                case ORANGEFS_VFS_OP_TRUNCATE:
  51                        fsid = op->upcall.req.truncate.refn.fs_id;
  52                        break;
  53                case ORANGEFS_VFS_OP_MMAP_RA_FLUSH:
  54                        fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
  55                        break;
  56                case ORANGEFS_VFS_OP_FS_UMOUNT:
  57                        fsid = op->upcall.req.fs_umount.fs_id;
  58                        break;
  59                case ORANGEFS_VFS_OP_GETXATTR:
  60                        fsid = op->upcall.req.getxattr.refn.fs_id;
  61                        break;
  62                case ORANGEFS_VFS_OP_SETXATTR:
  63                        fsid = op->upcall.req.setxattr.refn.fs_id;
  64                        break;
  65                case ORANGEFS_VFS_OP_LISTXATTR:
  66                        fsid = op->upcall.req.listxattr.refn.fs_id;
  67                        break;
  68                case ORANGEFS_VFS_OP_REMOVEXATTR:
  69                        fsid = op->upcall.req.removexattr.refn.fs_id;
  70                        break;
  71                case ORANGEFS_VFS_OP_FSYNC:
  72                        fsid = op->upcall.req.fsync.refn.fs_id;
  73                        break;
  74                default:
  75                        break;
  76                }
  77        }
  78        return fsid;
  79}
  80
  81static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
  82{
  83        int flags = 0;
  84        if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
  85                flags |= S_IMMUTABLE;
  86        else
  87                flags &= ~S_IMMUTABLE;
  88        if (attrs->flags & ORANGEFS_APPEND_FL)
  89                flags |= S_APPEND;
  90        else
  91                flags &= ~S_APPEND;
  92        if (attrs->flags & ORANGEFS_NOATIME_FL)
  93                flags |= S_NOATIME;
  94        else
  95                flags &= ~S_NOATIME;
  96        return flags;
  97}
  98
  99static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
 100{
 101        int perm_mode = 0;
 102
 103        if (attrs->perms & ORANGEFS_O_EXECUTE)
 104                perm_mode |= S_IXOTH;
 105        if (attrs->perms & ORANGEFS_O_WRITE)
 106                perm_mode |= S_IWOTH;
 107        if (attrs->perms & ORANGEFS_O_READ)
 108                perm_mode |= S_IROTH;
 109
 110        if (attrs->perms & ORANGEFS_G_EXECUTE)
 111                perm_mode |= S_IXGRP;
 112        if (attrs->perms & ORANGEFS_G_WRITE)
 113                perm_mode |= S_IWGRP;
 114        if (attrs->perms & ORANGEFS_G_READ)
 115                perm_mode |= S_IRGRP;
 116
 117        if (attrs->perms & ORANGEFS_U_EXECUTE)
 118                perm_mode |= S_IXUSR;
 119        if (attrs->perms & ORANGEFS_U_WRITE)
 120                perm_mode |= S_IWUSR;
 121        if (attrs->perms & ORANGEFS_U_READ)
 122                perm_mode |= S_IRUSR;
 123
 124        if (attrs->perms & ORANGEFS_G_SGID)
 125                perm_mode |= S_ISGID;
 126        if (attrs->perms & ORANGEFS_U_SUID)
 127                perm_mode |= S_ISUID;
 128
 129        return perm_mode;
 130}
 131
 132/*
 133 * NOTE: in kernel land, we never use the sys_attr->link_target for
 134 * anything, so don't bother copying it into the sys_attr object here.
 135 */
 136static inline int copy_attributes_from_inode(struct inode *inode,
 137                                             struct ORANGEFS_sys_attr_s *attrs,
 138                                             struct iattr *iattr)
 139{
 140        umode_t tmp_mode;
 141
 142        if (!iattr || !inode || !attrs) {
 143                gossip_err("NULL iattr (%p), inode (%p), attrs (%p) "
 144                           "in copy_attributes_from_inode!\n",
 145                           iattr,
 146                           inode,
 147                           attrs);
 148                return -EINVAL;
 149        }
 150        /*
 151         * We need to be careful to only copy the attributes out of the
 152         * iattr object that we know are valid.
 153         */
 154        attrs->mask = 0;
 155        if (iattr->ia_valid & ATTR_UID) {
 156                attrs->owner = from_kuid(current_user_ns(), iattr->ia_uid);
 157                attrs->mask |= ORANGEFS_ATTR_SYS_UID;
 158                gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
 159        }
 160        if (iattr->ia_valid & ATTR_GID) {
 161                attrs->group = from_kgid(current_user_ns(), iattr->ia_gid);
 162                attrs->mask |= ORANGEFS_ATTR_SYS_GID;
 163                gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
 164        }
 165
 166        if (iattr->ia_valid & ATTR_ATIME) {
 167                attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
 168                if (iattr->ia_valid & ATTR_ATIME_SET) {
 169                        attrs->atime = (time64_t)iattr->ia_atime.tv_sec;
 170                        attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
 171                }
 172        }
 173        if (iattr->ia_valid & ATTR_MTIME) {
 174                attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
 175                if (iattr->ia_valid & ATTR_MTIME_SET) {
 176                        attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec;
 177                        attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
 178                }
 179        }
 180        if (iattr->ia_valid & ATTR_CTIME)
 181                attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
 182
 183        /*
 184         * ORANGEFS cannot set size with a setattr operation.  Probably not likely
 185         * to be requested through the VFS, but just in case, don't worry about
 186         * ATTR_SIZE
 187         */
 188
 189        if (iattr->ia_valid & ATTR_MODE) {
 190                tmp_mode = iattr->ia_mode;
 191                if (tmp_mode & (S_ISVTX)) {
 192                        if (is_root_handle(inode)) {
 193                                /*
 194                                 * allow sticky bit to be set on root (since
 195                                 * it shows up that way by default anyhow),
 196                                 * but don't show it to the server
 197                                 */
 198                                tmp_mode -= S_ISVTX;
 199                        } else {
 200                                gossip_debug(GOSSIP_UTILS_DEBUG,
 201                                             "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
 202                                return -EINVAL;
 203                        }
 204                }
 205
 206                if (tmp_mode & (S_ISUID)) {
 207                        gossip_debug(GOSSIP_UTILS_DEBUG,
 208                                     "Attempting to set setuid bit (not supported); returning EINVAL.\n");
 209                        return -EINVAL;
 210                }
 211
 212                attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
 213                attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
 214        }
 215
 216        return 0;
 217}
 218
 219static int orangefs_inode_type(enum orangefs_ds_type objtype)
 220{
 221        if (objtype == ORANGEFS_TYPE_METAFILE)
 222                return S_IFREG;
 223        else if (objtype == ORANGEFS_TYPE_DIRECTORY)
 224                return S_IFDIR;
 225        else if (objtype == ORANGEFS_TYPE_SYMLINK)
 226                return S_IFLNK;
 227        else
 228                return -1;
 229}
 230
 231static int orangefs_inode_is_stale(struct inode *inode, int new,
 232    struct ORANGEFS_sys_attr_s *attrs, char *link_target)
 233{
 234        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 235        int type = orangefs_inode_type(attrs->objtype);
 236        if (!new) {
 237                /*
 238                 * If the inode type or symlink target have changed then this
 239                 * inode is stale.
 240                 */
 241                if (type == -1 || !(inode->i_mode & type)) {
 242                        orangefs_make_bad_inode(inode);
 243                        return 1;
 244                }
 245                if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
 246                    link_target, ORANGEFS_NAME_MAX)) {
 247                        orangefs_make_bad_inode(inode);
 248                        return 1;
 249                }
 250        }
 251        return 0;
 252}
 253
 254int orangefs_inode_getattr(struct inode *inode, int new, int size)
 255{
 256        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 257        struct orangefs_kernel_op_s *new_op;
 258        loff_t inode_size, rounded_up_size;
 259        int ret, type;
 260
 261        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
 262            get_khandle_from_ino(inode));
 263
 264        new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
 265        if (!new_op)
 266                return -ENOMEM;
 267        new_op->upcall.req.getattr.refn = orangefs_inode->refn;
 268        new_op->upcall.req.getattr.mask = size ?
 269            ORANGEFS_ATTR_SYS_ALL_NOHINT : ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE;
 270
 271        ret = service_operation(new_op, __func__,
 272            get_interruptible_flag(inode));
 273        if (ret != 0)
 274                goto out;
 275
 276        type = orangefs_inode_type(new_op->
 277            downcall.resp.getattr.attributes.objtype);
 278        ret = orangefs_inode_is_stale(inode, new,
 279            &new_op->downcall.resp.getattr.attributes,
 280            new_op->downcall.resp.getattr.link_target);
 281        if (ret) {
 282                ret = -ESTALE;
 283                goto out;
 284        }
 285
 286        switch (type) {
 287        case S_IFREG:
 288                inode->i_flags = orangefs_inode_flags(&new_op->
 289                    downcall.resp.getattr.attributes);
 290                if (size) {
 291                        inode_size = (loff_t)new_op->
 292                            downcall.resp.getattr.attributes.size;
 293                        rounded_up_size =
 294                            (inode_size + (4096 - (inode_size % 4096)));
 295                        inode->i_size = inode_size;
 296                        orangefs_inode->blksize =
 297                            new_op->downcall.resp.getattr.attributes.blksize;
 298                        spin_lock(&inode->i_lock);
 299                        inode->i_bytes = inode_size;
 300                        inode->i_blocks =
 301                            (unsigned long)(rounded_up_size / 512);
 302                        spin_unlock(&inode->i_lock);
 303                }
 304                break;
 305        case S_IFDIR:
 306                inode->i_size = PAGE_SIZE;
 307                orangefs_inode->blksize = (1 << inode->i_blkbits);
 308                spin_lock(&inode->i_lock);
 309                inode_set_bytes(inode, inode->i_size);
 310                spin_unlock(&inode->i_lock);
 311                set_nlink(inode, 1);
 312                break;
 313        case S_IFLNK:
 314                if (new) {
 315                        inode->i_size = (loff_t)strlen(new_op->
 316                            downcall.resp.getattr.link_target);
 317                        orangefs_inode->blksize = (1 << inode->i_blkbits);
 318                        ret = strscpy(orangefs_inode->link_target,
 319                            new_op->downcall.resp.getattr.link_target,
 320                            ORANGEFS_NAME_MAX);
 321                        if (ret == -E2BIG) {
 322                                ret = -EIO;
 323                                goto out;
 324                        }
 325                        inode->i_link = orangefs_inode->link_target;
 326                }
 327                break;
 328        }
 329
 330        inode->i_uid = make_kuid(&init_user_ns, new_op->
 331            downcall.resp.getattr.attributes.owner);
 332        inode->i_gid = make_kgid(&init_user_ns, new_op->
 333            downcall.resp.getattr.attributes.group);
 334        inode->i_atime.tv_sec = (time64_t)new_op->
 335            downcall.resp.getattr.attributes.atime;
 336        inode->i_mtime.tv_sec = (time64_t)new_op->
 337            downcall.resp.getattr.attributes.mtime;
 338        inode->i_ctime.tv_sec = (time64_t)new_op->
 339            downcall.resp.getattr.attributes.ctime;
 340        inode->i_atime.tv_nsec = 0;
 341        inode->i_mtime.tv_nsec = 0;
 342        inode->i_ctime.tv_nsec = 0;
 343
 344        /* special case: mark the root inode as sticky */
 345        inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
 346            orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
 347
 348        ret = 0;
 349out:
 350        op_release(new_op);
 351        return ret;
 352}
 353
 354int orangefs_inode_check_changed(struct inode *inode)
 355{
 356        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 357        struct orangefs_kernel_op_s *new_op;
 358        int ret;
 359
 360        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
 361            get_khandle_from_ino(inode));
 362
 363        new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
 364        if (!new_op)
 365                return -ENOMEM;
 366        new_op->upcall.req.getattr.refn = orangefs_inode->refn;
 367        new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
 368            ORANGEFS_ATTR_SYS_LNK_TARGET;
 369
 370        ret = service_operation(new_op, __func__,
 371            get_interruptible_flag(inode));
 372        if (ret != 0)
 373                goto out;
 374
 375        ret = orangefs_inode_is_stale(inode, 0,
 376            &new_op->downcall.resp.getattr.attributes,
 377            new_op->downcall.resp.getattr.link_target);
 378out:
 379        op_release(new_op);
 380        return ret;
 381}
 382
 383/*
 384 * issues a orangefs setattr request to make sure the new attribute values
 385 * take effect if successful.  returns 0 on success; -errno otherwise
 386 */
 387int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
 388{
 389        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 390        struct orangefs_kernel_op_s *new_op;
 391        int ret;
 392
 393        new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
 394        if (!new_op)
 395                return -ENOMEM;
 396
 397        new_op->upcall.req.setattr.refn = orangefs_inode->refn;
 398        ret = copy_attributes_from_inode(inode,
 399                       &new_op->upcall.req.setattr.attributes,
 400                       iattr);
 401        if (ret >= 0) {
 402                ret = service_operation(new_op, __func__,
 403                                get_interruptible_flag(inode));
 404
 405                gossip_debug(GOSSIP_UTILS_DEBUG,
 406                             "orangefs_inode_setattr: returning %d\n",
 407                             ret);
 408        }
 409
 410        op_release(new_op);
 411
 412        /*
 413         * successful setattr should clear the atime, mtime and
 414         * ctime flags.
 415         */
 416        if (ret == 0) {
 417                ClearAtimeFlag(orangefs_inode);
 418                ClearMtimeFlag(orangefs_inode);
 419                ClearCtimeFlag(orangefs_inode);
 420                ClearModeFlag(orangefs_inode);
 421        }
 422
 423        return ret;
 424}
 425
 426int orangefs_flush_inode(struct inode *inode)
 427{
 428        /*
 429         * If it is a dirty inode, this function gets called.
 430         * Gather all the information that needs to be setattr'ed
 431         * Right now, this will only be used for mode, atime, mtime
 432         * and/or ctime.
 433         */
 434        struct iattr wbattr;
 435        int ret;
 436        int mtime_flag;
 437        int ctime_flag;
 438        int atime_flag;
 439        int mode_flag;
 440        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 441
 442        memset(&wbattr, 0, sizeof(wbattr));
 443
 444        /*
 445         * check inode flags up front, and clear them if they are set.  This
 446         * will prevent multiple processes from all trying to flush the same
 447         * inode if they call close() simultaneously
 448         */
 449        mtime_flag = MtimeFlag(orangefs_inode);
 450        ClearMtimeFlag(orangefs_inode);
 451        ctime_flag = CtimeFlag(orangefs_inode);
 452        ClearCtimeFlag(orangefs_inode);
 453        atime_flag = AtimeFlag(orangefs_inode);
 454        ClearAtimeFlag(orangefs_inode);
 455        mode_flag = ModeFlag(orangefs_inode);
 456        ClearModeFlag(orangefs_inode);
 457
 458        /*  -- Lazy atime,mtime and ctime update --
 459         * Note: all times are dictated by server in the new scheme
 460         * and not by the clients
 461         *
 462         * Also mode updates are being handled now..
 463         */
 464
 465        if (mtime_flag)
 466                wbattr.ia_valid |= ATTR_MTIME;
 467        if (ctime_flag)
 468                wbattr.ia_valid |= ATTR_CTIME;
 469        if (atime_flag)
 470                wbattr.ia_valid |= ATTR_ATIME;
 471
 472        if (mode_flag) {
 473                wbattr.ia_mode = inode->i_mode;
 474                wbattr.ia_valid |= ATTR_MODE;
 475        }
 476
 477        gossip_debug(GOSSIP_UTILS_DEBUG,
 478                     "*********** orangefs_flush_inode: %pU "
 479                     "(ia_valid %d)\n",
 480                     get_khandle_from_ino(inode),
 481                     wbattr.ia_valid);
 482        if (wbattr.ia_valid == 0) {
 483                gossip_debug(GOSSIP_UTILS_DEBUG,
 484                             "orangefs_flush_inode skipping setattr()\n");
 485                return 0;
 486        }
 487
 488        gossip_debug(GOSSIP_UTILS_DEBUG,
 489                     "orangefs_flush_inode (%pU) writing mode %o\n",
 490                     get_khandle_from_ino(inode),
 491                     inode->i_mode);
 492
 493        ret = orangefs_inode_setattr(inode, &wbattr);
 494
 495        return ret;
 496}
 497
 498int orangefs_unmount_sb(struct super_block *sb)
 499{
 500        int ret = -EINVAL;
 501        struct orangefs_kernel_op_s *new_op = NULL;
 502
 503        gossip_debug(GOSSIP_UTILS_DEBUG,
 504                     "orangefs_unmount_sb called on sb %p\n",
 505                     sb);
 506
 507        new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
 508        if (!new_op)
 509                return -ENOMEM;
 510        new_op->upcall.req.fs_umount.id = ORANGEFS_SB(sb)->id;
 511        new_op->upcall.req.fs_umount.fs_id = ORANGEFS_SB(sb)->fs_id;
 512        strncpy(new_op->upcall.req.fs_umount.orangefs_config_server,
 513                ORANGEFS_SB(sb)->devname,
 514                ORANGEFS_MAX_SERVER_ADDR_LEN);
 515
 516        gossip_debug(GOSSIP_UTILS_DEBUG,
 517                     "Attempting ORANGEFS Unmount via host %s\n",
 518                     new_op->upcall.req.fs_umount.orangefs_config_server);
 519
 520        ret = service_operation(new_op, "orangefs_fs_umount", 0);
 521
 522        gossip_debug(GOSSIP_UTILS_DEBUG,
 523                     "orangefs_unmount: got return value of %d\n", ret);
 524        if (ret)
 525                sb = ERR_PTR(ret);
 526        else
 527                ORANGEFS_SB(sb)->mount_pending = 1;
 528
 529        op_release(new_op);
 530        return ret;
 531}
 532
 533void orangefs_make_bad_inode(struct inode *inode)
 534{
 535        if (is_root_handle(inode)) {
 536                /*
 537                 * if this occurs, the pvfs2-client-core was killed but we
 538                 * can't afford to lose the inode operations and such
 539                 * associated with the root handle in any case.
 540                 */
 541                gossip_debug(GOSSIP_UTILS_DEBUG,
 542                             "*** NOT making bad root inode %pU\n",
 543                             get_khandle_from_ino(inode));
 544        } else {
 545                gossip_debug(GOSSIP_UTILS_DEBUG,
 546                             "*** making bad inode %pU\n",
 547                             get_khandle_from_ino(inode));
 548                make_bad_inode(inode);
 549        }
 550}
 551
 552/*
 553 * The following is a very dirty hack that is now a permanent part of the
 554 * ORANGEFS protocol. See protocol.h for more error definitions.
 555 */
 556
 557/* The order matches include/orangefs-types.h in the OrangeFS source. */
 558static int PINT_errno_mapping[] = {
 559        0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
 560        EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
 561        EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
 562        ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
 563        EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
 564        EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
 565        ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
 566        EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
 567        ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
 568        EACCES, ECONNRESET, ERANGE
 569};
 570
 571int orangefs_normalize_to_errno(__s32 error_code)
 572{
 573        __u32 i;
 574
 575        /* Success */
 576        if (error_code == 0) {
 577                return 0;
 578        /*
 579         * This shouldn't ever happen. If it does it should be fixed on the
 580         * server.
 581         */
 582        } else if (error_code > 0) {
 583                gossip_err("orangefs: error status receieved.\n");
 584                gossip_err("orangefs: assuming error code is inverted.\n");
 585                error_code = -error_code;
 586        }
 587
 588        /*
 589         * XXX: This is very bad since error codes from ORANGEFS may not be
 590         * suitable for return into userspace.
 591         */
 592
 593        /*
 594         * Convert ORANGEFS error values into errno values suitable for return
 595         * from the kernel.
 596         */
 597        if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
 598                if (((-error_code) &
 599                    (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
 600                    ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
 601                        /*
 602                         * cancellation error codes generally correspond to
 603                         * a timeout from the client's perspective
 604                         */
 605                        error_code = -ETIMEDOUT;
 606                } else {
 607                        /* assume a default error code */
 608                        gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
 609                        error_code = -EINVAL;
 610                }
 611
 612        /* Convert ORANGEFS encoded errno values into regular errno values. */
 613        } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
 614                i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
 615                if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
 616                        error_code = -PINT_errno_mapping[i];
 617                else
 618                        error_code = -EINVAL;
 619
 620        /*
 621         * Only ORANGEFS protocol error codes should ever come here. Otherwise
 622         * there is a bug somewhere.
 623         */
 624        } else {
 625                gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
 626        }
 627        return error_code;
 628}
 629
 630#define NUM_MODES 11
 631__s32 ORANGEFS_util_translate_mode(int mode)
 632{
 633        int ret = 0;
 634        int i = 0;
 635        static int modes[NUM_MODES] = {
 636                S_IXOTH, S_IWOTH, S_IROTH,
 637                S_IXGRP, S_IWGRP, S_IRGRP,
 638                S_IXUSR, S_IWUSR, S_IRUSR,
 639                S_ISGID, S_ISUID
 640        };
 641        static int orangefs_modes[NUM_MODES] = {
 642                ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
 643                ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
 644                ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
 645                ORANGEFS_G_SGID, ORANGEFS_U_SUID
 646        };
 647
 648        for (i = 0; i < NUM_MODES; i++)
 649                if (mode & modes[i])
 650                        ret |= orangefs_modes[i];
 651
 652        return ret;
 653}
 654#undef NUM_MODES
 655
 656/*
 657 * After obtaining a string representation of the client's debug
 658 * keywords and their associated masks, this function is called to build an
 659 * array of these values.
 660 */
 661int orangefs_prepare_cdm_array(char *debug_array_string)
 662{
 663        int i;
 664        int rc = -EINVAL;
 665        char *cds_head = NULL;
 666        char *cds_delimiter = NULL;
 667        int keyword_len = 0;
 668
 669        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
 670
 671        /*
 672         * figure out how many elements the cdm_array needs.
 673         */
 674        for (i = 0; i < strlen(debug_array_string); i++)
 675                if (debug_array_string[i] == '\n')
 676                        cdm_element_count++;
 677
 678        if (!cdm_element_count) {
 679                pr_info("No elements in client debug array string!\n");
 680                goto out;
 681        }
 682
 683        cdm_array =
 684                kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
 685                        GFP_KERNEL);
 686        if (!cdm_array) {
 687                pr_info("malloc failed for cdm_array!\n");
 688                rc = -ENOMEM;
 689                goto out;
 690        }
 691
 692        cds_head = debug_array_string;
 693
 694        for (i = 0; i < cdm_element_count; i++) {
 695                cds_delimiter = strchr(cds_head, '\n');
 696                *cds_delimiter = '\0';
 697
 698                keyword_len = strcspn(cds_head, " ");
 699
 700                cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
 701                if (!cdm_array[i].keyword) {
 702                        rc = -ENOMEM;
 703                        goto out;
 704                }
 705
 706                sscanf(cds_head,
 707                       "%s %llx %llx",
 708                       cdm_array[i].keyword,
 709                       (unsigned long long *)&(cdm_array[i].mask1),
 710                       (unsigned long long *)&(cdm_array[i].mask2));
 711
 712                if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
 713                        client_verbose_index = i;
 714
 715                if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
 716                        client_all_index = i;
 717
 718                cds_head = cds_delimiter + 1;
 719        }
 720
 721        rc = cdm_element_count;
 722
 723        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
 724
 725out:
 726
 727        return rc;
 728
 729}
 730
 731/*
 732 * /sys/kernel/debug/orangefs/debug-help can be catted to
 733 * see all the available kernel and client debug keywords.
 734 *
 735 * When the kernel boots, we have no idea what keywords the
 736 * client supports, nor their associated masks.
 737 *
 738 * We pass through this function once at boot and stamp a
 739 * boilerplate "we don't know" message for the client in the
 740 * debug-help file. We pass through here again when the client
 741 * starts and then we can fill out the debug-help file fully.
 742 *
 743 * The client might be restarted any number of times between
 744 * reboots, we only build the debug-help file the first time.
 745 */
 746int orangefs_prepare_debugfs_help_string(int at_boot)
 747{
 748        int rc = -EINVAL;
 749        int i;
 750        int byte_count = 0;
 751        char *client_title = "Client Debug Keywords:\n";
 752        char *kernel_title = "Kernel Debug Keywords:\n";
 753
 754        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
 755
 756        if (at_boot) {
 757                byte_count += strlen(HELP_STRING_UNINITIALIZED);
 758                client_title = HELP_STRING_UNINITIALIZED;
 759        } else {
 760                /*
 761                 * fill the client keyword/mask array and remember
 762                 * how many elements there were.
 763                 */
 764                cdm_element_count =
 765                        orangefs_prepare_cdm_array(client_debug_array_string);
 766                if (cdm_element_count <= 0)
 767                        goto out;
 768
 769                /* Count the bytes destined for debug_help_string. */
 770                byte_count += strlen(client_title);
 771
 772                for (i = 0; i < cdm_element_count; i++) {
 773                        byte_count += strlen(cdm_array[i].keyword + 2);
 774                        if (byte_count >= DEBUG_HELP_STRING_SIZE) {
 775                                pr_info("%s: overflow 1!\n", __func__);
 776                                goto out;
 777                        }
 778                }
 779
 780                gossip_debug(GOSSIP_UTILS_DEBUG,
 781                             "%s: cdm_element_count:%d:\n",
 782                             __func__,
 783                             cdm_element_count);
 784        }
 785
 786        byte_count += strlen(kernel_title);
 787        for (i = 0; i < num_kmod_keyword_mask_map; i++) {
 788                byte_count +=
 789                        strlen(s_kmod_keyword_mask_map[i].keyword + 2);
 790                if (byte_count >= DEBUG_HELP_STRING_SIZE) {
 791                        pr_info("%s: overflow 2!\n", __func__);
 792                        goto out;
 793                }
 794        }
 795
 796        /* build debug_help_string. */
 797        debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
 798        if (!debug_help_string) {
 799                rc = -ENOMEM;
 800                goto out;
 801        }
 802
 803        strcat(debug_help_string, client_title);
 804
 805        if (!at_boot) {
 806                for (i = 0; i < cdm_element_count; i++) {
 807                        strcat(debug_help_string, "\t");
 808                        strcat(debug_help_string, cdm_array[i].keyword);
 809                        strcat(debug_help_string, "\n");
 810                }
 811        }
 812
 813        strcat(debug_help_string, "\n");
 814        strcat(debug_help_string, kernel_title);
 815
 816        for (i = 0; i < num_kmod_keyword_mask_map; i++) {
 817                strcat(debug_help_string, "\t");
 818                strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
 819                strcat(debug_help_string, "\n");
 820        }
 821
 822        rc = 0;
 823
 824out:
 825
 826        return rc;
 827
 828}
 829
 830/*
 831 * kernel = type 0
 832 * client = type 1
 833 */
 834void debug_mask_to_string(void *mask, int type)
 835{
 836        int i;
 837        int len = 0;
 838        char *debug_string;
 839        int element_count = 0;
 840
 841        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
 842
 843        if (type) {
 844                debug_string = client_debug_string;
 845                element_count = cdm_element_count;
 846        } else {
 847                debug_string = kernel_debug_string;
 848                element_count = num_kmod_keyword_mask_map;
 849        }
 850
 851        memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
 852
 853        /*
 854         * Some keywords, like "all" or "verbose", are amalgams of
 855         * numerous other keywords. Make a special check for those
 856         * before grinding through the whole mask only to find out
 857         * later...
 858         */
 859        if (check_amalgam_keyword(mask, type))
 860                goto out;
 861
 862        /* Build the debug string. */
 863        for (i = 0; i < element_count; i++)
 864                if (type)
 865                        do_c_string(mask, i);
 866                else
 867                        do_k_string(mask, i);
 868
 869        len = strlen(debug_string);
 870
 871        if ((len) && (type))
 872                client_debug_string[len - 1] = '\0';
 873        else if (len)
 874                kernel_debug_string[len - 1] = '\0';
 875        else if (type)
 876                strcpy(client_debug_string, "none");
 877        else
 878                strcpy(kernel_debug_string, "none");
 879
 880out:
 881gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
 882
 883        return;
 884
 885}
 886
 887void do_k_string(void *k_mask, int index)
 888{
 889        __u64 *mask = (__u64 *) k_mask;
 890
 891        if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
 892                goto out;
 893
 894        if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
 895                if ((strlen(kernel_debug_string) +
 896                     strlen(s_kmod_keyword_mask_map[index].keyword))
 897                        < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
 898                                strcat(kernel_debug_string,
 899                                       s_kmod_keyword_mask_map[index].keyword);
 900                                strcat(kernel_debug_string, ",");
 901                        } else {
 902                                gossip_err("%s: overflow!\n", __func__);
 903                                strcpy(kernel_debug_string, ORANGEFS_ALL);
 904                                goto out;
 905                        }
 906        }
 907
 908out:
 909
 910        return;
 911}
 912
 913void do_c_string(void *c_mask, int index)
 914{
 915        struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
 916
 917        if (keyword_is_amalgam(cdm_array[index].keyword))
 918                goto out;
 919
 920        if ((mask->mask1 & cdm_array[index].mask1) ||
 921            (mask->mask2 & cdm_array[index].mask2)) {
 922                if ((strlen(client_debug_string) +
 923                     strlen(cdm_array[index].keyword) + 1)
 924                        < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
 925                                strcat(client_debug_string,
 926                                       cdm_array[index].keyword);
 927                                strcat(client_debug_string, ",");
 928                        } else {
 929                                gossip_err("%s: overflow!\n", __func__);
 930                                strcpy(client_debug_string, ORANGEFS_ALL);
 931                                goto out;
 932                        }
 933        }
 934out:
 935        return;
 936}
 937
 938int keyword_is_amalgam(char *keyword)
 939{
 940        int rc = 0;
 941
 942        if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
 943                rc = 1;
 944
 945        return rc;
 946}
 947
 948/*
 949 * kernel = type 0
 950 * client = type 1
 951 *
 952 * return 1 if we found an amalgam.
 953 */
 954int check_amalgam_keyword(void *mask, int type)
 955{
 956        __u64 *k_mask;
 957        struct client_debug_mask *c_mask;
 958        int k_all_index = num_kmod_keyword_mask_map - 1;
 959        int rc = 0;
 960
 961        if (type) {
 962                c_mask = (struct client_debug_mask *) mask;
 963
 964                if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
 965                    (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
 966                        strcpy(client_debug_string, ORANGEFS_ALL);
 967                        rc = 1;
 968                        goto out;
 969                }
 970
 971                if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
 972                    (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
 973                        strcpy(client_debug_string, ORANGEFS_VERBOSE);
 974                        rc = 1;
 975                        goto out;
 976                }
 977
 978        } else {
 979                k_mask = (__u64 *) mask;
 980
 981                if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
 982                        strcpy(kernel_debug_string, ORANGEFS_ALL);
 983                        rc = 1;
 984                        goto out;
 985                }
 986        }
 987
 988out:
 989
 990        return rc;
 991}
 992
 993/*
 994 * kernel = type 0
 995 * client = type 1
 996 */
 997void debug_string_to_mask(char *debug_string, void *mask, int type)
 998{
 999        char *unchecked_keyword;
1000        int i;
1001        char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
1002        char *original_pointer;
1003        int element_count = 0;
1004        struct client_debug_mask *c_mask;
1005        __u64 *k_mask;
1006
1007        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1008
1009        if (type) {
1010                c_mask = (struct client_debug_mask *)mask;
1011                element_count = cdm_element_count;
1012        } else {
1013                k_mask = (__u64 *)mask;
1014                *k_mask = 0;
1015                element_count = num_kmod_keyword_mask_map;
1016        }
1017
1018        original_pointer = strsep_fodder;
1019        while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
1020                if (strlen(unchecked_keyword)) {
1021                        for (i = 0; i < element_count; i++)
1022                                if (type)
1023                                        do_c_mask(i,
1024                                                  unchecked_keyword,
1025                                                  &c_mask);
1026                                else
1027                                        do_k_mask(i,
1028                                                  unchecked_keyword,
1029                                                  &k_mask);
1030                }
1031
1032        kfree(original_pointer);
1033}
1034
1035void do_c_mask(int i,
1036               char *unchecked_keyword,
1037               struct client_debug_mask **sane_mask)
1038{
1039
1040        if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
1041                (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
1042                (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
1043        }
1044}
1045
1046void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
1047{
1048
1049        if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
1050                **sane_mask = (**sane_mask) |
1051                                s_kmod_keyword_mask_map[i].mask_val;
1052}
1053