linux/fs/orangefs/orangefs-utils.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * (C) 2001 Clemson University and The University of Chicago
   4 * Copyright 2018 Omnibond Systems, L.L.C.
   5 *
   6 * See COPYING in top-level directory.
   7 */
   8#include <linux/kernel.h>
   9#include "protocol.h"
  10#include "orangefs-kernel.h"
  11#include "orangefs-dev-proto.h"
  12#include "orangefs-bufmap.h"
  13
  14__s32 fsid_of_op(struct orangefs_kernel_op_s *op)
  15{
  16        __s32 fsid = ORANGEFS_FS_ID_NULL;
  17
  18        if (op) {
  19                switch (op->upcall.type) {
  20                case ORANGEFS_VFS_OP_FILE_IO:
  21                        fsid = op->upcall.req.io.refn.fs_id;
  22                        break;
  23                case ORANGEFS_VFS_OP_LOOKUP:
  24                        fsid = op->upcall.req.lookup.parent_refn.fs_id;
  25                        break;
  26                case ORANGEFS_VFS_OP_CREATE:
  27                        fsid = op->upcall.req.create.parent_refn.fs_id;
  28                        break;
  29                case ORANGEFS_VFS_OP_GETATTR:
  30                        fsid = op->upcall.req.getattr.refn.fs_id;
  31                        break;
  32                case ORANGEFS_VFS_OP_REMOVE:
  33                        fsid = op->upcall.req.remove.parent_refn.fs_id;
  34                        break;
  35                case ORANGEFS_VFS_OP_MKDIR:
  36                        fsid = op->upcall.req.mkdir.parent_refn.fs_id;
  37                        break;
  38                case ORANGEFS_VFS_OP_READDIR:
  39                        fsid = op->upcall.req.readdir.refn.fs_id;
  40                        break;
  41                case ORANGEFS_VFS_OP_SETATTR:
  42                        fsid = op->upcall.req.setattr.refn.fs_id;
  43                        break;
  44                case ORANGEFS_VFS_OP_SYMLINK:
  45                        fsid = op->upcall.req.sym.parent_refn.fs_id;
  46                        break;
  47                case ORANGEFS_VFS_OP_RENAME:
  48                        fsid = op->upcall.req.rename.old_parent_refn.fs_id;
  49                        break;
  50                case ORANGEFS_VFS_OP_STATFS:
  51                        fsid = op->upcall.req.statfs.fs_id;
  52                        break;
  53                case ORANGEFS_VFS_OP_TRUNCATE:
  54                        fsid = op->upcall.req.truncate.refn.fs_id;
  55                        break;
  56                case ORANGEFS_VFS_OP_RA_FLUSH:
  57                        fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
  58                        break;
  59                case ORANGEFS_VFS_OP_FS_UMOUNT:
  60                        fsid = op->upcall.req.fs_umount.fs_id;
  61                        break;
  62                case ORANGEFS_VFS_OP_GETXATTR:
  63                        fsid = op->upcall.req.getxattr.refn.fs_id;
  64                        break;
  65                case ORANGEFS_VFS_OP_SETXATTR:
  66                        fsid = op->upcall.req.setxattr.refn.fs_id;
  67                        break;
  68                case ORANGEFS_VFS_OP_LISTXATTR:
  69                        fsid = op->upcall.req.listxattr.refn.fs_id;
  70                        break;
  71                case ORANGEFS_VFS_OP_REMOVEXATTR:
  72                        fsid = op->upcall.req.removexattr.refn.fs_id;
  73                        break;
  74                case ORANGEFS_VFS_OP_FSYNC:
  75                        fsid = op->upcall.req.fsync.refn.fs_id;
  76                        break;
  77                default:
  78                        break;
  79                }
  80        }
  81        return fsid;
  82}
  83
  84static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
  85{
  86        int flags = 0;
  87        if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
  88                flags |= S_IMMUTABLE;
  89        else
  90                flags &= ~S_IMMUTABLE;
  91        if (attrs->flags & ORANGEFS_APPEND_FL)
  92                flags |= S_APPEND;
  93        else
  94                flags &= ~S_APPEND;
  95        if (attrs->flags & ORANGEFS_NOATIME_FL)
  96                flags |= S_NOATIME;
  97        else
  98                flags &= ~S_NOATIME;
  99        return flags;
 100}
 101
 102static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
 103{
 104        int perm_mode = 0;
 105
 106        if (attrs->perms & ORANGEFS_O_EXECUTE)
 107                perm_mode |= S_IXOTH;
 108        if (attrs->perms & ORANGEFS_O_WRITE)
 109                perm_mode |= S_IWOTH;
 110        if (attrs->perms & ORANGEFS_O_READ)
 111                perm_mode |= S_IROTH;
 112
 113        if (attrs->perms & ORANGEFS_G_EXECUTE)
 114                perm_mode |= S_IXGRP;
 115        if (attrs->perms & ORANGEFS_G_WRITE)
 116                perm_mode |= S_IWGRP;
 117        if (attrs->perms & ORANGEFS_G_READ)
 118                perm_mode |= S_IRGRP;
 119
 120        if (attrs->perms & ORANGEFS_U_EXECUTE)
 121                perm_mode |= S_IXUSR;
 122        if (attrs->perms & ORANGEFS_U_WRITE)
 123                perm_mode |= S_IWUSR;
 124        if (attrs->perms & ORANGEFS_U_READ)
 125                perm_mode |= S_IRUSR;
 126
 127        if (attrs->perms & ORANGEFS_G_SGID)
 128                perm_mode |= S_ISGID;
 129        if (attrs->perms & ORANGEFS_U_SUID)
 130                perm_mode |= S_ISUID;
 131
 132        return perm_mode;
 133}
 134
 135/*
 136 * NOTE: in kernel land, we never use the sys_attr->link_target for
 137 * anything, so don't bother copying it into the sys_attr object here.
 138 */
 139static inline void copy_attributes_from_inode(struct inode *inode,
 140    struct ORANGEFS_sys_attr_s *attrs)
 141{
 142        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 143        attrs->mask = 0;
 144        if (orangefs_inode->attr_valid & ATTR_UID) {
 145                attrs->owner = from_kuid(&init_user_ns, inode->i_uid);
 146                attrs->mask |= ORANGEFS_ATTR_SYS_UID;
 147                gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
 148        }
 149        if (orangefs_inode->attr_valid & ATTR_GID) {
 150                attrs->group = from_kgid(&init_user_ns, inode->i_gid);
 151                attrs->mask |= ORANGEFS_ATTR_SYS_GID;
 152                gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
 153        }
 154
 155        if (orangefs_inode->attr_valid & ATTR_ATIME) {
 156                attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
 157                if (orangefs_inode->attr_valid & ATTR_ATIME_SET) {
 158                        attrs->atime = (time64_t)inode->i_atime.tv_sec;
 159                        attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
 160                }
 161        }
 162        if (orangefs_inode->attr_valid & ATTR_MTIME) {
 163                attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
 164                if (orangefs_inode->attr_valid & ATTR_MTIME_SET) {
 165                        attrs->mtime = (time64_t)inode->i_mtime.tv_sec;
 166                        attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
 167                }
 168        }
 169        if (orangefs_inode->attr_valid & ATTR_CTIME)
 170                attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
 171
 172        /*
 173         * ORANGEFS cannot set size with a setattr operation. Probably not
 174         * likely to be requested through the VFS, but just in case, don't
 175         * worry about ATTR_SIZE
 176         */
 177
 178        if (orangefs_inode->attr_valid & ATTR_MODE) {
 179                attrs->perms = ORANGEFS_util_translate_mode(inode->i_mode);
 180                attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
 181        }
 182}
 183
 184static int orangefs_inode_type(enum orangefs_ds_type objtype)
 185{
 186        if (objtype == ORANGEFS_TYPE_METAFILE)
 187                return S_IFREG;
 188        else if (objtype == ORANGEFS_TYPE_DIRECTORY)
 189                return S_IFDIR;
 190        else if (objtype == ORANGEFS_TYPE_SYMLINK)
 191                return S_IFLNK;
 192        else
 193                return -1;
 194}
 195
 196static void orangefs_make_bad_inode(struct inode *inode)
 197{
 198        if (is_root_handle(inode)) {
 199                /*
 200                 * if this occurs, the pvfs2-client-core was killed but we
 201                 * can't afford to lose the inode operations and such
 202                 * associated with the root handle in any case.
 203                 */
 204                gossip_debug(GOSSIP_UTILS_DEBUG,
 205                             "*** NOT making bad root inode %pU\n",
 206                             get_khandle_from_ino(inode));
 207        } else {
 208                gossip_debug(GOSSIP_UTILS_DEBUG,
 209                             "*** making bad inode %pU\n",
 210                             get_khandle_from_ino(inode));
 211                make_bad_inode(inode);
 212        }
 213}
 214
 215static int orangefs_inode_is_stale(struct inode *inode,
 216    struct ORANGEFS_sys_attr_s *attrs, char *link_target)
 217{
 218        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 219        int type = orangefs_inode_type(attrs->objtype);
 220        /*
 221         * If the inode type or symlink target have changed then this
 222         * inode is stale.
 223         */
 224        if (type == -1 || inode_wrong_type(inode, type)) {
 225                orangefs_make_bad_inode(inode);
 226                return 1;
 227        }
 228        if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
 229            link_target, ORANGEFS_NAME_MAX)) {
 230                orangefs_make_bad_inode(inode);
 231                return 1;
 232        }
 233        return 0;
 234}
 235
 236int orangefs_inode_getattr(struct inode *inode, int flags)
 237{
 238        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 239        struct orangefs_kernel_op_s *new_op;
 240        loff_t inode_size;
 241        int ret, type;
 242
 243        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU flags %d\n",
 244            __func__, get_khandle_from_ino(inode), flags);
 245
 246again:
 247        spin_lock(&inode->i_lock);
 248        /* Must have all the attributes in the mask and be within cache time. */
 249        if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
 250            orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
 251                if (orangefs_inode->attr_valid) {
 252                        spin_unlock(&inode->i_lock);
 253                        write_inode_now(inode, 1);
 254                        goto again;
 255                }
 256                spin_unlock(&inode->i_lock);
 257                return 0;
 258        }
 259        spin_unlock(&inode->i_lock);
 260
 261        new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
 262        if (!new_op)
 263                return -ENOMEM;
 264        new_op->upcall.req.getattr.refn = orangefs_inode->refn;
 265        /*
 266         * Size is the hardest attribute to get.  The incremental cost of any
 267         * other attribute is essentially zero.
 268         */
 269        if (flags)
 270                new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
 271        else
 272                new_op->upcall.req.getattr.mask =
 273                    ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
 274
 275        ret = service_operation(new_op, __func__,
 276            get_interruptible_flag(inode));
 277        if (ret != 0)
 278                goto out;
 279
 280again2:
 281        spin_lock(&inode->i_lock);
 282        /* Must have all the attributes in the mask and be within cache time. */
 283        if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
 284            orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
 285                if (orangefs_inode->attr_valid) {
 286                        spin_unlock(&inode->i_lock);
 287                        write_inode_now(inode, 1);
 288                        goto again2;
 289                }
 290                if (inode->i_state & I_DIRTY_PAGES) {
 291                        ret = 0;
 292                        goto out_unlock;
 293                }
 294                gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n",
 295                    __func__);
 296                ret = 0;
 297                goto out_unlock;
 298        }
 299
 300        if (!(flags & ORANGEFS_GETATTR_NEW)) {
 301                ret = orangefs_inode_is_stale(inode,
 302                    &new_op->downcall.resp.getattr.attributes,
 303                    new_op->downcall.resp.getattr.link_target);
 304                if (ret) {
 305                        ret = -ESTALE;
 306                        goto out_unlock;
 307                }
 308        }
 309
 310        type = orangefs_inode_type(new_op->
 311            downcall.resp.getattr.attributes.objtype);
 312        switch (type) {
 313        case S_IFREG:
 314                inode->i_flags = orangefs_inode_flags(&new_op->
 315                    downcall.resp.getattr.attributes);
 316                if (flags) {
 317                        inode_size = (loff_t)new_op->
 318                            downcall.resp.getattr.attributes.size;
 319                        inode->i_size = inode_size;
 320                        inode->i_blkbits = ffs(new_op->downcall.resp.getattr.
 321                            attributes.blksize);
 322                        inode->i_bytes = inode_size;
 323                        inode->i_blocks =
 324                            (inode_size + 512 - inode_size % 512)/512;
 325                }
 326                break;
 327        case S_IFDIR:
 328                if (flags) {
 329                        inode->i_size = PAGE_SIZE;
 330                        inode_set_bytes(inode, inode->i_size);
 331                }
 332                set_nlink(inode, 1);
 333                break;
 334        case S_IFLNK:
 335                if (flags & ORANGEFS_GETATTR_NEW) {
 336                        inode->i_size = (loff_t)strlen(new_op->
 337                            downcall.resp.getattr.link_target);
 338                        ret = strscpy(orangefs_inode->link_target,
 339                            new_op->downcall.resp.getattr.link_target,
 340                            ORANGEFS_NAME_MAX);
 341                        if (ret == -E2BIG) {
 342                                ret = -EIO;
 343                                goto out_unlock;
 344                        }
 345                        inode->i_link = orangefs_inode->link_target;
 346                }
 347                break;
 348        /* i.e. -1 */
 349        default:
 350                /* XXX: ESTALE?  This is what is done if it is not new. */
 351                orangefs_make_bad_inode(inode);
 352                ret = -ESTALE;
 353                goto out_unlock;
 354        }
 355
 356        inode->i_uid = make_kuid(&init_user_ns, new_op->
 357            downcall.resp.getattr.attributes.owner);
 358        inode->i_gid = make_kgid(&init_user_ns, new_op->
 359            downcall.resp.getattr.attributes.group);
 360        inode->i_atime.tv_sec = (time64_t)new_op->
 361            downcall.resp.getattr.attributes.atime;
 362        inode->i_mtime.tv_sec = (time64_t)new_op->
 363            downcall.resp.getattr.attributes.mtime;
 364        inode->i_ctime.tv_sec = (time64_t)new_op->
 365            downcall.resp.getattr.attributes.ctime;
 366        inode->i_atime.tv_nsec = 0;
 367        inode->i_mtime.tv_nsec = 0;
 368        inode->i_ctime.tv_nsec = 0;
 369
 370        /* special case: mark the root inode as sticky */
 371        inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
 372            orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
 373
 374        orangefs_inode->getattr_time = jiffies +
 375            orangefs_getattr_timeout_msecs*HZ/1000;
 376        ret = 0;
 377out_unlock:
 378        spin_unlock(&inode->i_lock);
 379out:
 380        op_release(new_op);
 381        return ret;
 382}
 383
 384int orangefs_inode_check_changed(struct inode *inode)
 385{
 386        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 387        struct orangefs_kernel_op_s *new_op;
 388        int ret;
 389
 390        gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
 391            get_khandle_from_ino(inode));
 392
 393        new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
 394        if (!new_op)
 395                return -ENOMEM;
 396        new_op->upcall.req.getattr.refn = orangefs_inode->refn;
 397        new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
 398            ORANGEFS_ATTR_SYS_LNK_TARGET;
 399
 400        ret = service_operation(new_op, __func__,
 401            get_interruptible_flag(inode));
 402        if (ret != 0)
 403                goto out;
 404
 405        ret = orangefs_inode_is_stale(inode,
 406            &new_op->downcall.resp.getattr.attributes,
 407            new_op->downcall.resp.getattr.link_target);
 408out:
 409        op_release(new_op);
 410        return ret;
 411}
 412
 413/*
 414 * issues a orangefs setattr request to make sure the new attribute values
 415 * take effect if successful.  returns 0 on success; -errno otherwise
 416 */
 417int orangefs_inode_setattr(struct inode *inode)
 418{
 419        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 420        struct orangefs_kernel_op_s *new_op;
 421        int ret;
 422
 423        new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
 424        if (!new_op)
 425                return -ENOMEM;
 426
 427        spin_lock(&inode->i_lock);
 428        new_op->upcall.uid = from_kuid(&init_user_ns, orangefs_inode->attr_uid);
 429        new_op->upcall.gid = from_kgid(&init_user_ns, orangefs_inode->attr_gid);
 430        new_op->upcall.req.setattr.refn = orangefs_inode->refn;
 431        copy_attributes_from_inode(inode,
 432            &new_op->upcall.req.setattr.attributes);
 433        orangefs_inode->attr_valid = 0;
 434        if (!new_op->upcall.req.setattr.attributes.mask) {
 435                spin_unlock(&inode->i_lock);
 436                op_release(new_op);
 437                return 0;
 438        }
 439        spin_unlock(&inode->i_lock);
 440
 441        ret = service_operation(new_op, __func__,
 442            get_interruptible_flag(inode) | ORANGEFS_OP_WRITEBACK);
 443        gossip_debug(GOSSIP_UTILS_DEBUG,
 444            "orangefs_inode_setattr: returning %d\n", ret);
 445        if (ret)
 446                orangefs_make_bad_inode(inode);
 447
 448        op_release(new_op);
 449
 450        if (ret == 0)
 451                orangefs_inode->getattr_time = jiffies - 1;
 452        return ret;
 453}
 454
 455/*
 456 * The following is a very dirty hack that is now a permanent part of the
 457 * ORANGEFS protocol. See protocol.h for more error definitions.
 458 */
 459
 460/* The order matches include/orangefs-types.h in the OrangeFS source. */
 461static int PINT_errno_mapping[] = {
 462        0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
 463        EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
 464        EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
 465        ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
 466        EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
 467        EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
 468        ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
 469        EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
 470        ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
 471        EACCES, ECONNRESET, ERANGE
 472};
 473
 474int orangefs_normalize_to_errno(__s32 error_code)
 475{
 476        __u32 i;
 477
 478        /* Success */
 479        if (error_code == 0) {
 480                return 0;
 481        /*
 482         * This shouldn't ever happen. If it does it should be fixed on the
 483         * server.
 484         */
 485        } else if (error_code > 0) {
 486                gossip_err("orangefs: error status received.\n");
 487                gossip_err("orangefs: assuming error code is inverted.\n");
 488                error_code = -error_code;
 489        }
 490
 491        /*
 492         * XXX: This is very bad since error codes from ORANGEFS may not be
 493         * suitable for return into userspace.
 494         */
 495
 496        /*
 497         * Convert ORANGEFS error values into errno values suitable for return
 498         * from the kernel.
 499         */
 500        if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
 501                if (((-error_code) &
 502                    (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
 503                    ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
 504                        /*
 505                         * cancellation error codes generally correspond to
 506                         * a timeout from the client's perspective
 507                         */
 508                        error_code = -ETIMEDOUT;
 509                } else {
 510                        /* assume a default error code */
 511                        gossip_err("%s: bad error code :%d:.\n",
 512                                __func__,
 513                                error_code);
 514                        error_code = -EINVAL;
 515                }
 516
 517        /* Convert ORANGEFS encoded errno values into regular errno values. */
 518        } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
 519                i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
 520                if (i < ARRAY_SIZE(PINT_errno_mapping))
 521                        error_code = -PINT_errno_mapping[i];
 522                else
 523                        error_code = -EINVAL;
 524
 525        /*
 526         * Only ORANGEFS protocol error codes should ever come here. Otherwise
 527         * there is a bug somewhere.
 528         */
 529        } else {
 530                gossip_err("%s: unknown error code.\n", __func__);
 531                error_code = -EINVAL;
 532        }
 533        return error_code;
 534}
 535
 536#define NUM_MODES 11
 537__s32 ORANGEFS_util_translate_mode(int mode)
 538{
 539        int ret = 0;
 540        int i = 0;
 541        static int modes[NUM_MODES] = {
 542                S_IXOTH, S_IWOTH, S_IROTH,
 543                S_IXGRP, S_IWGRP, S_IRGRP,
 544                S_IXUSR, S_IWUSR, S_IRUSR,
 545                S_ISGID, S_ISUID
 546        };
 547        static int orangefs_modes[NUM_MODES] = {
 548                ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
 549                ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
 550                ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
 551                ORANGEFS_G_SGID, ORANGEFS_U_SUID
 552        };
 553
 554        for (i = 0; i < NUM_MODES; i++)
 555                if (mode & modes[i])
 556                        ret |= orangefs_modes[i];
 557
 558        return ret;
 559}
 560#undef NUM_MODES
 561