static int hpfs_fill_super(struct super_block *s, void *options, int silent) { struct buffer_head *bh0, *bh1, *bh2; struct hpfs_boot_block *bootblock; struct hpfs_super_block *superblock; struct hpfs_spare_block *spareblock; struct hpfs_sb_info *sbi; struct inode *root; kuid_t uid; kgid_t gid; umode_t umask; int lowercase, eas, chk, errs, chkdsk, timeshift; dnode_secno root_dno; struct hpfs_dirent *de = NULL; struct quad_buffer_head qbh; int o; save_mount_options(s, options); sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) { return -ENOMEM; } s->s_fs_info = sbi; sbi->sb_bmp_dir = NULL; sbi->sb_cp_table = NULL; mutex_init(&sbi->hpfs_mutex); hpfs_lock(s); uid = current_uid(); gid = current_gid(); umask = current_umask(); lowercase = 0; eas = 2; chk = 1; errs = 1; chkdsk = 1; timeshift = 0; if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase, &eas, &chk, &errs, &chkdsk, ×hift))) { printk("HPFS: bad mount options.\n"); goto bail0; } if (o==2) { hpfs_help(); goto bail0; } /*sbi->sb_mounting = 1;*/ sb_set_blocksize(s, 512); sbi->sb_fs_size = -1; if (!(bootblock = hpfs_map_sector(s, 0, &bh0, 0))) goto bail1; if (!(superblock = hpfs_map_sector(s, 16, &bh1, 1))) goto bail2; if (!(spareblock = hpfs_map_sector(s, 17, &bh2, 0))) goto bail3; /* Check magics */ if (/*le16_to_cpu(bootblock->magic) != BB_MAGIC ||*/ le32_to_cpu(superblock->magic) != SB_MAGIC || le32_to_cpu(spareblock->magic) != SP_MAGIC) { if (!silent) printk("HPFS: Bad magic ... probably not HPFS\n"); goto bail4; } /* Check version */ if (!(s->s_flags & MS_RDONLY) && superblock->funcversion != 2 && superblock->funcversion != 3) { printk("HPFS: Bad version %d,%d. Mount readonly to go around\n", (int)superblock->version, (int)superblock->funcversion); printk("HPFS: please try recent version of HPFS driver at http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi and if it still can't understand this format, contact author - [email protected]\n"); goto bail4; } s->s_flags |= MS_NOATIME; /* Fill superblock stuff */ s->s_magic = HPFS_SUPER_MAGIC; s->s_op = &hpfs_sops; s->s_d_op = &hpfs_dentry_operations; sbi->sb_root = le32_to_cpu(superblock->root); sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors); sbi->sb_bitmaps = le32_to_cpu(superblock->bitmaps); sbi->sb_dirband_start = le32_to_cpu(superblock->dir_band_start); sbi->sb_dirband_size = le32_to_cpu(superblock->n_dir_band); sbi->sb_dmap = le32_to_cpu(superblock->dir_band_bitmap); sbi->sb_uid = uid; sbi->sb_gid = gid; sbi->sb_mode = 0777 & ~umask; sbi->sb_n_free = -1; sbi->sb_n_free_dnodes = -1; sbi->sb_lowercase = lowercase; sbi->sb_eas = eas; sbi->sb_chk = chk; sbi->sb_chkdsk = chkdsk; sbi->sb_err = errs; sbi->sb_timeshift = timeshift; sbi->sb_was_error = 0; sbi->sb_cp_table = NULL; sbi->sb_c_bitmap = -1; sbi->sb_max_fwd_alloc = 0xffffff; if (sbi->sb_fs_size >= 0x80000000) { hpfs_error(s, "invalid size in superblock: %08x", (unsigned)sbi->sb_fs_size); goto bail4; } /* Load bitmap directory */ if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps)))) goto bail4; /* Check for general fs errors*/ if (spareblock->dirty && !spareblock->old_wrote) { if (errs == 2) { printk("HPFS: Improperly stopped, not mounted\n"); goto bail4; } hpfs_error(s, "improperly stopped"); } if (!(s->s_flags & MS_RDONLY)) { spareblock->dirty = 1; spareblock->old_wrote = 0; mark_buffer_dirty(bh2); } if (le32_to_cpu(spareblock->hotfixes_used) || le32_to_cpu(spareblock->n_spares_used)) { if (errs >= 2) { printk("HPFS: Hotfixes not supported here, try chkdsk\n"); mark_dirty(s, 0); goto bail4; } hpfs_error(s, "hotfixes not supported here, try chkdsk"); if (errs == 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n"); else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n"); } if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) { if (errs >= 2) { printk("HPFS: Spare dnodes used, try chkdsk\n"); mark_dirty(s, 0); goto bail4; } hpfs_error(s, "warning: spare dnodes used, try chkdsk"); if (errs == 0) printk("HPFS: Proceeding, but your filesystem could be corrupted if you delete files or directories\n"); } if (chk) { unsigned a; if (le32_to_cpu(superblock->dir_band_end) - le32_to_cpu(superblock->dir_band_start) + 1 != le32_to_cpu(superblock->n_dir_band) || le32_to_cpu(superblock->dir_band_end) < le32_to_cpu(superblock->dir_band_start) || le32_to_cpu(superblock->n_dir_band) > 0x4000) { hpfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x", le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->dir_band_end), le32_to_cpu(superblock->n_dir_band)); goto bail4; } a = sbi->sb_dirband_size; sbi->sb_dirband_size = 0; if (hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->n_dir_band), "dir_band") || hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_bitmap), 4, "dir_band_bitmap") || hpfs_chk_sectors(s, le32_to_cpu(superblock->bitmaps), 4, "bitmaps")) { mark_dirty(s, 0); goto bail4; } sbi->sb_dirband_size = a; } else printk("HPFS: You really don't want any checks? You are crazy...\n"); /* Load code page table */ if (le32_to_cpu(spareblock->n_code_pages)) if (!(sbi->sb_cp_table = hpfs_load_code_page(s, le32_to_cpu(spareblock->code_page_dir)))) printk("HPFS: Warning: code page support is disabled\n"); brelse(bh2); brelse(bh1); brelse(bh0); root = iget_locked(s, sbi->sb_root); if (!root) goto bail0; hpfs_init_inode(root); hpfs_read_inode(root); unlock_new_inode(root); s->s_root = d_make_root(root); if (!s->s_root) goto bail0; /* * find the root directory's . pointer & finish filling in the inode */ root_dno = hpfs_fnode_dno(s, sbi->sb_root); if (root_dno) de = map_dirent(root, root_dno, "\001\001", 2, NULL, &qbh); if (!de) hpfs_error(s, "unable to find root dir"); else { root->i_atime.tv_sec = local_to_gmt(s, le32_to_cpu(de->read_date)); root->i_atime.tv_nsec = 0; root->i_mtime.tv_sec = local_to_gmt(s, le32_to_cpu(de->write_date)); root->i_mtime.tv_nsec = 0; root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date)); root->i_ctime.tv_nsec = 0; hpfs_i(root)->i_ea_size = le16_to_cpu(de->ea_size); hpfs_i(root)->i_parent_dir = root->i_ino; if (root->i_size == -1) root->i_size = 2048; if (root->i_blocks == -1) root->i_blocks = 5; hpfs_brelse4(&qbh); } hpfs_unlock(s); return 0; bail4: brelse(bh2); bail3: brelse(bh1); bail2: brelse(bh0); bail1: bail0: hpfs_unlock(s); kfree(sbi->sb_bmp_dir); kfree(sbi->sb_cp_table); s->s_fs_info = NULL; kfree(sbi); return -EINVAL; }
/** * This is called when vfs failed to locate dentry in the cache. The * job of this function is to allocate inode and link it to dentry. * [dentry] contains the name to be looked in the [parent] directory. * Failure to locate the name is not a "hard" error, in this case NULL * inode is added to [dentry] and vfs should proceed trying to create * the entry via other means. NULL(or "positive" pointer) ought to be * returned in case of success and "negative" pointer on error */ static struct dentry *sf_lookup(struct inode *parent, struct dentry *dentry #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) , unsigned int flags #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) , struct nameidata *nd #endif ) { int err; struct sf_inode_info *sf_i, *sf_new_i; struct sf_glob_info *sf_g; SHFLSTRING *path; struct inode *inode; ino_t ino; SHFLFSOBJINFO fsinfo; TRACE(); sf_g = GET_GLOB_INFO(parent->i_sb); sf_i = GET_INODE_INFO(parent); BUG_ON(!sf_g); BUG_ON(!sf_i); err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path); if (err) goto fail0; err = sf_stat(__func__, sf_g, path, &fsinfo, 1); if (err) { if (err == -ENOENT) { /* -ENOENT: add NULL inode to dentry so it later can be created via call to create/mkdir/open */ kfree(path); inode = NULL; } else goto fail1; } else { sf_new_i = kmalloc(sizeof(*sf_new_i), GFP_KERNEL); if (!sf_new_i) { LogRelFunc(("could not allocate memory for new inode info\n")); err = -ENOMEM; goto fail1; } sf_new_i->handle = SHFL_HANDLE_NIL; sf_new_i->force_reread = 0; ino = iunique(parent->i_sb, 1); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) inode = iget_locked(parent->i_sb, ino); #else inode = iget(parent->i_sb, ino); #endif if (!inode) { LogFunc(("iget failed\n")); err = -ENOMEM; /* XXX: ??? */ goto fail2; } SET_INODE_INFO(inode, sf_new_i); sf_init_inode(sf_g, inode, &fsinfo); sf_new_i->path = path; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(inode); #endif } sf_i->force_restat = 0; dentry->d_time = jiffies; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) d_set_d_op(dentry, &sf_dentry_ops); #else dentry->d_op = &sf_dentry_ops; #endif d_add(dentry, inode); return NULL; fail2: kfree(sf_new_i); fail1: kfree(path); fail0: return ERR_PTR(err); }
struct inode *affs_iget(struct super_block *sb, unsigned long ino) { struct affs_sb_info *sbi = AFFS_SB(sb); struct buffer_head *bh; struct affs_tail *tail; struct inode *inode; u32 block; u32 size; u32 prot; u16 id; inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; pr_debug("affs_iget(%lu)\n", inode->i_ino); block = inode->i_ino; bh = affs_bread(sb, block); if (!bh) { affs_warning(sb, "read_inode", "Cannot read block %d", block); goto bad_inode; } if (affs_checksum_block(sb, bh) || be32_to_cpu(AFFS_HEAD(bh)->ptype) != T_SHORT) { affs_warning(sb,"read_inode", "Checksum or type (ptype=%d) error on inode %d", AFFS_HEAD(bh)->ptype, block); goto bad_inode; } tail = AFFS_TAIL(sb, bh); prot = be32_to_cpu(tail->protect); inode->i_size = 0; set_nlink(inode, 1); inode->i_mode = 0; AFFS_I(inode)->i_extcnt = 1; AFFS_I(inode)->i_ext_last = ~1; AFFS_I(inode)->i_protect = prot; atomic_set(&AFFS_I(inode)->i_opencnt, 0); AFFS_I(inode)->i_blkcnt = 0; AFFS_I(inode)->i_lc = NULL; AFFS_I(inode)->i_lc_size = 0; AFFS_I(inode)->i_lc_shift = 0; AFFS_I(inode)->i_lc_mask = 0; AFFS_I(inode)->i_ac = NULL; AFFS_I(inode)->i_ext_bh = NULL; AFFS_I(inode)->mmu_private = 0; AFFS_I(inode)->i_lastalloc = 0; AFFS_I(inode)->i_pa_cnt = 0; if (sbi->s_flags & SF_SETMODE) inode->i_mode = sbi->s_mode; else inode->i_mode = prot_to_mode(prot); id = be16_to_cpu(tail->uid); if (id == 0 || sbi->s_flags & SF_SETUID) inode->i_uid = sbi->s_uid; else if (id == 0xFFFF && sbi->s_flags & SF_MUFS) i_uid_write(inode, 0); else i_uid_write(inode, id); id = be16_to_cpu(tail->gid); if (id == 0 || sbi->s_flags & SF_SETGID) inode->i_gid = sbi->s_gid; else if (id == 0xFFFF && sbi->s_flags & SF_MUFS) i_gid_write(inode, 0); else i_gid_write(inode, id); switch (be32_to_cpu(tail->stype)) { case ST_ROOT: inode->i_uid = sbi->s_uid; inode->i_gid = sbi->s_gid; /* fall through */ case ST_USERDIR: if (be32_to_cpu(tail->stype) == ST_USERDIR || sbi->s_flags & SF_SETMODE) { if (inode->i_mode & S_IRUSR) inode->i_mode |= S_IXUSR; if (inode->i_mode & S_IRGRP) inode->i_mode |= S_IXGRP; if (inode->i_mode & S_IROTH) inode->i_mode |= S_IXOTH; inode->i_mode |= S_IFDIR; } else inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR; /* Maybe it should be controlled by mount parameter? */ //inode->i_mode |= S_ISVTX; inode->i_op = &affs_dir_inode_operations; inode->i_fop = &affs_dir_operations; break; case ST_LINKDIR: #if 0 affs_warning(sb, "read_inode", "inode is LINKDIR"); goto bad_inode; #else inode->i_mode |= S_IFDIR; /* ... and leave ->i_op and ->i_fop pointing to empty */ break; #endif case ST_LINKFILE: affs_warning(sb, "read_inode", "inode is LINKFILE"); goto bad_inode; case ST_FILE: size = be32_to_cpu(tail->size); inode->i_mode |= S_IFREG; AFFS_I(inode)->mmu_private = inode->i_size = size; if (inode->i_size) { AFFS_I(inode)->i_blkcnt = (size - 1) / sbi->s_data_blksize + 1; AFFS_I(inode)->i_extcnt = (AFFS_I(inode)->i_blkcnt - 1) / sbi->s_hashsize + 1; } if (tail->link_chain) set_nlink(inode, 2); inode->i_mapping->a_ops = (sbi->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops; inode->i_op = &affs_file_inode_operations; inode->i_fop = &affs_file_operations; break; case ST_SOFTLINK: inode->i_mode |= S_IFLNK; inode->i_op = &affs_symlink_inode_operations; inode->i_data.a_ops = &affs_symlink_aops; break; } inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = (be32_to_cpu(tail->change.days) * (24 * 60 * 60) + be32_to_cpu(tail->change.mins) * 60 + be32_to_cpu(tail->change.ticks) / 50 + ((8 * 365 + 2) * 24 * 60 * 60)) + sys_tz.tz_minuteswest * 60; inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0; affs_brelse(bh); unlock_new_inode(inode); return inode; bad_inode: affs_brelse(bh); iget_failed(inode); return ERR_PTR(-EIO); }
struct inode *qnx4_iget(struct super_block *sb, unsigned long ino) { struct buffer_head *bh; struct qnx4_inode_entry *raw_inode; int block; struct qnx4_inode_entry *qnx4_inode; struct inode *inode; inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; qnx4_inode = qnx4_raw_inode(inode); inode->i_mode = 0; QNX4DEBUG((KERN_INFO "reading inode : [%d]\n", ino)); if (!ino) { // printk(KERN_ERR "qnx4: bad inode number on dev %s: %lu is " // "out of range\n", ; iget_failed(inode); return ERR_PTR(-EIO); } block = ino / QNX4_INODES_PER_BLOCK; if (!(bh = sb_bread(sb, block))) { // printk(KERN_ERR "qnx4: major problem: unable to read inode from dev " ; iget_failed(inode); return ERR_PTR(-EIO); } raw_inode = ((struct qnx4_inode_entry *) bh->b_data) + (ino % QNX4_INODES_PER_BLOCK); inode->i_mode = le16_to_cpu(raw_inode->di_mode); inode->i_uid = (uid_t)le16_to_cpu(raw_inode->di_uid); inode->i_gid = (gid_t)le16_to_cpu(raw_inode->di_gid); inode->i_nlink = le16_to_cpu(raw_inode->di_nlink); inode->i_size = le32_to_cpu(raw_inode->di_size); inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->di_mtime); inode->i_mtime.tv_nsec = 0; inode->i_atime.tv_sec = le32_to_cpu(raw_inode->di_atime); inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->di_ctime); inode->i_ctime.tv_nsec = 0; inode->i_blocks = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size); memcpy(qnx4_inode, raw_inode, QNX4_DIR_ENTRY_SIZE); if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; inode->i_mapping->a_ops = &qnx4_aops; qnx4_i(inode)->mmu_private = inode->i_size; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &qnx4_dir_inode_operations; inode->i_fop = &qnx4_dir_operations; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &qnx4_aops; qnx4_i(inode)->mmu_private = inode->i_size; } else { // printk(KERN_ERR "qnx4: bad inode %lu on dev %s\n", ; iget_failed(inode); brelse(bh); return ERR_PTR(-EIO); } brelse(bh); unlock_new_inode(inode); return inode; }
static struct inode *befs_iget(struct super_block *sb, unsigned long ino) { struct buffer_head *bh = NULL; befs_inode *raw_inode = NULL; befs_sb_info *befs_sb = BEFS_SB(sb); befs_inode_info *befs_ino = NULL; struct inode *inode; long ret = -EIO; befs_debug(sb, "---> %s inode = %lu", __func__, ino); inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; befs_ino = BEFS_I(inode); /* convert from vfs's inode number to befs's inode number */ befs_ino->i_inode_num = blockno2iaddr(sb, inode->i_ino); befs_debug(sb, " real inode number [%u, %hu, %hu]", befs_ino->i_inode_num.allocation_group, befs_ino->i_inode_num.start, befs_ino->i_inode_num.len); bh = befs_bread(sb, inode->i_ino); if (!bh) { befs_error(sb, "unable to read inode block - " "inode = %lu", inode->i_ino); goto unacquire_none; } raw_inode = (befs_inode *) bh->b_data; befs_dump_inode(sb, raw_inode); if (befs_check_inode(sb, raw_inode, inode->i_ino) != BEFS_OK) { befs_error(sb, "Bad inode: %lu", inode->i_ino); goto unacquire_bh; } inode->i_mode = (umode_t) fs32_to_cpu(sb, raw_inode->mode); /* * set uid and gid. But since current BeOS is single user OS, so * you can change by "uid" or "gid" options. */ inode->i_uid = befs_sb->mount_opts.use_uid ? befs_sb->mount_opts.uid : make_kuid(&init_user_ns, fs32_to_cpu(sb, raw_inode->uid)); inode->i_gid = befs_sb->mount_opts.use_gid ? befs_sb->mount_opts.gid : make_kgid(&init_user_ns, fs32_to_cpu(sb, raw_inode->gid)); set_nlink(inode, 1); /* * BEFS's time is 64 bits, but current VFS is 32 bits... * BEFS don't have access time. Nor inode change time. VFS * doesn't have creation time. * Also, the lower 16 bits of the last_modified_time and * create_time are just a counter to help ensure uniqueness * for indexing purposes. (PFD, page 54) */ inode->i_mtime.tv_sec = fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16; inode->i_mtime.tv_nsec = 0; /* lower 16 bits are not a time */ inode->i_ctime = inode->i_mtime; inode->i_atime = inode->i_mtime; befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num); befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent); befs_ino->i_attribute = fsrun_to_cpu(sb, raw_inode->attributes); befs_ino->i_flags = fs32_to_cpu(sb, raw_inode->flags); if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){ inode->i_size = 0; inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE; strlcpy(befs_ino->i_data.symlink, raw_inode->data.symlink, BEFS_SYMLINK_LEN); } else { int num_blks; befs_ino->i_data.ds = fsds_to_cpu(sb, &raw_inode->data.datastream); num_blks = befs_count_blocks(sb, &befs_ino->i_data.ds); inode->i_blocks = num_blks * (befs_sb->block_size / VFS_BLOCK_SIZE); inode->i_size = befs_ino->i_data.ds.size; } inode->i_mapping->a_ops = &befs_aops; if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &befs_dir_inode_operations; inode->i_fop = &befs_dir_operations; } else if (S_ISLNK(inode->i_mode)) { if (befs_ino->i_flags & BEFS_LONG_SYMLINK) inode->i_op = &befs_symlink_inode_operations; else inode->i_op = &befs_fast_symlink_inode_operations; } else { befs_error(sb, "Inode %lu is not a regular file, " "directory or symlink. THAT IS WRONG! BeFS has no " "on disk special files", inode->i_ino); goto unacquire_bh; } brelse(bh); befs_debug(sb, "<--- %s", __func__); unlock_new_inode(inode); return inode; unacquire_bh: brelse(bh); unacquire_none: iget_failed(inode); befs_debug(sb, "<--- %s - Bad inode", __func__); return ERR_PTR(ret); }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Function :me2fsGetVfsInode Input :struct super_block *sb < vfs super block > unsigned int ino < inode number for allocating new inode > Output :void Return :struct inode *inode < vfs inode > Description :allocate me2fs inode info, get locked vfs inode, read ext2 inode from a disk and fill them _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ struct inode *me2fsGetVfsInode( struct super_block *sb, unsigned int ino ) { struct inode *inode; struct me2fs_inode_info *mei; struct ext2_inode *ext2_inode; struct buffer_head *bh; uid_t i_uid; gid_t i_gid; int i; /* ------------------------------------------------------------------------ */ /* find an inode cache or allocate inode and lock it */ /* ------------------------------------------------------------------------ */ inode = iget_locked( sb, ino ); if( !inode ) { return( ERR_PTR( -ENOMEM ) ); } /* ------------------------------------------------------------------------ */ /* get an inode which has already existed */ /* ------------------------------------------------------------------------ */ if( !( inode->i_state & I_NEW ) ) { return( inode ); } /* ------------------------------------------------------------------------ */ /* read ext2 inode */ /* ------------------------------------------------------------------------ */ mei = ME2FS_I( inode ); ext2_inode = me2fsGetExt2Inode( inode->i_sb, ino, &bh ); if( IS_ERR( ext2_inode ) ) { iget_failed( inode ); return( ( struct inode* )( ext2_inode ) ); } dbgPrintExt2InodeInfo( ext2_inode ); /* ------------------------------------------------------------------------ */ /* set up vfs inode */ /* ------------------------------------------------------------------------ */ inode->i_mode = le16_to_cpu( ext2_inode->i_mode ); i_uid = ( uid_t )le16_to_cpu( ext2_inode->i_uid ); // low bytes i_gid = ( gid_t )le16_to_cpu( ext2_inode->i_gid ); // low bytes if( ME2FS_SB( sb )->s_mount_opt & EXT2_MOUNT_NO_UID32 ) { /* do nothing */ } else { i_uid |= le16_to_cpu( ext2_inode->osd2.linux2.l_i_uid_high ) << 16; i_gid |= le16_to_cpu( ext2_inode->osd2.linux2.l_i_gid_high ) << 16; } i_uid_write( inode, i_uid ); i_gid_write( inode, i_gid ); set_nlink( inode, le16_to_cpu( ext2_inode->i_links_count ) ); inode->i_size = le32_to_cpu( ext2_inode->i_size ); inode->i_atime.tv_sec = ( signed int )le32_to_cpu( ext2_inode->i_atime ); inode->i_ctime.tv_sec = ( signed int )le32_to_cpu( ext2_inode->i_ctime ); inode->i_mtime.tv_sec = ( signed int )le32_to_cpu( ext2_inode->i_mtime ); inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; inode->i_mtime.tv_nsec = 0; mei->i_dtime = le32_to_cpu( ext2_inode->i_dtime ); if( ( inode->i_nlink == 0 ) && ( ( inode->i_mode == 0 ) || ( mei->i_dtime ) ) ) { brelse( bh ); iget_failed( inode ); return( ERR_PTR( -ESTALE ) ); } inode->i_blocks = le32_to_cpu( ext2_inode->i_blocks ); mei->i_flags = le32_to_cpu( ext2_inode->i_flags ); mei->i_faddr = le32_to_cpu( ext2_inode->i_faddr ); mei->i_frag_no = ext2_inode->osd2.linux2.l_i_frag; mei->i_frag_size = ext2_inode->osd2.linux2.l_i_fsize; mei->i_file_acl = le32_to_cpu( ext2_inode->i_file_acl ); mei->i_dir_acl = 0; if( S_ISREG( inode->i_mode ) ) { /* use i_dir_acl higher 32 byte of file size */ inode->i_size |= ( ( __u64 )le32_to_cpu( ext2_inode->i_dir_acl ) ) << 32; } else { mei->i_dir_acl = le32_to_cpu( ext2_inode->i_dir_acl ); } mei->i_dtime = 0; inode->i_generation = le32_to_cpu( ext2_inode->i_generation ); mei->i_state = 0; mei->i_block_group = ( ino - 1 ) / ME2FS_SB( sb )->s_inodes_per_group; mei->i_dir_start_lookup = 0; for( i = 0 ; i < ME2FS_NR_BLOCKS ; i++ ) { mei->i_data[ i ] = ext2_inode->i_block[ i ]; } if( S_ISREG( inode->i_mode ) ) { } else if( S_ISDIR( inode->i_mode ) ) { DBGPRINT( "<ME2FS>get directory inode!\n" ); inode->i_fop = &me2fs_dir_operations; inode->i_op = &me2fs_dir_inode_operations; } else if( S_ISLNK( inode->i_mode ) ) { } else { } brelse( bh ); me2fsSetVfsInodeFlags( inode ); dbgPrintMe2fsInodeInfo( mei ); dbgPrintVfsInode( inode ); unlock_new_inode( inode ); return( inode ); }
/* * get a romfs inode based on its position in the image (which doubles as the * inode number) */ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos) { struct romfs_inode_info *inode; struct romfs_inode ri; struct inode *i; unsigned long nlen; unsigned nextfh; int ret; umode_t mode; /* we might have to traverse a chain of "hard link" file entries to get * to the actual file */ for (;;) { ret = romfs_dev_read(sb, pos, &ri, sizeof(ri)); if (ret < 0) goto error; /* XXX: do romfs_checksum here too (with name) */ nextfh = be32_to_cpu(ri.next); if ((nextfh & ROMFH_TYPE) != ROMFH_HRD) break; pos = be32_to_cpu(ri.spec) & ROMFH_MASK; } /* determine the length of the filename */ nlen = romfs_dev_strnlen(sb, pos + ROMFH_SIZE, ROMFS_MAXFN); if (IS_ERR_VALUE(nlen)) goto eio; /* get an inode for this image position */ i = iget_locked(sb, pos); if (!i) return ERR_PTR(-ENOMEM); if (!(i->i_state & I_NEW)) return i; /* precalculate the data offset */ inode = ROMFS_I(i); inode->i_metasize = (ROMFH_SIZE + nlen + 1 + ROMFH_PAD) & ROMFH_MASK; inode->i_dataoffset = pos + inode->i_metasize; i->i_nlink = 1; /* Hard to decide.. */ i->i_size = be32_to_cpu(ri.size); i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0; i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0; /* set up mode and ops */ mode = romfs_modemap[nextfh & ROMFH_TYPE]; switch (nextfh & ROMFH_TYPE) { case ROMFH_DIR: i->i_size = ROMFS_I(i)->i_metasize; i->i_op = &romfs_dir_inode_operations; i->i_fop = &romfs_dir_operations; if (nextfh & ROMFH_EXEC) mode |= S_IXUGO; break; case ROMFH_REG: i->i_fop = &romfs_ro_fops; i->i_data.a_ops = &romfs_aops; if (i->i_sb->s_mtd) i->i_data.backing_dev_info = i->i_sb->s_mtd->backing_dev_info; if (nextfh & ROMFH_EXEC) mode |= S_IXUGO; break; case ROMFH_SYM: i->i_op = &page_symlink_inode_operations; i->i_data.a_ops = &romfs_aops; mode |= S_IRWXUGO; break; default: /* depending on MBZ for sock/fifos */ nextfh = be32_to_cpu(ri.spec); init_special_inode(i, mode, MKDEV(nextfh >> 16, nextfh & 0xffff)); break; } i->i_mode = mode; unlock_new_inode(i); return i; eio: ret = -EIO; error: printk(KERN_ERR "ROMFS: read error for inode 0x%lx\n", pos); return ERR_PTR(ret); }
void lzfs_zfsctl_create(vfs_t *vfsp) { vnode_t *vp_zfsctl_dir = NULL, *vp_snap_dir = NULL; struct dentry *zfsctl_dir_dentry = NULL, *snap_dir_dentry = NULL; struct inode *inode_ctldir = NULL, *inode_snapdir = NULL; timestruc_t now; inode_ctldir = iget_locked(vfsp->vfs_super, LZFS_ZFSCTL_INO_ROOT); ASSERT(inode_ctldir != NULL); vp_zfsctl_dir = LZFS_ITOV(inode_ctldir); gethrestime(&now); ASSERT(inode_ctldir->i_state & I_NEW); mutex_enter(&vp_zfsctl_dir->v_lock); vp_zfsctl_dir->v_count = 1; VN_SET_VFS_TYPE_DEV(vp_zfsctl_dir, vfsp, VDIR, 0); bcopy(&now, &(vp_zfsctl_dir->v_inode.i_ctime), sizeof (timestruc_t)); bcopy(&now, &(vp_zfsctl_dir->v_inode.i_atime), sizeof (timestruc_t)); bcopy(&now,&(vp_zfsctl_dir->v_inode.i_mtime),sizeof (timestruc_t)); #ifdef HAVE_CRED_STRUCT inode_ctldir->i_uid = current->cred->uid; inode_ctldir->i_gid = current->cred->gid; #else inode_ctldir->i_uid = current->uid; inode_ctldir->i_gid = current->gid; #endif inode_ctldir->i_version = 1; inode_ctldir->i_mode |= (S_IFDIR | S_IRWXU); inode_ctldir->i_op = &zfsctl_dir_inode_operations; inode_ctldir->i_fop = &zfsctl_dir_file_operations; ASSERT(vfsp); inode_ctldir->i_sb = vfsp->vfs_super; ASSERT(vfsp->vfs_super); ASSERT(vfsp->vfs_super->s_root); unlock_new_inode(inode_ctldir); zfsctl_dir_dentry = d_alloc_name(vfsp->vfs_super->s_root, ZFS_CTLDIR_NAME); if (zfsctl_dir_dentry) { d_add(zfsctl_dir_dentry, LZFS_VTOI(vp_zfsctl_dir)); vfsp->zfsctl_dir_dentry = zfsctl_dir_dentry; } else { goto dentry_out; } set_zfsvfs_ctldir(vfsp->vfs_data, vp_zfsctl_dir); mutex_exit(&vp_zfsctl_dir->v_lock); inode_snapdir = iget_locked(vfsp->vfs_super, LZFS_ZFSCTL_INO_SNAPDIR); ASSERT(inode_snapdir != NULL); ASSERT(inode_snapdir->i_state & I_NEW); vp_snap_dir = LZFS_ITOV(inode_snapdir); gethrestime(&now); vfsp->vfs_snap_dir = vp_snap_dir; mutex_enter(&vp_snap_dir->v_lock); vp_snap_dir->v_count = 1; VN_SET_VFS_TYPE_DEV(vp_snap_dir, vfsp, VDIR, 0); bcopy(&now,&(vp_snap_dir->v_inode.i_ctime),sizeof (timestruc_t)); bcopy(&now,&(vp_snap_dir->v_inode.i_atime),sizeof (timestruc_t)); bcopy(&now,&(vp_snap_dir->v_inode.i_mtime),sizeof (timestruc_t)); #ifdef HAVE_CRED_STRUCT inode_snapdir->i_uid = current->cred->uid; inode_snapdir->i_gid = current->cred->gid; #else inode_snapdir->i_uid = current->uid; inode_snapdir->i_gid = current->gid; #endif inode_snapdir->i_version = 1; inode_snapdir->i_mode |= (S_IFDIR | S_IRWXU); inode_snapdir->i_op = &snap_dir_inode_operations; inode_snapdir->i_fop = &snap_dir_file_operations; inode_snapdir->i_sb = vfsp->vfs_super; unlock_new_inode(inode_snapdir); ASSERT(zfsctl_dir_dentry); snap_dir_dentry = d_alloc_name(zfsctl_dir_dentry, ZFS_SNAPDIR_NAME); if (snap_dir_dentry) { d_add(snap_dir_dentry, LZFS_VTOI(vp_snap_dir)); vfsp->snap_dir_dentry = snap_dir_dentry; mutex_exit(&vp_snap_dir->v_lock); } else { goto dentry_out; } return; dentry_out: // free vnode vn_free(vp_zfsctl_dir); ASSERT(0 && "TODO"); }
/** * This is called (by sf_read_super_[24|26] when vfs mounts the fs and * wants to read super_block. * * calls [sf_glob_alloc] to map the folder and allocate global * information structure. * * initializes [sb], initializes root inode and dentry. * * should respect [flags] */ static int sf_read_super_aux(struct super_block *sb, void *data, int flags) { int err; struct dentry *droot; struct inode *iroot; struct sf_inode_info *sf_i; struct sf_glob_info *sf_g; SHFLFSOBJINFO fsinfo; struct vbsf_mount_info_new *info; bool fInodePut = true; TRACE(); if (!data) { LogFunc(("no mount info specified\n")); return -EINVAL; } info = data; if (flags & MS_REMOUNT) { LogFunc(("remounting is not supported\n")); return -ENOSYS; } err = sf_glob_alloc(info, &sf_g); if (err) goto fail0; sf_i = kmalloc(sizeof (*sf_i), GFP_KERNEL); if (!sf_i) { err = -ENOMEM; LogRelFunc(("could not allocate memory for root inode info\n")); goto fail1; } sf_i->handle = SHFL_HANDLE_NIL; sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL); if (!sf_i->path) { err = -ENOMEM; LogRelFunc(("could not allocate memory for root inode path\n")); goto fail2; } sf_i->path->u16Length = 1; sf_i->path->u16Size = 2; sf_i->path->String.utf8[0] = '/'; sf_i->path->String.utf8[1] = 0; sf_i->force_reread = 0; err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0); if (err) { LogFunc(("could not stat root of share\n")); goto fail3; } sb->s_magic = 0xface; sb->s_blocksize = 1024; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3) /* Required for seek/sendfile. * * Must by less than or equal to INT64_MAX despite the fact that the * declaration of this variable is unsigned long long. See determination * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the * page cache into account and is the suggested limit. */ # if defined MAX_LFS_FILESIZE sb->s_maxbytes = MAX_LFS_FILESIZE; # else sb->s_maxbytes = 0x7fffffffffffffffULL; # endif #endif sb->s_op = &sf_super_ops; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) iroot = iget_locked(sb, 0); #else iroot = iget(sb, 0); #endif if (!iroot) { err = -ENOMEM; /* XXX */ LogFunc(("could not get root inode\n")); goto fail3; } if (sf_init_backing_dev(sf_g)) { err = -EINVAL; LogFunc(("could not init bdi\n")); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(iroot); #endif goto fail4; } sf_init_inode(sf_g, iroot, &fsinfo); SET_INODE_INFO(iroot, sf_i); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(iroot); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) droot = d_make_root(iroot); #else droot = d_alloc_root(iroot); #endif if (!droot) { err = -ENOMEM; /* XXX */ LogFunc(("d_alloc_root failed\n")); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) fInodePut = false; #endif goto fail5; } sb->s_root = droot; SET_GLOB_INFO(sb, sf_g); return 0; fail5: sf_done_backing_dev(sf_g); fail4: if (fInodePut) iput(iroot); fail3: kfree(sf_i->path); fail2: kfree(sf_i); fail1: sf_glob_free(sf_g); fail0: return err; }
struct inode *omfs_iget(struct super_block *sb, ino_t ino) { struct omfs_sb_info *sbi = OMFS_SB(sb); struct omfs_inode *oi; struct buffer_head *bh; u64 ctime; unsigned long nsecs; struct inode *inode; inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; bh = omfs_bread(inode->i_sb, ino); if (!bh) goto iget_failed; oi = (struct omfs_inode *)bh->b_data; /* check self */ if (ino != be64_to_cpu(oi->i_head.h_self)) goto fail_bh; inode->i_uid = sbi->s_uid; inode->i_gid = sbi->s_gid; ctime = be64_to_cpu(oi->i_ctime); nsecs = do_div(ctime, 1000) * 1000L; inode->i_atime.tv_sec = ctime; inode->i_mtime.tv_sec = ctime; inode->i_ctime.tv_sec = ctime; inode->i_atime.tv_nsec = nsecs; inode->i_mtime.tv_nsec = nsecs; inode->i_ctime.tv_nsec = nsecs; inode->i_mapping->a_ops = &omfs_aops; switch (oi->i_type) { case OMFS_DIR: inode->i_mode = S_IFDIR | (S_IRWXUGO & ~sbi->s_dmask); inode->i_op = &omfs_dir_inops; inode->i_fop = &omfs_dir_operations; inode->i_size = sbi->s_sys_blocksize; inc_nlink(inode); break; case OMFS_FILE: inode->i_mode = S_IFREG | (S_IRWXUGO & ~sbi->s_fmask); inode->i_fop = &omfs_file_operations; inode->i_size = be64_to_cpu(oi->i_size); break; } brelse(bh); unlock_new_inode(inode); return inode; fail_bh: brelse(bh); iget_failed: iget_failed(inode); return ERR_PTR(-EIO); }
struct inode *efs_iget(struct super_block *super, unsigned long ino) { int i, inode_index; dev_t device; u32 rdev; struct buffer_head *bh; struct efs_sb_info *sb = SUPER_INFO(super); struct efs_inode_info *in; efs_block_t block, offset; struct efs_dinode *efs_inode; struct inode *inode; inode = iget_locked(super, ino); if (IS_ERR(inode)) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; in = INODE_INFO(inode); /* ** EFS layout: ** ** | cylinder group | cylinder group | cylinder group ..etc ** |inodes|data |inodes|data |inodes|data ..etc ** ** work out the inode block index, (considering initially that the ** inodes are stored as consecutive blocks). then work out the block ** number of that inode given the above layout, and finally the ** offset of the inode within that block. */ inode_index = inode->i_ino / (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); block = sb->fs_start + sb->first_block + (sb->group_size * (inode_index / sb->inode_blocks)) + (inode_index % sb->inode_blocks); offset = (inode->i_ino % (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) * sizeof(struct efs_dinode); bh = sb_bread(inode->i_sb, block); if (!bh) { printk(KERN_WARNING "EFS: bread() failed at block %d\n", block); goto read_inode_error; } efs_inode = (struct efs_dinode *) (bh->b_data + offset); inode->i_mode = be16_to_cpu(efs_inode->di_mode); inode->i_nlink = be16_to_cpu(efs_inode->di_nlink); inode->i_uid = (uid_t)be16_to_cpu(efs_inode->di_uid); inode->i_gid = (gid_t)be16_to_cpu(efs_inode->di_gid); inode->i_size = be32_to_cpu(efs_inode->di_size); inode->i_atime.tv_sec = be32_to_cpu(efs_inode->di_atime); inode->i_mtime.tv_sec = be32_to_cpu(efs_inode->di_mtime); inode->i_ctime.tv_sec = be32_to_cpu(efs_inode->di_ctime); inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0; /* this is the number of blocks in the file */ if (inode->i_size == 0) { inode->i_blocks = 0; } else { inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1; } rdev = be16_to_cpu(efs_inode->di_u.di_dev.odev); if (rdev == 0xffff) { rdev = be32_to_cpu(efs_inode->di_u.di_dev.ndev); if (sysv_major(rdev) > 0xfff) device = 0; else device = MKDEV(sysv_major(rdev), sysv_minor(rdev)); } else device = old_decode_dev(rdev); /* get the number of extents for this object */ in->numextents = be16_to_cpu(efs_inode->di_numextents); in->lastextent = 0; /* copy the extents contained within the inode to memory */ for(i = 0; i < EFS_DIRECTEXTENTS; i++) { extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i])); if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) { printk(KERN_WARNING "EFS: extent %d has bad magic number in inode %lu\n", i, inode->i_ino); brelse(bh); goto read_inode_error; } } brelse(bh); #ifdef DEBUG printk(KERN_DEBUG "EFS: efs_iget(): inode %lu, extents %d, mode %o\n", inode->i_ino, in->numextents, inode->i_mode); #endif switch (inode->i_mode & S_IFMT) { case S_IFDIR: inode->i_op = &efs_dir_inode_operations; inode->i_fop = &efs_dir_operations; break; case S_IFREG: inode->i_fop = &generic_ro_fops; inode->i_data.a_ops = &efs_aops; break; case S_IFLNK: inode->i_op = &page_symlink_inode_operations; inode->i_data.a_ops = &efs_symlink_aops; break; case S_IFCHR: case S_IFBLK: case S_IFIFO: init_special_inode(inode, inode->i_mode, device); break; default: printk(KERN_WARNING "EFS: unsupported inode mode %o\n", inode->i_mode); goto read_inode_error; break; } unlock_new_inode(inode); return inode; read_inode_error: printk(KERN_WARNING "EFS: failed to read inode %lu\n", inode->i_ino); iget_failed(inode); return ERR_PTR(-EIO); }
struct inode *f2fs_iget(struct super_block *sb, unsigned long ino) { struct f2fs_sb_info *sbi = F2FS_SB(sb); struct inode *inode; int ret = 0; inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) { trace_f2fs_iget(inode); return inode; } if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi)) goto make_now; ret = do_read_inode(inode); if (ret) goto bad_inode; make_now: if (ino == F2FS_NODE_INO(sbi)) { inode->i_mapping->a_ops = &f2fs_node_aops; mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); } else if (ino == F2FS_META_INO(sbi)) { inode->i_mapping->a_ops = &f2fs_meta_aops; mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); } else if (S_ISREG(inode->i_mode)) { inode->i_op = &f2fs_file_inode_operations; inode->i_fop = &f2fs_file_operations; inode->i_mapping->a_ops = &f2fs_dblock_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &f2fs_dir_inode_operations; inode->i_fop = &f2fs_dir_operations; inode->i_mapping->a_ops = &f2fs_dblock_aops; inode_nohighmem(inode); } else if (S_ISLNK(inode->i_mode)) { if (f2fs_encrypted_inode(inode)) inode->i_op = &f2fs_encrypted_symlink_inode_operations; else inode->i_op = &f2fs_symlink_inode_operations; inode_nohighmem(inode); inode->i_mapping->a_ops = &f2fs_dblock_aops; } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { inode->i_op = &f2fs_special_inode_operations; init_special_inode(inode, inode->i_mode, inode->i_rdev); } else { ret = -EIO; goto bad_inode; } f2fs_set_inode_flags(inode); unlock_new_inode(inode); trace_f2fs_iget(inode); return inode; bad_inode: iget_failed(inode); trace_f2fs_iget_exit(inode, ret); return ERR_PTR(ret); }
struct inode *ubifs_iget(struct super_block *sb, unsigned long inum) { int err; union ubifs_key key; struct ubifs_ino_node *ino; struct ubifs_info *c = sb->s_fs_info; struct inode *inode; struct ubifs_inode *ui; int i; dbg_gen("inode %lu", inum); /* * U-Boot special handling of locked down inodes via recovery * e.g. ubifs_recover_size() */ for (i = 0; i < INODE_LOCKED_MAX; i++) { /* * Exit on last entry (NULL), inode not found in list */ if (inodes_locked_down[i] == NULL) break; if (inodes_locked_down[i]->i_ino == inum) { /* * We found the locked down inode in our array, * so just return this pointer instead of creating * a new one. */ return inodes_locked_down[i]; } } inode = iget_locked(sb, inum); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; ui = ubifs_inode(inode); ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); if (!ino) { err = -ENOMEM; goto out; } ino_key_init(c, &key, inode->i_ino); err = ubifs_tnc_lookup(c, &key, ino); if (err) goto out_ino; inode->i_flags |= (S_NOCMTIME | S_NOATIME); inode->i_nlink = le32_to_cpu(ino->nlink); inode->i_uid = le32_to_cpu(ino->uid); inode->i_gid = le32_to_cpu(ino->gid); inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec); inode->i_atime.tv_nsec = le32_to_cpu(ino->atime_nsec); inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec); inode->i_mtime.tv_nsec = le32_to_cpu(ino->mtime_nsec); inode->i_ctime.tv_sec = (int64_t)le64_to_cpu(ino->ctime_sec); inode->i_ctime.tv_nsec = le32_to_cpu(ino->ctime_nsec); inode->i_mode = le32_to_cpu(ino->mode); inode->i_size = le64_to_cpu(ino->size); ui->data_len = le32_to_cpu(ino->data_len); ui->flags = le32_to_cpu(ino->flags); ui->compr_type = le16_to_cpu(ino->compr_type); ui->creat_sqnum = le64_to_cpu(ino->creat_sqnum); ui->synced_i_size = ui->ui_size = inode->i_size; err = validate_inode(c, inode); if (err) goto out_invalid; if ((inode->i_mode & S_IFMT) == S_IFLNK) { if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) { err = 12; goto out_invalid; } ui->data = kmalloc(ui->data_len + 1, GFP_NOFS); if (!ui->data) { err = -ENOMEM; goto out_ino; } memcpy(ui->data, ino->data, ui->data_len); ((char *)ui->data)[ui->data_len] = '\0'; } kfree(ino); inode->i_state &= ~(I_LOCK | I_NEW); return inode; out_invalid: ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err); dbg_dump_node(c, ino); dbg_dump_inode(c, inode); err = -EINVAL; out_ino: kfree(ino); out: ubifs_err("failed to read inode %lu, error %d", inode->i_ino, err); return ERR_PTR(err); }
/** * This should allocate memory for sf_inode_info, compute a unique inode * number, get an inode from vfs, initialize inode info, instantiate * dentry. * * @param parent inode entry of the directory * @param dentry directory cache entry * @param path path name * @param info file information * @param handle handle * @returns 0 on success, Linux error code otherwise */ static int sf_instantiate(struct inode *parent, struct dentry *dentry, SHFLSTRING *path, PSHFLFSOBJINFO info, SHFLHANDLE handle) { int err; ino_t ino; struct inode *inode; struct sf_inode_info *sf_new_i; struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb); TRACE(); BUG_ON(!sf_g); sf_new_i = kmalloc(sizeof(*sf_new_i), GFP_KERNEL); if (!sf_new_i) { LogRelFunc(("could not allocate inode info.\n")); err = -ENOMEM; goto fail0; } ino = iunique(parent->i_sb, 1); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) inode = iget_locked(parent->i_sb, ino); #else inode = iget(parent->i_sb, ino); #endif if (!inode) { LogFunc(("iget failed\n")); err = -ENOMEM; goto fail1; } sf_init_inode(sf_g, inode, info); sf_new_i->path = path; SET_INODE_INFO(inode, sf_new_i); dentry->d_time = jiffies; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) d_set_d_op(dentry, &sf_dentry_ops); #else dentry->d_op = &sf_dentry_ops; #endif sf_new_i->force_restat = 1; sf_new_i->force_reread = 0; d_instantiate(dentry, inode); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(inode); #endif /* Store this handle if we leave the handle open. */ sf_new_i->handle = handle; return 0; fail1: kfree(sf_new_i); fail0: return err; }
struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { const unsigned char *name = dentry->d_name.name; unsigned len = dentry->d_name.len; struct quad_buffer_head qbh; struct hpfs_dirent *de; ino_t ino; int err; struct inode *result = NULL; struct hpfs_inode_info *hpfs_result; hpfs_lock(dir->i_sb); if ((err = hpfs_chk_name(name, &len))) { if (err == -ENAMETOOLONG) { hpfs_unlock(dir->i_sb); return ERR_PTR(-ENAMETOOLONG); } goto end_add; } /* * '.' and '..' will never be passed here. */ de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, NULL, &qbh); /* * This is not really a bailout, just means file not found. */ if (!de) goto end; /* * Get inode number, what we're after. */ ino = de->fnode; /* * Go find or make an inode. */ result = iget_locked(dir->i_sb, ino); if (!result) { hpfs_error(dir->i_sb, "hpfs_lookup: can't get inode"); goto bail1; } if (result->i_state & I_NEW) { hpfs_init_inode(result); if (de->directory) hpfs_read_inode(result); else if (de->ea_size && hpfs_sb(dir->i_sb)->sb_eas) hpfs_read_inode(result); else { result->i_mode |= S_IFREG; result->i_mode &= ~0111; result->i_op = &hpfs_file_iops; result->i_fop = &hpfs_file_ops; result->i_nlink = 1; } unlock_new_inode(result); } hpfs_result = hpfs_i(result); if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino; hpfs_decide_conv(result, name, len); if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) { hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures"); goto bail1; } /* * Fill in the info from the directory if this is a newly created * inode. */ if (!result->i_ctime.tv_sec) { if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, de->creation_date))) result->i_ctime.tv_sec = 1; result->i_ctime.tv_nsec = 0; result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, de->write_date); result->i_mtime.tv_nsec = 0; result->i_atime.tv_sec = local_to_gmt(dir->i_sb, de->read_date); result->i_atime.tv_nsec = 0; hpfs_result->i_ea_size = de->ea_size; if (!hpfs_result->i_ea_mode && de->read_only) result->i_mode &= ~0222; if (!de->directory) { if (result->i_size == -1) { result->i_size = de->file_size; result->i_data.a_ops = &hpfs_aops; hpfs_i(result)->mmu_private = result->i_size; /* * i_blocks should count the fnode and any anodes. * We count 1 for the fnode and don't bother about * anodes -- the disk heads are on the directory band * and we want them to stay there. */ result->i_blocks = 1 + ((result->i_size + 511) >> 9); } } }
struct inode *bfs_iget(struct super_block *sb, unsigned long ino) { struct bfs_inode *di; struct inode *inode; struct buffer_head *bh; int block, off; inode = iget_locked(sb, ino); if (IS_ERR(inode)) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) { printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino); goto error; } block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; bh = sb_bread(inode->i_sb, block); if (!bh) { printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino); goto error; } off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; di = (struct bfs_inode *)bh->b_data + off; inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode); if (le32_to_cpu(di->i_vtype) == BFS_VDIR) { inode->i_mode |= S_IFDIR; inode->i_op = &bfs_dir_inops; inode->i_fop = &bfs_dir_operations; } else if (le32_to_cpu(di->i_vtype) == BFS_VREG) { inode->i_mode |= S_IFREG; inode->i_op = &bfs_file_inops; inode->i_fop = &bfs_file_operations; inode->i_mapping->a_ops = &bfs_aops; } BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock); BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock); BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); inode->i_uid = le32_to_cpu(di->i_uid); inode->i_gid = le32_to_cpu(di->i_gid); set_nlink(inode, le32_to_cpu(di->i_nlink)); inode->i_size = BFS_FILESIZE(di); inode->i_blocks = BFS_FILEBLOCKS(di); inode->i_atime.tv_sec = le32_to_cpu(di->i_atime); inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime); inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime); inode->i_atime.tv_nsec = 0; inode->i_mtime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; brelse(bh); unlock_new_inode(inode); return inode; error: iget_failed(inode); return ERR_PTR(-EIO); }
static struct dentry *proc_ns_get_dentry(struct super_block *sb, struct task_struct *task, const struct proc_ns_operations *ns_ops) { struct dentry *dentry, *result; struct inode *inode; struct proc_inode *ei; struct qstr qname = { .name = "", }; void *ns; ns = ns_ops->get(task); if (!ns) return ERR_PTR(-ENOENT); dentry = d_alloc_pseudo(sb, &qname); if (!dentry) { ns_ops->put(ns); return ERR_PTR(-ENOMEM); } inode = iget_locked(sb, ns_ops->inum(ns)); if (!inode) { dput(dentry); ns_ops->put(ns); return ERR_PTR(-ENOMEM); } ei = PROC_I(inode); if (inode->i_state & I_NEW) { inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_op = &ns_inode_operations; inode->i_mode = S_IFREG | S_IRUGO; inode->i_fop = &ns_file_operations; ei->ns.ns_ops = ns_ops; ei->ns.ns = ns; unlock_new_inode(inode); } else { ns_ops->put(ns); } d_set_d_op(dentry, &ns_dentry_operations); result = d_instantiate_unique(dentry, inode); if (result) { dput(dentry); dentry = result; } return dentry; } static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; struct super_block *sb = inode->i_sb; struct proc_inode *ei = PROC_I(inode); struct task_struct *task; struct path ns_path; void *error = ERR_PTR(-EACCES); task = get_proc_task(inode); if (!task) goto out; if (!ptrace_may_access(task, PTRACE_MODE_READ)) goto out_put_task; ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops); if (IS_ERR(ns_path.dentry)) { error = ERR_CAST(ns_path.dentry); goto out_put_task; } ns_path.mnt = mntget(nd->path.mnt); nd_jump_link(nd, &ns_path); error = NULL; out_put_task: put_task_struct(task); out: return error; } static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen) { struct inode *inode = dentry->d_inode; struct proc_inode *ei = PROC_I(inode); const struct proc_ns_operations *ns_ops = ei->ns.ns_ops; struct task_struct *task; void *ns; char name[50]; int len = -EACCES; task = get_proc_task(inode); if (!task) goto out; if (!ptrace_may_access(task, PTRACE_MODE_READ)) goto out_put_task; len = -ENOENT; ns = ns_ops->get(task); if (!ns) goto out_put_task; snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns)); len = strlen(name); if (len > buflen) len = buflen; if (copy_to_user(buffer, name, len)) len = -EFAULT; ns_ops->put(ns); out_put_task: put_task_struct(task); out: return len; } static const struct inode_operations proc_ns_link_inode_operations = { .readlink = proc_ns_readlink, .follow_link = proc_ns_follow_link, .setattr = proc_setattr, }; static int proc_ns_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr) { const struct proc_ns_operations *ns_ops = ptr; struct inode *inode; struct proc_inode *ei; inode = proc_pid_make_inode(dir->i_sb, task); if (!inode) goto out; ei = PROC_I(inode); inode->i_mode = S_IFLNK|S_IRWXUGO; inode->i_op = &proc_ns_link_inode_operations; ei->ns.ns_ops = ns_ops; d_set_d_op(dentry, &pid_dentry_operations); d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ if (pid_revalidate(dentry, 0)) return 0; out: return -ENOENT; } static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx) { struct task_struct *task = get_proc_task(file_inode(file)); const struct proc_ns_operations **entry, **last; if (!task) return -ENOENT; if (!dir_emit_dots(file, ctx)) goto out; if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries)) goto out; entry = ns_entries + (ctx->pos - 2); last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; while (entry <= last) { const struct proc_ns_operations *ops = *entry; if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name), proc_ns_instantiate, task, ops)) break; ctx->pos++; entry++; } out: put_task_struct(task); return 0; } const struct file_operations proc_ns_dir_operations = { .read = generic_read_dir, .iterate = proc_ns_dir_readdir, }; static struct dentry *proc_ns_dir_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { int error; struct task_struct *task = get_proc_task(dir); const struct proc_ns_operations **entry, **last; unsigned int len = dentry->d_name.len; error = -ENOENT; if (!task) goto out_no_task; last = &ns_entries[ARRAY_SIZE(ns_entries)]; for (entry = ns_entries; entry < last; entry++) { if (strlen((*entry)->name) != len) continue; if (!memcmp(dentry->d_name.name, (*entry)->name, len)) break; } if (entry == last) goto out; error = proc_ns_instantiate(dir, dentry, task, *entry); out: put_task_struct(task); out_no_task: return ERR_PTR(error); }