linux/fs/erofs/inode.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2017-2018 HUAWEI, Inc.
   4 *             https://www.huawei.com/
   5 * Copyright (C) 2021, Alibaba Cloud
   6 */
   7#include "xattr.h"
   8
   9#include <trace/events/erofs.h>
  10
  11/*
  12 * if inode is successfully read, return its inode page (or sometimes
  13 * the inode payload page if it's an extended inode) in order to fill
  14 * inline data if possible.
  15 */
  16static struct page *erofs_read_inode(struct inode *inode,
  17                                     unsigned int *ofs)
  18{
  19        struct super_block *sb = inode->i_sb;
  20        struct erofs_sb_info *sbi = EROFS_SB(sb);
  21        struct erofs_inode *vi = EROFS_I(inode);
  22        const erofs_off_t inode_loc = iloc(sbi, vi->nid);
  23
  24        erofs_blk_t blkaddr, nblks = 0;
  25        struct page *page;
  26        struct erofs_inode_compact *dic;
  27        struct erofs_inode_extended *die, *copied = NULL;
  28        unsigned int ifmt;
  29        int err;
  30
  31        blkaddr = erofs_blknr(inode_loc);
  32        *ofs = erofs_blkoff(inode_loc);
  33
  34        erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u",
  35                  __func__, vi->nid, *ofs, blkaddr);
  36
  37        page = erofs_get_meta_page(sb, blkaddr);
  38        if (IS_ERR(page)) {
  39                erofs_err(sb, "failed to get inode (nid: %llu) page, err %ld",
  40                          vi->nid, PTR_ERR(page));
  41                return page;
  42        }
  43
  44        dic = page_address(page) + *ofs;
  45        ifmt = le16_to_cpu(dic->i_format);
  46
  47        if (ifmt & ~EROFS_I_ALL) {
  48                erofs_err(inode->i_sb, "unsupported i_format %u of nid %llu",
  49                          ifmt, vi->nid);
  50                err = -EOPNOTSUPP;
  51                goto err_out;
  52        }
  53
  54        vi->datalayout = erofs_inode_datalayout(ifmt);
  55        if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) {
  56                erofs_err(inode->i_sb, "unsupported datalayout %u of nid %llu",
  57                          vi->datalayout, vi->nid);
  58                err = -EOPNOTSUPP;
  59                goto err_out;
  60        }
  61
  62        switch (erofs_inode_version(ifmt)) {
  63        case EROFS_INODE_LAYOUT_EXTENDED:
  64                vi->inode_isize = sizeof(struct erofs_inode_extended);
  65                /* check if the inode acrosses page boundary */
  66                if (*ofs + vi->inode_isize <= PAGE_SIZE) {
  67                        *ofs += vi->inode_isize;
  68                        die = (struct erofs_inode_extended *)dic;
  69                } else {
  70                        const unsigned int gotten = PAGE_SIZE - *ofs;
  71
  72                        copied = kmalloc(vi->inode_isize, GFP_NOFS);
  73                        if (!copied) {
  74                                err = -ENOMEM;
  75                                goto err_out;
  76                        }
  77                        memcpy(copied, dic, gotten);
  78                        unlock_page(page);
  79                        put_page(page);
  80
  81                        page = erofs_get_meta_page(sb, blkaddr + 1);
  82                        if (IS_ERR(page)) {
  83                                erofs_err(sb, "failed to get inode payload page (nid: %llu), err %ld",
  84                                          vi->nid, PTR_ERR(page));
  85                                kfree(copied);
  86                                return page;
  87                        }
  88                        *ofs = vi->inode_isize - gotten;
  89                        memcpy((u8 *)copied + gotten, page_address(page), *ofs);
  90                        die = copied;
  91                }
  92                vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount);
  93
  94                inode->i_mode = le16_to_cpu(die->i_mode);
  95                switch (inode->i_mode & S_IFMT) {
  96                case S_IFREG:
  97                case S_IFDIR:
  98                case S_IFLNK:
  99                        vi->raw_blkaddr = le32_to_cpu(die->i_u.raw_blkaddr);
 100                        break;
 101                case S_IFCHR:
 102                case S_IFBLK:
 103                        inode->i_rdev =
 104                                new_decode_dev(le32_to_cpu(die->i_u.rdev));
 105                        break;
 106                case S_IFIFO:
 107                case S_IFSOCK:
 108                        inode->i_rdev = 0;
 109                        break;
 110                default:
 111                        goto bogusimode;
 112                }
 113                i_uid_write(inode, le32_to_cpu(die->i_uid));
 114                i_gid_write(inode, le32_to_cpu(die->i_gid));
 115                set_nlink(inode, le32_to_cpu(die->i_nlink));
 116
 117                /* extended inode has its own timestamp */
 118                inode->i_ctime.tv_sec = le64_to_cpu(die->i_ctime);
 119                inode->i_ctime.tv_nsec = le32_to_cpu(die->i_ctime_nsec);
 120
 121                inode->i_size = le64_to_cpu(die->i_size);
 122
 123                /* total blocks for compressed files */
 124                if (erofs_inode_is_data_compressed(vi->datalayout))
 125                        nblks = le32_to_cpu(die->i_u.compressed_blocks);
 126                else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
 127                        /* fill chunked inode summary info */
 128                        vi->chunkformat = le16_to_cpu(die->i_u.c.format);
 129                kfree(copied);
 130                copied = NULL;
 131                break;
 132        case EROFS_INODE_LAYOUT_COMPACT:
 133                vi->inode_isize = sizeof(struct erofs_inode_compact);
 134                *ofs += vi->inode_isize;
 135                vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount);
 136
 137                inode->i_mode = le16_to_cpu(dic->i_mode);
 138                switch (inode->i_mode & S_IFMT) {
 139                case S_IFREG:
 140                case S_IFDIR:
 141                case S_IFLNK:
 142                        vi->raw_blkaddr = le32_to_cpu(dic->i_u.raw_blkaddr);
 143                        break;
 144                case S_IFCHR:
 145                case S_IFBLK:
 146                        inode->i_rdev =
 147                                new_decode_dev(le32_to_cpu(dic->i_u.rdev));
 148                        break;
 149                case S_IFIFO:
 150                case S_IFSOCK:
 151                        inode->i_rdev = 0;
 152                        break;
 153                default:
 154                        goto bogusimode;
 155                }
 156                i_uid_write(inode, le16_to_cpu(dic->i_uid));
 157                i_gid_write(inode, le16_to_cpu(dic->i_gid));
 158                set_nlink(inode, le16_to_cpu(dic->i_nlink));
 159
 160                /* use build time for compact inodes */
 161                inode->i_ctime.tv_sec = sbi->build_time;
 162                inode->i_ctime.tv_nsec = sbi->build_time_nsec;
 163
 164                inode->i_size = le32_to_cpu(dic->i_size);
 165                if (erofs_inode_is_data_compressed(vi->datalayout))
 166                        nblks = le32_to_cpu(dic->i_u.compressed_blocks);
 167                else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
 168                        vi->chunkformat = le16_to_cpu(dic->i_u.c.format);
 169                break;
 170        default:
 171                erofs_err(inode->i_sb,
 172                          "unsupported on-disk inode version %u of nid %llu",
 173                          erofs_inode_version(ifmt), vi->nid);
 174                err = -EOPNOTSUPP;
 175                goto err_out;
 176        }
 177
 178        if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
 179                if (vi->chunkformat & ~EROFS_CHUNK_FORMAT_ALL) {
 180                        erofs_err(inode->i_sb,
 181                                  "unsupported chunk format %x of nid %llu",
 182                                  vi->chunkformat, vi->nid);
 183                        err = -EOPNOTSUPP;
 184                        goto err_out;
 185                }
 186                vi->chunkbits = LOG_BLOCK_SIZE +
 187                        (vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK);
 188        }
 189        inode->i_mtime.tv_sec = inode->i_ctime.tv_sec;
 190        inode->i_atime.tv_sec = inode->i_ctime.tv_sec;
 191        inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec;
 192        inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec;
 193
 194        inode->i_flags &= ~S_DAX;
 195        if (test_opt(&sbi->ctx, DAX_ALWAYS) && S_ISREG(inode->i_mode) &&
 196            vi->datalayout == EROFS_INODE_FLAT_PLAIN)
 197                inode->i_flags |= S_DAX;
 198        if (!nblks)
 199                /* measure inode.i_blocks as generic filesystems */
 200                inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9;
 201        else
 202                inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK;
 203        return page;
 204
 205bogusimode:
 206        erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu",
 207                  inode->i_mode, vi->nid);
 208        err = -EFSCORRUPTED;
 209err_out:
 210        DBG_BUGON(1);
 211        kfree(copied);
 212        unlock_page(page);
 213        put_page(page);
 214        return ERR_PTR(err);
 215}
 216
 217static int erofs_fill_symlink(struct inode *inode, void *data,
 218                              unsigned int m_pofs)
 219{
 220        struct erofs_inode *vi = EROFS_I(inode);
 221        char *lnk;
 222
 223        /* if it cannot be handled with fast symlink scheme */
 224        if (vi->datalayout != EROFS_INODE_FLAT_INLINE ||
 225            inode->i_size >= PAGE_SIZE) {
 226                inode->i_op = &erofs_symlink_iops;
 227                return 0;
 228        }
 229
 230        lnk = kmalloc(inode->i_size + 1, GFP_KERNEL);
 231        if (!lnk)
 232                return -ENOMEM;
 233
 234        m_pofs += vi->xattr_isize;
 235        /* inline symlink data shouldn't cross page boundary as well */
 236        if (m_pofs + inode->i_size > PAGE_SIZE) {
 237                kfree(lnk);
 238                erofs_err(inode->i_sb,
 239                          "inline data cross block boundary @ nid %llu",
 240                          vi->nid);
 241                DBG_BUGON(1);
 242                return -EFSCORRUPTED;
 243        }
 244
 245        memcpy(lnk, data + m_pofs, inode->i_size);
 246        lnk[inode->i_size] = '\0';
 247
 248        inode->i_link = lnk;
 249        inode->i_op = &erofs_fast_symlink_iops;
 250        return 0;
 251}
 252
 253static int erofs_fill_inode(struct inode *inode, int isdir)
 254{
 255        struct erofs_inode *vi = EROFS_I(inode);
 256        struct page *page;
 257        unsigned int ofs;
 258        int err = 0;
 259
 260        trace_erofs_fill_inode(inode, isdir);
 261
 262        /* read inode base data from disk */
 263        page = erofs_read_inode(inode, &ofs);
 264        if (IS_ERR(page))
 265                return PTR_ERR(page);
 266
 267        /* setup the new inode */
 268        switch (inode->i_mode & S_IFMT) {
 269        case S_IFREG:
 270                inode->i_op = &erofs_generic_iops;
 271                if (erofs_inode_is_data_compressed(vi->datalayout))
 272                        inode->i_fop = &generic_ro_fops;
 273                else
 274                        inode->i_fop = &erofs_file_fops;
 275                break;
 276        case S_IFDIR:
 277                inode->i_op = &erofs_dir_iops;
 278                inode->i_fop = &erofs_dir_fops;
 279                break;
 280        case S_IFLNK:
 281                err = erofs_fill_symlink(inode, page_address(page), ofs);
 282                if (err)
 283                        goto out_unlock;
 284                inode_nohighmem(inode);
 285                break;
 286        case S_IFCHR:
 287        case S_IFBLK:
 288        case S_IFIFO:
 289        case S_IFSOCK:
 290                inode->i_op = &erofs_generic_iops;
 291                init_special_inode(inode, inode->i_mode, inode->i_rdev);
 292                goto out_unlock;
 293        default:
 294                err = -EFSCORRUPTED;
 295                goto out_unlock;
 296        }
 297
 298        if (erofs_inode_is_data_compressed(vi->datalayout)) {
 299                err = z_erofs_fill_inode(inode);
 300                goto out_unlock;
 301        }
 302        inode->i_mapping->a_ops = &erofs_raw_access_aops;
 303
 304out_unlock:
 305        unlock_page(page);
 306        put_page(page);
 307        return err;
 308}
 309
 310/*
 311 * erofs nid is 64bits, but i_ino is 'unsigned long', therefore
 312 * we should do more for 32-bit platform to find the right inode.
 313 */
 314static int erofs_ilookup_test_actor(struct inode *inode, void *opaque)
 315{
 316        const erofs_nid_t nid = *(erofs_nid_t *)opaque;
 317
 318        return EROFS_I(inode)->nid == nid;
 319}
 320
 321static int erofs_iget_set_actor(struct inode *inode, void *opaque)
 322{
 323        const erofs_nid_t nid = *(erofs_nid_t *)opaque;
 324
 325        inode->i_ino = erofs_inode_hash(nid);
 326        return 0;
 327}
 328
 329static inline struct inode *erofs_iget_locked(struct super_block *sb,
 330                                              erofs_nid_t nid)
 331{
 332        const unsigned long hashval = erofs_inode_hash(nid);
 333
 334        return iget5_locked(sb, hashval, erofs_ilookup_test_actor,
 335                erofs_iget_set_actor, &nid);
 336}
 337
 338struct inode *erofs_iget(struct super_block *sb,
 339                         erofs_nid_t nid,
 340                         bool isdir)
 341{
 342        struct inode *inode = erofs_iget_locked(sb, nid);
 343
 344        if (!inode)
 345                return ERR_PTR(-ENOMEM);
 346
 347        if (inode->i_state & I_NEW) {
 348                int err;
 349                struct erofs_inode *vi = EROFS_I(inode);
 350
 351                vi->nid = nid;
 352
 353                err = erofs_fill_inode(inode, isdir);
 354                if (!err)
 355                        unlock_new_inode(inode);
 356                else {
 357                        iget_failed(inode);
 358                        inode = ERR_PTR(err);
 359                }
 360        }
 361        return inode;
 362}
 363
 364int erofs_getattr(struct user_namespace *mnt_userns, const struct path *path,
 365                  struct kstat *stat, u32 request_mask,
 366                  unsigned int query_flags)
 367{
 368        struct inode *const inode = d_inode(path->dentry);
 369
 370        if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout))
 371                stat->attributes |= STATX_ATTR_COMPRESSED;
 372
 373        stat->attributes |= STATX_ATTR_IMMUTABLE;
 374        stat->attributes_mask |= (STATX_ATTR_COMPRESSED |
 375                                  STATX_ATTR_IMMUTABLE);
 376
 377        generic_fillattr(&init_user_ns, inode, stat);
 378        return 0;
 379}
 380
 381const struct inode_operations erofs_generic_iops = {
 382        .getattr = erofs_getattr,
 383        .listxattr = erofs_listxattr,
 384        .get_acl = erofs_get_acl,
 385        .fiemap = erofs_fiemap,
 386};
 387
 388const struct inode_operations erofs_symlink_iops = {
 389        .get_link = page_get_link,
 390        .getattr = erofs_getattr,
 391        .listxattr = erofs_listxattr,
 392        .get_acl = erofs_get_acl,
 393};
 394
 395const struct inode_operations erofs_fast_symlink_iops = {
 396        .get_link = simple_get_link,
 397        .getattr = erofs_getattr,
 398        .listxattr = erofs_listxattr,
 399        .get_acl = erofs_get_acl,
 400};
 401