root/fs/affs/inode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. affs_iget
  2. affs_write_inode
  3. affs_notify_change
  4. affs_evict_inode
  5. affs_new_inode
  6. affs_add_entry

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  linux/fs/affs/inode.c
   4  *
   5  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
   6  *
   7  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
   8  *
   9  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
  10  *
  11  *  (C) 1991  Linus Torvalds - minix filesystem
  12  */
  13 #include <linux/sched.h>
  14 #include <linux/cred.h>
  15 #include <linux/gfp.h>
  16 #include "affs.h"
  17 
  18 struct inode *affs_iget(struct super_block *sb, unsigned long ino)
  19 {
  20         struct affs_sb_info     *sbi = AFFS_SB(sb);
  21         struct buffer_head      *bh;
  22         struct affs_tail        *tail;
  23         struct inode            *inode;
  24         u32                      block;
  25         u32                      size;
  26         u32                      prot;
  27         u16                      id;
  28 
  29         inode = iget_locked(sb, ino);
  30         if (!inode)
  31                 return ERR_PTR(-ENOMEM);
  32         if (!(inode->i_state & I_NEW))
  33                 return inode;
  34 
  35         pr_debug("affs_iget(%lu)\n", inode->i_ino);
  36 
  37         block = inode->i_ino;
  38         bh = affs_bread(sb, block);
  39         if (!bh) {
  40                 affs_warning(sb, "read_inode", "Cannot read block %d", block);
  41                 goto bad_inode;
  42         }
  43         if (affs_checksum_block(sb, bh) || be32_to_cpu(AFFS_HEAD(bh)->ptype) != T_SHORT) {
  44                 affs_warning(sb,"read_inode",
  45                            "Checksum or type (ptype=%d) error on inode %d",
  46                            AFFS_HEAD(bh)->ptype, block);
  47                 goto bad_inode;
  48         }
  49 
  50         tail = AFFS_TAIL(sb, bh);
  51         prot = be32_to_cpu(tail->protect);
  52 
  53         inode->i_size = 0;
  54         set_nlink(inode, 1);
  55         inode->i_mode = 0;
  56         AFFS_I(inode)->i_extcnt = 1;
  57         AFFS_I(inode)->i_ext_last = ~1;
  58         AFFS_I(inode)->i_protect = prot;
  59         atomic_set(&AFFS_I(inode)->i_opencnt, 0);
  60         AFFS_I(inode)->i_blkcnt = 0;
  61         AFFS_I(inode)->i_lc = NULL;
  62         AFFS_I(inode)->i_lc_size = 0;
  63         AFFS_I(inode)->i_lc_shift = 0;
  64         AFFS_I(inode)->i_lc_mask = 0;
  65         AFFS_I(inode)->i_ac = NULL;
  66         AFFS_I(inode)->i_ext_bh = NULL;
  67         AFFS_I(inode)->mmu_private = 0;
  68         AFFS_I(inode)->i_lastalloc = 0;
  69         AFFS_I(inode)->i_pa_cnt = 0;
  70 
  71         if (affs_test_opt(sbi->s_flags, SF_SETMODE))
  72                 inode->i_mode = sbi->s_mode;
  73         else
  74                 inode->i_mode = affs_prot_to_mode(prot);
  75 
  76         id = be16_to_cpu(tail->uid);
  77         if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETUID))
  78                 inode->i_uid = sbi->s_uid;
  79         else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
  80                 i_uid_write(inode, 0);
  81         else
  82                 i_uid_write(inode, id);
  83 
  84         id = be16_to_cpu(tail->gid);
  85         if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETGID))
  86                 inode->i_gid = sbi->s_gid;
  87         else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
  88                 i_gid_write(inode, 0);
  89         else
  90                 i_gid_write(inode, id);
  91 
  92         switch (be32_to_cpu(tail->stype)) {
  93         case ST_ROOT:
  94                 inode->i_uid = sbi->s_uid;
  95                 inode->i_gid = sbi->s_gid;
  96                 /* fall through */
  97         case ST_USERDIR:
  98                 if (be32_to_cpu(tail->stype) == ST_USERDIR ||
  99                     affs_test_opt(sbi->s_flags, SF_SETMODE)) {
 100                         if (inode->i_mode & S_IRUSR)
 101                                 inode->i_mode |= S_IXUSR;
 102                         if (inode->i_mode & S_IRGRP)
 103                                 inode->i_mode |= S_IXGRP;
 104                         if (inode->i_mode & S_IROTH)
 105                                 inode->i_mode |= S_IXOTH;
 106                         inode->i_mode |= S_IFDIR;
 107                 } else
 108                         inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;
 109                 /* Maybe it should be controlled by mount parameter? */
 110                 //inode->i_mode |= S_ISVTX;
 111                 inode->i_op = &affs_dir_inode_operations;
 112                 inode->i_fop = &affs_dir_operations;
 113                 break;
 114         case ST_LINKDIR:
 115 #if 0
 116                 affs_warning(sb, "read_inode", "inode is LINKDIR");
 117                 goto bad_inode;
 118 #else
 119                 inode->i_mode |= S_IFDIR;
 120                 /* ... and leave ->i_op and ->i_fop pointing to empty */
 121                 break;
 122 #endif
 123         case ST_LINKFILE:
 124                 affs_warning(sb, "read_inode", "inode is LINKFILE");
 125                 goto bad_inode;
 126         case ST_FILE:
 127                 size = be32_to_cpu(tail->size);
 128                 inode->i_mode |= S_IFREG;
 129                 AFFS_I(inode)->mmu_private = inode->i_size = size;
 130                 if (inode->i_size) {
 131                         AFFS_I(inode)->i_blkcnt = (size - 1) /
 132                                                sbi->s_data_blksize + 1;
 133                         AFFS_I(inode)->i_extcnt = (AFFS_I(inode)->i_blkcnt - 1) /
 134                                                sbi->s_hashsize + 1;
 135                 }
 136                 if (tail->link_chain)
 137                         set_nlink(inode, 2);
 138                 inode->i_mapping->a_ops = affs_test_opt(sbi->s_flags, SF_OFS) ?
 139                                           &affs_aops_ofs : &affs_aops;
 140                 inode->i_op = &affs_file_inode_operations;
 141                 inode->i_fop = &affs_file_operations;
 142                 break;
 143         case ST_SOFTLINK:
 144                 inode->i_size = strlen((char *)AFFS_HEAD(bh)->table);
 145                 inode->i_mode |= S_IFLNK;
 146                 inode_nohighmem(inode);
 147                 inode->i_op = &affs_symlink_inode_operations;
 148                 inode->i_data.a_ops = &affs_symlink_aops;
 149                 break;
 150         }
 151 
 152         inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec
 153                        = (be32_to_cpu(tail->change.days) * 86400LL +
 154                          be32_to_cpu(tail->change.mins) * 60 +
 155                          be32_to_cpu(tail->change.ticks) / 50 +
 156                          AFFS_EPOCH_DELTA) +
 157                          sys_tz.tz_minuteswest * 60;
 158         inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
 159         affs_brelse(bh);
 160         unlock_new_inode(inode);
 161         return inode;
 162 
 163 bad_inode:
 164         affs_brelse(bh);
 165         iget_failed(inode);
 166         return ERR_PTR(-EIO);
 167 }
 168 
 169 int
 170 affs_write_inode(struct inode *inode, struct writeback_control *wbc)
 171 {
 172         struct super_block      *sb = inode->i_sb;
 173         struct buffer_head      *bh;
 174         struct affs_tail        *tail;
 175         uid_t                    uid;
 176         gid_t                    gid;
 177 
 178         pr_debug("write_inode(%lu)\n", inode->i_ino);
 179 
 180         if (!inode->i_nlink)
 181                 // possibly free block
 182                 return 0;
 183         bh = affs_bread(sb, inode->i_ino);
 184         if (!bh) {
 185                 affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
 186                 return -EIO;
 187         }
 188         tail = AFFS_TAIL(sb, bh);
 189         if (tail->stype == cpu_to_be32(ST_ROOT)) {
 190                 affs_secs_to_datestamp(inode->i_mtime.tv_sec,
 191                                        &AFFS_ROOT_TAIL(sb, bh)->root_change);
 192         } else {
 193                 tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
 194                 tail->size = cpu_to_be32(inode->i_size);
 195                 affs_secs_to_datestamp(inode->i_mtime.tv_sec, &tail->change);
 196                 if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) {
 197                         uid = i_uid_read(inode);
 198                         gid = i_gid_read(inode);
 199                         if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_MUFS)) {
 200                                 if (uid == 0 || uid == 0xFFFF)
 201                                         uid = uid ^ ~0;
 202                                 if (gid == 0 || gid == 0xFFFF)
 203                                         gid = gid ^ ~0;
 204                         }
 205                         if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETUID))
 206                                 tail->uid = cpu_to_be16(uid);
 207                         if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETGID))
 208                                 tail->gid = cpu_to_be16(gid);
 209                 }
 210         }
 211         affs_fix_checksum(sb, bh);
 212         mark_buffer_dirty_inode(bh, inode);
 213         affs_brelse(bh);
 214         affs_free_prealloc(inode);
 215         return 0;
 216 }
 217 
 218 int
 219 affs_notify_change(struct dentry *dentry, struct iattr *attr)
 220 {
 221         struct inode *inode = d_inode(dentry);
 222         int error;
 223 
 224         pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
 225 
 226         error = setattr_prepare(dentry, attr);
 227         if (error)
 228                 goto out;
 229 
 230         if (((attr->ia_valid & ATTR_UID) &&
 231               affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETUID)) ||
 232             ((attr->ia_valid & ATTR_GID) &&
 233               affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETGID)) ||
 234             ((attr->ia_valid & ATTR_MODE) &&
 235              (AFFS_SB(inode->i_sb)->s_flags &
 236               (AFFS_MOUNT_SF_SETMODE | AFFS_MOUNT_SF_IMMUTABLE)))) {
 237                 if (!affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_QUIET))
 238                         error = -EPERM;
 239                 goto out;
 240         }
 241 
 242         if ((attr->ia_valid & ATTR_SIZE) &&
 243             attr->ia_size != i_size_read(inode)) {
 244                 error = inode_newsize_ok(inode, attr->ia_size);
 245                 if (error)
 246                         return error;
 247 
 248                 truncate_setsize(inode, attr->ia_size);
 249                 affs_truncate(inode);
 250         }
 251 
 252         setattr_copy(inode, attr);
 253         mark_inode_dirty(inode);
 254 
 255         if (attr->ia_valid & ATTR_MODE)
 256                 affs_mode_to_prot(inode);
 257 out:
 258         return error;
 259 }
 260 
 261 void
 262 affs_evict_inode(struct inode *inode)
 263 {
 264         unsigned long cache_page;
 265         pr_debug("evict_inode(ino=%lu, nlink=%u)\n",
 266                  inode->i_ino, inode->i_nlink);
 267         truncate_inode_pages_final(&inode->i_data);
 268 
 269         if (!inode->i_nlink) {
 270                 inode->i_size = 0;
 271                 affs_truncate(inode);
 272         }
 273 
 274         invalidate_inode_buffers(inode);
 275         clear_inode(inode);
 276         affs_free_prealloc(inode);
 277         cache_page = (unsigned long)AFFS_I(inode)->i_lc;
 278         if (cache_page) {
 279                 pr_debug("freeing ext cache\n");
 280                 AFFS_I(inode)->i_lc = NULL;
 281                 AFFS_I(inode)->i_ac = NULL;
 282                 free_page(cache_page);
 283         }
 284         affs_brelse(AFFS_I(inode)->i_ext_bh);
 285         AFFS_I(inode)->i_ext_last = ~1;
 286         AFFS_I(inode)->i_ext_bh = NULL;
 287 
 288         if (!inode->i_nlink)
 289                 affs_free_block(inode->i_sb, inode->i_ino);
 290 }
 291 
 292 struct inode *
 293 affs_new_inode(struct inode *dir)
 294 {
 295         struct super_block      *sb = dir->i_sb;
 296         struct inode            *inode;
 297         u32                      block;
 298         struct buffer_head      *bh;
 299 
 300         if (!(inode = new_inode(sb)))
 301                 goto err_inode;
 302 
 303         if (!(block = affs_alloc_block(dir, dir->i_ino)))
 304                 goto err_block;
 305 
 306         bh = affs_getzeroblk(sb, block);
 307         if (!bh)
 308                 goto err_bh;
 309         mark_buffer_dirty_inode(bh, inode);
 310         affs_brelse(bh);
 311 
 312         inode->i_uid     = current_fsuid();
 313         inode->i_gid     = current_fsgid();
 314         inode->i_ino     = block;
 315         set_nlink(inode, 1);
 316         inode->i_mtime   = inode->i_atime = inode->i_ctime = current_time(inode);
 317         atomic_set(&AFFS_I(inode)->i_opencnt, 0);
 318         AFFS_I(inode)->i_blkcnt = 0;
 319         AFFS_I(inode)->i_lc = NULL;
 320         AFFS_I(inode)->i_lc_size = 0;
 321         AFFS_I(inode)->i_lc_shift = 0;
 322         AFFS_I(inode)->i_lc_mask = 0;
 323         AFFS_I(inode)->i_ac = NULL;
 324         AFFS_I(inode)->i_ext_bh = NULL;
 325         AFFS_I(inode)->mmu_private = 0;
 326         AFFS_I(inode)->i_protect = 0;
 327         AFFS_I(inode)->i_lastalloc = 0;
 328         AFFS_I(inode)->i_pa_cnt = 0;
 329         AFFS_I(inode)->i_extcnt = 1;
 330         AFFS_I(inode)->i_ext_last = ~1;
 331 
 332         insert_inode_hash(inode);
 333 
 334         return inode;
 335 
 336 err_bh:
 337         affs_free_block(sb, block);
 338 err_block:
 339         iput(inode);
 340 err_inode:
 341         return NULL;
 342 }
 343 
 344 /*
 345  * Add an entry to a directory. Create the header block
 346  * and insert it into the hash table.
 347  */
 348 
 349 int
 350 affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type)
 351 {
 352         struct super_block *sb = dir->i_sb;
 353         struct buffer_head *inode_bh = NULL;
 354         struct buffer_head *bh;
 355         u32 block = 0;
 356         int retval;
 357 
 358         pr_debug("%s(dir=%lu, inode=%lu, \"%pd\", type=%d)\n", __func__,
 359                  dir->i_ino, inode->i_ino, dentry, type);
 360 
 361         retval = -EIO;
 362         bh = affs_bread(sb, inode->i_ino);
 363         if (!bh)
 364                 goto done;
 365 
 366         affs_lock_link(inode);
 367         switch (type) {
 368         case ST_LINKFILE:
 369         case ST_LINKDIR:
 370                 retval = -ENOSPC;
 371                 block = affs_alloc_block(dir, dir->i_ino);
 372                 if (!block)
 373                         goto err;
 374                 retval = -EIO;
 375                 inode_bh = bh;
 376                 bh = affs_getzeroblk(sb, block);
 377                 if (!bh)
 378                         goto err;
 379                 break;
 380         default:
 381                 break;
 382         }
 383 
 384         AFFS_HEAD(bh)->ptype = cpu_to_be32(T_SHORT);
 385         AFFS_HEAD(bh)->key = cpu_to_be32(bh->b_blocknr);
 386         affs_copy_name(AFFS_TAIL(sb, bh)->name, dentry);
 387         AFFS_TAIL(sb, bh)->stype = cpu_to_be32(type);
 388         AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
 389 
 390         if (inode_bh) {
 391                 __be32 chain;
 392                 chain = AFFS_TAIL(sb, inode_bh)->link_chain;
 393                 AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
 394                 AFFS_TAIL(sb, bh)->link_chain = chain;
 395                 AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
 396                 affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
 397                 mark_buffer_dirty_inode(inode_bh, inode);
 398                 set_nlink(inode, 2);
 399                 ihold(inode);
 400         }
 401         affs_fix_checksum(sb, bh);
 402         mark_buffer_dirty_inode(bh, inode);
 403         dentry->d_fsdata = (void *)(long)bh->b_blocknr;
 404 
 405         affs_lock_dir(dir);
 406         retval = affs_insert_hash(dir, bh);
 407         mark_buffer_dirty_inode(bh, inode);
 408         affs_unlock_dir(dir);
 409         affs_unlock_link(inode);
 410 
 411         d_instantiate(dentry, inode);
 412 done:
 413         affs_brelse(inode_bh);
 414         affs_brelse(bh);
 415         return retval;
 416 err:
 417         if (block)
 418                 affs_free_block(sb, block);
 419         affs_unlock_link(inode);
 420         goto done;
 421 }

/* [<][>][^][v][top][bottom][index][help] */