Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  linux/fs/affs/inode.c
0004  *
0005  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
0006  *
0007  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
0008  *
0009  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
0010  *
0011  *  (C) 1991  Linus Torvalds - minix filesystem
0012  */
0013 #include <linux/sched.h>
0014 #include <linux/cred.h>
0015 #include <linux/gfp.h>
0016 #include "affs.h"
0017 
0018 struct inode *affs_iget(struct super_block *sb, unsigned long ino)
0019 {
0020     struct affs_sb_info *sbi = AFFS_SB(sb);
0021     struct buffer_head  *bh;
0022     struct affs_tail    *tail;
0023     struct inode        *inode;
0024     u32          block;
0025     u32          size;
0026     u32          prot;
0027     u16          id;
0028 
0029     inode = iget_locked(sb, ino);
0030     if (!inode)
0031         return ERR_PTR(-ENOMEM);
0032     if (!(inode->i_state & I_NEW))
0033         return inode;
0034 
0035     pr_debug("affs_iget(%lu)\n", inode->i_ino);
0036 
0037     block = inode->i_ino;
0038     bh = affs_bread(sb, block);
0039     if (!bh) {
0040         affs_warning(sb, "read_inode", "Cannot read block %d", block);
0041         goto bad_inode;
0042     }
0043     if (affs_checksum_block(sb, bh) || be32_to_cpu(AFFS_HEAD(bh)->ptype) != T_SHORT) {
0044         affs_warning(sb,"read_inode",
0045                "Checksum or type (ptype=%d) error on inode %d",
0046                AFFS_HEAD(bh)->ptype, block);
0047         goto bad_inode;
0048     }
0049 
0050     tail = AFFS_TAIL(sb, bh);
0051     prot = be32_to_cpu(tail->protect);
0052 
0053     inode->i_size = 0;
0054     set_nlink(inode, 1);
0055     inode->i_mode = 0;
0056     AFFS_I(inode)->i_extcnt = 1;
0057     AFFS_I(inode)->i_ext_last = ~1;
0058     AFFS_I(inode)->i_protect = prot;
0059     atomic_set(&AFFS_I(inode)->i_opencnt, 0);
0060     AFFS_I(inode)->i_blkcnt = 0;
0061     AFFS_I(inode)->i_lc = NULL;
0062     AFFS_I(inode)->i_lc_size = 0;
0063     AFFS_I(inode)->i_lc_shift = 0;
0064     AFFS_I(inode)->i_lc_mask = 0;
0065     AFFS_I(inode)->i_ac = NULL;
0066     AFFS_I(inode)->i_ext_bh = NULL;
0067     AFFS_I(inode)->mmu_private = 0;
0068     AFFS_I(inode)->i_lastalloc = 0;
0069     AFFS_I(inode)->i_pa_cnt = 0;
0070 
0071     if (affs_test_opt(sbi->s_flags, SF_SETMODE))
0072         inode->i_mode = sbi->s_mode;
0073     else
0074         inode->i_mode = affs_prot_to_mode(prot);
0075 
0076     id = be16_to_cpu(tail->uid);
0077     if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETUID))
0078         inode->i_uid = sbi->s_uid;
0079     else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
0080         i_uid_write(inode, 0);
0081     else
0082         i_uid_write(inode, id);
0083 
0084     id = be16_to_cpu(tail->gid);
0085     if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETGID))
0086         inode->i_gid = sbi->s_gid;
0087     else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
0088         i_gid_write(inode, 0);
0089     else
0090         i_gid_write(inode, id);
0091 
0092     switch (be32_to_cpu(tail->stype)) {
0093     case ST_ROOT:
0094         inode->i_uid = sbi->s_uid;
0095         inode->i_gid = sbi->s_gid;
0096         fallthrough;
0097     case ST_USERDIR:
0098         if (be32_to_cpu(tail->stype) == ST_USERDIR ||
0099             affs_test_opt(sbi->s_flags, SF_SETMODE)) {
0100             if (inode->i_mode & S_IRUSR)
0101                 inode->i_mode |= S_IXUSR;
0102             if (inode->i_mode & S_IRGRP)
0103                 inode->i_mode |= S_IXGRP;
0104             if (inode->i_mode & S_IROTH)
0105                 inode->i_mode |= S_IXOTH;
0106             inode->i_mode |= S_IFDIR;
0107         } else
0108             inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;
0109         /* Maybe it should be controlled by mount parameter? */
0110         //inode->i_mode |= S_ISVTX;
0111         inode->i_op = &affs_dir_inode_operations;
0112         inode->i_fop = &affs_dir_operations;
0113         break;
0114     case ST_LINKDIR:
0115 #if 0
0116         affs_warning(sb, "read_inode", "inode is LINKDIR");
0117         goto bad_inode;
0118 #else
0119         inode->i_mode |= S_IFDIR;
0120         /* ... and leave ->i_op and ->i_fop pointing to empty */
0121         break;
0122 #endif
0123     case ST_LINKFILE:
0124         affs_warning(sb, "read_inode", "inode is LINKFILE");
0125         goto bad_inode;
0126     case ST_FILE:
0127         size = be32_to_cpu(tail->size);
0128         inode->i_mode |= S_IFREG;
0129         AFFS_I(inode)->mmu_private = inode->i_size = size;
0130         if (inode->i_size) {
0131             AFFS_I(inode)->i_blkcnt = (size - 1) /
0132                            sbi->s_data_blksize + 1;
0133             AFFS_I(inode)->i_extcnt = (AFFS_I(inode)->i_blkcnt - 1) /
0134                            sbi->s_hashsize + 1;
0135         }
0136         if (tail->link_chain)
0137             set_nlink(inode, 2);
0138         inode->i_mapping->a_ops = affs_test_opt(sbi->s_flags, SF_OFS) ?
0139                       &affs_aops_ofs : &affs_aops;
0140         inode->i_op = &affs_file_inode_operations;
0141         inode->i_fop = &affs_file_operations;
0142         break;
0143     case ST_SOFTLINK:
0144         inode->i_size = strlen((char *)AFFS_HEAD(bh)->table);
0145         inode->i_mode |= S_IFLNK;
0146         inode_nohighmem(inode);
0147         inode->i_op = &affs_symlink_inode_operations;
0148         inode->i_data.a_ops = &affs_symlink_aops;
0149         break;
0150     }
0151 
0152     inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec
0153                = (be32_to_cpu(tail->change.days) * 86400LL +
0154                  be32_to_cpu(tail->change.mins) * 60 +
0155              be32_to_cpu(tail->change.ticks) / 50 +
0156              AFFS_EPOCH_DELTA) +
0157              sys_tz.tz_minuteswest * 60;
0158     inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
0159     affs_brelse(bh);
0160     unlock_new_inode(inode);
0161     return inode;
0162 
0163 bad_inode:
0164     affs_brelse(bh);
0165     iget_failed(inode);
0166     return ERR_PTR(-EIO);
0167 }
0168 
0169 int
0170 affs_write_inode(struct inode *inode, struct writeback_control *wbc)
0171 {
0172     struct super_block  *sb = inode->i_sb;
0173     struct buffer_head  *bh;
0174     struct affs_tail    *tail;
0175     uid_t            uid;
0176     gid_t            gid;
0177 
0178     pr_debug("write_inode(%lu)\n", inode->i_ino);
0179 
0180     if (!inode->i_nlink)
0181         // possibly free block
0182         return 0;
0183     bh = affs_bread(sb, inode->i_ino);
0184     if (!bh) {
0185         affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
0186         return -EIO;
0187     }
0188     tail = AFFS_TAIL(sb, bh);
0189     if (tail->stype == cpu_to_be32(ST_ROOT)) {
0190         affs_secs_to_datestamp(inode->i_mtime.tv_sec,
0191                        &AFFS_ROOT_TAIL(sb, bh)->root_change);
0192     } else {
0193         tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
0194         tail->size = cpu_to_be32(inode->i_size);
0195         affs_secs_to_datestamp(inode->i_mtime.tv_sec, &tail->change);
0196         if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) {
0197             uid = i_uid_read(inode);
0198             gid = i_gid_read(inode);
0199             if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_MUFS)) {
0200                 if (uid == 0 || uid == 0xFFFF)
0201                     uid = uid ^ ~0;
0202                 if (gid == 0 || gid == 0xFFFF)
0203                     gid = gid ^ ~0;
0204             }
0205             if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETUID))
0206                 tail->uid = cpu_to_be16(uid);
0207             if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETGID))
0208                 tail->gid = cpu_to_be16(gid);
0209         }
0210     }
0211     affs_fix_checksum(sb, bh);
0212     mark_buffer_dirty_inode(bh, inode);
0213     affs_brelse(bh);
0214     affs_free_prealloc(inode);
0215     return 0;
0216 }
0217 
0218 int
0219 affs_notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
0220            struct iattr *attr)
0221 {
0222     struct inode *inode = d_inode(dentry);
0223     int error;
0224 
0225     pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
0226 
0227     error = setattr_prepare(&init_user_ns, dentry, attr);
0228     if (error)
0229         goto out;
0230 
0231     if (((attr->ia_valid & ATTR_UID) &&
0232           affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETUID)) ||
0233         ((attr->ia_valid & ATTR_GID) &&
0234           affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETGID)) ||
0235         ((attr->ia_valid & ATTR_MODE) &&
0236          (AFFS_SB(inode->i_sb)->s_flags &
0237           (AFFS_MOUNT_SF_SETMODE | AFFS_MOUNT_SF_IMMUTABLE)))) {
0238         if (!affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_QUIET))
0239             error = -EPERM;
0240         goto out;
0241     }
0242 
0243     if ((attr->ia_valid & ATTR_SIZE) &&
0244         attr->ia_size != i_size_read(inode)) {
0245         error = inode_newsize_ok(inode, attr->ia_size);
0246         if (error)
0247             return error;
0248 
0249         truncate_setsize(inode, attr->ia_size);
0250         affs_truncate(inode);
0251     }
0252 
0253     setattr_copy(&init_user_ns, inode, attr);
0254     mark_inode_dirty(inode);
0255 
0256     if (attr->ia_valid & ATTR_MODE)
0257         affs_mode_to_prot(inode);
0258 out:
0259     return error;
0260 }
0261 
0262 void
0263 affs_evict_inode(struct inode *inode)
0264 {
0265     unsigned long cache_page;
0266     pr_debug("evict_inode(ino=%lu, nlink=%u)\n",
0267          inode->i_ino, inode->i_nlink);
0268     truncate_inode_pages_final(&inode->i_data);
0269 
0270     if (!inode->i_nlink) {
0271         inode->i_size = 0;
0272         affs_truncate(inode);
0273     }
0274 
0275     invalidate_inode_buffers(inode);
0276     clear_inode(inode);
0277     affs_free_prealloc(inode);
0278     cache_page = (unsigned long)AFFS_I(inode)->i_lc;
0279     if (cache_page) {
0280         pr_debug("freeing ext cache\n");
0281         AFFS_I(inode)->i_lc = NULL;
0282         AFFS_I(inode)->i_ac = NULL;
0283         free_page(cache_page);
0284     }
0285     affs_brelse(AFFS_I(inode)->i_ext_bh);
0286     AFFS_I(inode)->i_ext_last = ~1;
0287     AFFS_I(inode)->i_ext_bh = NULL;
0288 
0289     if (!inode->i_nlink)
0290         affs_free_block(inode->i_sb, inode->i_ino);
0291 }
0292 
0293 struct inode *
0294 affs_new_inode(struct inode *dir)
0295 {
0296     struct super_block  *sb = dir->i_sb;
0297     struct inode        *inode;
0298     u32          block;
0299     struct buffer_head  *bh;
0300 
0301     if (!(inode = new_inode(sb)))
0302         goto err_inode;
0303 
0304     if (!(block = affs_alloc_block(dir, dir->i_ino)))
0305         goto err_block;
0306 
0307     bh = affs_getzeroblk(sb, block);
0308     if (!bh)
0309         goto err_bh;
0310     mark_buffer_dirty_inode(bh, inode);
0311     affs_brelse(bh);
0312 
0313     inode->i_uid     = current_fsuid();
0314     inode->i_gid     = current_fsgid();
0315     inode->i_ino     = block;
0316     set_nlink(inode, 1);
0317     inode->i_mtime   = inode->i_atime = inode->i_ctime = current_time(inode);
0318     atomic_set(&AFFS_I(inode)->i_opencnt, 0);
0319     AFFS_I(inode)->i_blkcnt = 0;
0320     AFFS_I(inode)->i_lc = NULL;
0321     AFFS_I(inode)->i_lc_size = 0;
0322     AFFS_I(inode)->i_lc_shift = 0;
0323     AFFS_I(inode)->i_lc_mask = 0;
0324     AFFS_I(inode)->i_ac = NULL;
0325     AFFS_I(inode)->i_ext_bh = NULL;
0326     AFFS_I(inode)->mmu_private = 0;
0327     AFFS_I(inode)->i_protect = 0;
0328     AFFS_I(inode)->i_lastalloc = 0;
0329     AFFS_I(inode)->i_pa_cnt = 0;
0330     AFFS_I(inode)->i_extcnt = 1;
0331     AFFS_I(inode)->i_ext_last = ~1;
0332 
0333     insert_inode_hash(inode);
0334 
0335     return inode;
0336 
0337 err_bh:
0338     affs_free_block(sb, block);
0339 err_block:
0340     iput(inode);
0341 err_inode:
0342     return NULL;
0343 }
0344 
0345 /*
0346  * Add an entry to a directory. Create the header block
0347  * and insert it into the hash table.
0348  */
0349 
0350 int
0351 affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type)
0352 {
0353     struct super_block *sb = dir->i_sb;
0354     struct buffer_head *inode_bh = NULL;
0355     struct buffer_head *bh;
0356     u32 block = 0;
0357     int retval;
0358 
0359     pr_debug("%s(dir=%lu, inode=%lu, \"%pd\", type=%d)\n", __func__,
0360          dir->i_ino, inode->i_ino, dentry, type);
0361 
0362     retval = -EIO;
0363     bh = affs_bread(sb, inode->i_ino);
0364     if (!bh)
0365         goto done;
0366 
0367     affs_lock_link(inode);
0368     switch (type) {
0369     case ST_LINKFILE:
0370     case ST_LINKDIR:
0371         retval = -ENOSPC;
0372         block = affs_alloc_block(dir, dir->i_ino);
0373         if (!block)
0374             goto err;
0375         retval = -EIO;
0376         inode_bh = bh;
0377         bh = affs_getzeroblk(sb, block);
0378         if (!bh)
0379             goto err;
0380         break;
0381     default:
0382         break;
0383     }
0384 
0385     AFFS_HEAD(bh)->ptype = cpu_to_be32(T_SHORT);
0386     AFFS_HEAD(bh)->key = cpu_to_be32(bh->b_blocknr);
0387     affs_copy_name(AFFS_TAIL(sb, bh)->name, dentry);
0388     AFFS_TAIL(sb, bh)->stype = cpu_to_be32(type);
0389     AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
0390 
0391     if (inode_bh) {
0392         __be32 chain;
0393             chain = AFFS_TAIL(sb, inode_bh)->link_chain;
0394         AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
0395         AFFS_TAIL(sb, bh)->link_chain = chain;
0396         AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
0397         affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
0398         mark_buffer_dirty_inode(inode_bh, inode);
0399         set_nlink(inode, 2);
0400         ihold(inode);
0401     }
0402     affs_fix_checksum(sb, bh);
0403     mark_buffer_dirty_inode(bh, inode);
0404     dentry->d_fsdata = (void *)(long)bh->b_blocknr;
0405 
0406     affs_lock_dir(dir);
0407     retval = affs_insert_hash(dir, bh);
0408     mark_buffer_dirty_inode(bh, inode);
0409     affs_unlock_dir(dir);
0410     affs_unlock_link(inode);
0411 
0412     d_instantiate(dentry, inode);
0413 done:
0414     affs_brelse(inode_bh);
0415     affs_brelse(bh);
0416     return retval;
0417 err:
0418     if (block)
0419         affs_free_block(sb, block);
0420     affs_unlock_link(inode);
0421     goto done;
0422 }