static int do_load_em86(struct linux_binprm *bprm,struct pt_regs *regs) { char *cp, *interp, *i_name, *i_arg; int retval; struct elfhdr elf_ex; uid_t x86_uid; gid_t x86_gid; /* Make sure this is a Linux/Intel ELF executable... */ elf_ex = *((struct elfhdr *)bprm->buf); if (elf_ex.e_ident[0] != 0x7f || strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) { return -ENOEXEC; } /* First of all, some simple consistency checks */ if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || (!((elf_ex.e_machine == EM_386) || (elf_ex.e_machine == EM_486))) || (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || !bprm->inode->i_op->default_file_ops->mmap)){ return -ENOEXEC; } bprm->sh_bang++; /* Well, the bang-shell is implicit... */ iput(bprm->inode); bprm->dont_iput = 1; /* Unlike in the script case, we don't have to do any hairy * parsing to find our interpreter... it's hardcoded! */ interp = EM86_INTERP; i_name = EM86_I_NAME; i_arg = NULL; /* We reserve the right to add an arg later */ /* * Splice in (1) the interpreter's name for argv[0] * (2) (optional) argument to interpreter * (3) filename of emulated file (replace argv[0]) * * This is done in reverse order, because of how the * user environment and arguments are stored. */ remove_arg_zero(bprm); bprm->p = copy_strings(1, &bprm->filename, bprm->page, bprm->p, 2); bprm->argc++; if (i_arg) { bprm->p = copy_strings(1, &i_arg, bprm->page, bprm->p, 2); bprm->argc++; } bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; if (!bprm->p) return -E2BIG; /* * OK, now restart the process with the interpreter's inode. * Note that we use open_namei() as the name is now in kernel * space, and we don't need to copy it. */ retval = open_namei(interp, 0, 0, &bprm->inode, NULL); if (retval) return retval; bprm->dont_iput=0; /* Remember the uid/gid that was set by this executable */ x86_uid = bprm->e_uid; x86_gid = bprm->e_gid; retval=prepare_binprm(bprm); if(retval<0) return retval; /* ...so that we may propagate them to em86 */ bprm->e_uid = x86_uid; bprm->e_gid = x86_gid; current->personality = PER_LINUX_EM86; return search_binary_handler(bprm,regs); }
// Common idiom: unlock, then put. void iunlockput(struct inode *ip) { iunlock(ip); iput(ip); }
static int reiserfs_symlink(struct inode *parent_dir, struct dentry *dentry, const char *symname) { int retval; struct inode *inode; char *name; int item_len; struct reiserfs_transaction_handle th; struct reiserfs_security_handle security; int mode = S_IFLNK | S_IRWXUGO; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb)); dquot_initialize(parent_dir); if (!(inode = new_inode(parent_dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, parent_dir, mode); retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name, &security); if (retval < 0) { drop_new_inode(inode); return retval; } jbegin_count += retval; reiserfs_write_lock(parent_dir->i_sb); item_len = ROUND_UP(strlen(symname)); if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) { retval = -ENAMETOOLONG; drop_new_inode(inode); goto out_failed; } name = kmalloc(item_len, GFP_NOFS); if (!name) { drop_new_inode(inode); retval = -ENOMEM; goto out_failed; } memcpy(name, symname, strlen(symname)); padd_item(name, item_len, strlen(symname)); retval = journal_begin(&th, parent_dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); kfree(name); goto out_failed; } retval = reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname), dentry, inode, &security); kfree(name); if (retval) { /* reiserfs_new_inode iputs for us */ goto out_failed; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(parent_dir); inode->i_op = &reiserfs_symlink_inode_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; // must be sure this inode is written with this transaction // //reiserfs_update_sd (&th, inode, READ_BLOCKS); retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; inode->i_nlink--; reiserfs_update_sd(&th, inode); err = journal_end(&th, parent_dir->i_sb, jbegin_count); if (err) retval = err; unlock_new_inode(inode); iput(inode); goto out_failed; } d_instantiate(dentry, inode); unlock_new_inode(inode); retval = journal_end(&th, parent_dir->i_sb, jbegin_count); out_failed: reiserfs_write_unlock(parent_dir->i_sb); return retval; }
/* * Any time a mark is getting freed we end up here. * The caller had better be holding a reference to this mark so we don't actually * do the final put under the mark->lock */ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, struct fsnotify_group *group) { struct inode *inode = NULL; BUG_ON(!mutex_is_locked(&group->mark_mutex)); spin_lock(&mark->lock); /* something else already called this function on this mark */ if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) { spin_unlock(&mark->lock); return; } mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { inode = mark->inode; fsnotify_destroy_inode_mark(mark); } else if (mark->flags & FSNOTIFY_MARK_FLAG_VFSMOUNT) fsnotify_destroy_vfsmount_mark(mark); else if (mark->flags & FSNOTIFY_MARK_FLAG_TASK) { fsnotify_destroy_task_mark(mark); } else BUG(); list_del_init(&mark->g_list); spin_unlock(&mark->lock); if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED)) iput(inode); /* release lock temporarily */ mutex_unlock(&group->mark_mutex); spin_lock(&destroy_lock); list_add(&mark->g_list, &destroy_list); spin_unlock(&destroy_lock); wake_up(&destroy_waitq); /* * We don't necessarily have a ref on mark from caller so the above destroy * may have actually freed it, unless this group provides a 'freeing_mark' * function which must be holding a reference. */ /* * Some groups like to know that marks are being freed. This is a * callback to the group function to let it know that this mark * is being freed. */ if (group->ops->freeing_mark) group->ops->freeing_mark(mark, group); /* * __fsnotify_update_child_dentry_flags(inode); * * I really want to call that, but we can't, we have no idea if the inode * still exists the second we drop the mark->lock. * * The next time an event arrive to this inode from one of it's children * __fsnotify_parent will see that the inode doesn't care about it's * children and will update all of these flags then. So really this * is just a lazy update (and could be a perf win...) */ atomic_dec(&group->num_marks); mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); }
/* * There is no need to lock the wrapfs_super_info's rwsem as there is no * way anyone can have a reference to the superblock at this point in time. */ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent) { int err = 0; struct super_block *lower_sb; struct path lower_path; char *dev_name = (char *) raw_data; struct inode *inode; if (!dev_name) { printk(KERN_ERR "wrapfs: read_super: missing dev_name argument\n"); err = -EINVAL; goto out; } /* parse lower path */ err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &lower_path); if (err) { printk(KERN_ERR "wrapfs: error accessing " "lower directory '%s'\n", dev_name); goto out; } /* allocate superblock private data */ sb->s_fs_info = kzalloc(sizeof(struct wrapfs_sb_info), GFP_KERNEL); if (!WRAPFS_SB(sb)) { printk(KERN_CRIT "wrapfs: read_super: out of memory\n"); err = -ENOMEM; goto out_free; } /* set the lower superblock field of upper superblock */ lower_sb = lower_path.dentry->d_sb; atomic_inc(&lower_sb->s_active); wrapfs_set_lower_super(sb, lower_sb); /* inherit maxbytes from lower file system */ sb->s_maxbytes = lower_sb->s_maxbytes; /* * Our c/m/atime granularity is 1 ns because we may stack on file * systems whose granularity is as good. */ sb->s_time_gran = 1; sb->s_op = &wrapfs_sops; /* get a new inode and allocate our root dentry */ inode = wrapfs_iget(sb, lower_path.dentry->d_inode); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out_sput; } sb->s_root = d_alloc_root(inode); if (!sb->s_root) { err = -ENOMEM; goto out_iput; } d_set_d_op(sb->s_root, &wrapfs_dops); /* link the upper and lower dentries */ sb->s_root->d_fsdata = NULL; err = new_dentry_private_data(sb->s_root); if (err) goto out_freeroot; /* if get here: cannot have error */ /* set the lower dentries for s_root */ wrapfs_set_lower_path(sb->s_root, &lower_path); /* * No need to call interpose because we already have a positive * dentry, which was instantiated by d_alloc_root. Just need to * d_rehash it. */ d_rehash(sb->s_root); if (!silent) printk(KERN_INFO "wrapfs: mounted on top of %s type %s\n", dev_name, lower_sb->s_type->name); goto out; /* all is well */ /* no longer needed: free_dentry_private_data(sb->s_root); */ out_freeroot: dput(sb->s_root); out_iput: iput(inode); out_sput: /* drop refs we took earlier */ atomic_dec(&lower_sb->s_active); kfree(WRAPFS_SB(sb)); sb->s_fs_info = NULL; out_free: path_put(&lower_path); out: return err; }
static int recover_dentry(struct inode *inode, struct page *ipage) { struct f2fs_inode *raw_inode = F2FS_INODE(ipage); nid_t pino = le32_to_cpu(raw_inode->i_pino); struct f2fs_dir_entry *de; struct qstr name; struct page *page; struct inode *dir, *einode; int err = 0; dir = f2fs_iget(inode->i_sb, pino); if (IS_ERR(dir)) { err = PTR_ERR(dir); goto out; } name.len = le32_to_cpu(raw_inode->i_namelen); name.name = raw_inode->i_name; if (unlikely(name.len > F2FS_NAME_LEN)) { WARN_ON(1); err = -ENAMETOOLONG; goto out_err; } retry: de = f2fs_find_entry(dir, &name, &page, 0); if (de && inode->i_ino == le32_to_cpu(de->ino)) { clear_inode_flag(F2FS_I(inode), FI_INC_LINK); goto out_unmap_put; } if (de) { einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); if (IS_ERR(einode)) { WARN_ON(1); err = PTR_ERR(einode); if (err == -ENOENT) err = -EEXIST; goto out_unmap_put; } err = acquire_orphan_inode(F2FS_I_SB(inode)); if (err) { iput(einode); goto out_unmap_put; } f2fs_delete_entry(de, page, dir, einode); iput(einode); goto retry; } err = __f2fs_add_link(dir, &name, inode); if (err) goto out_err; if (is_inode_flag_set(F2FS_I(dir), FI_DELAY_IPUT)) { iput(dir); } else { add_dirty_dir_inode(dir); set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT); } goto out; out_unmap_put: f2fs_dentry_kunmap(dir, page); f2fs_put_page(page, 0); out_err: iput(dir); out: f2fs_msg(inode->i_sb, KERN_NOTICE, "%s: ino = %x, name = %s, dir = %lx, err = %d", __func__, ino_of_node(ipage), raw_inode->i_name, IS_ERR(dir) ? 0 : dir->i_ino, err); return err; }
int parse_rock_ridge_inode(struct iso_directory_record * de, struct inode * inode){ int len; unsigned char * chr; int symlink_len = 0; CONTINUE_DECLS; if (!inode->i_sb->u.isofs_sb.s_rock) return 0; SETUP_ROCK_RIDGE(de, chr, len); repeat: { int cnt, sig; struct inode * reloc; struct rock_ridge * rr; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = (chr[0] << 8) + chr[1]; chr += rr->len; len -= rr->len; switch(sig){ case SIG('R','R'): if((rr->u.RR.flags[0] & (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out; break; case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','E'): CHECK_CE; break; case SIG('E','R'): inode->i_sb->u.isofs_sb.s_rock = 1; printk(KERN_DEBUG"ISO 9660 Extensions: "); { int p; for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]); }; printk("\n"); break; case SIG('P','X'): inode->i_mode = isonum_733(rr->u.PX.mode); inode->i_nlink = isonum_733(rr->u.PX.n_links); inode->i_uid = isonum_733(rr->u.PX.uid); inode->i_gid = isonum_733(rr->u.PX.gid); break; case SIG('P','N'): { int high, low; high = isonum_733(rr->u.PN.dev_high); low = isonum_733(rr->u.PN.dev_low); /* * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4, * then the high field is unused, and the device number is completely * stored in the low field. Some writers may ignore this subtlety, * and as a result we test to see if the entire device number is * stored in the low field, and use that. */ if((low & ~0xff) && high == 0) { inode->i_rdev = MKDEV(low >> 8, low & 0xff); } else { inode->i_rdev = MKDEV(high, low); } }; break; case SIG('T','F'): { struct stamp *times = (struct stamp *) &(rr->u.TF.__times); /* Some RRIP writers incorrectly place ctime in the TF_CREATE field. Try to handle this correctly for either case. */ cnt = 0; /* Rock ridge never appears on a High Sierra disk */ if(rr->u.TF.flags & TF_CREATE) inode->i_ctime = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_ATTRIBUTES) inode->i_ctime = iso_date(times[cnt++].time, 0); break; } case SIG('S','L'): {int slen; struct SL_component * slp; struct SL_component * oldslp; slen = rr->len - 5; slp = (struct SL_component *)&rr->u.SL.__link; inode->i_size = symlink_len; while (slen > 1){ rootflag = 0; switch(slp->flags &~1){ case 0: inode->i_size += slp->len; break; case 2: inode->i_size += 1; break; case 4: inode->i_size += 2; break; case 8: rootflag = 1; inode->i_size += 1; break; default: printk("Symlink component flag not implemented\n"); }; slen -= slp->len + 2; oldslp = slp; slp = (struct SL_component *) (((char *) slp) + slp->len + 2); if(slen < 2) { if( ((rr->u.SL.flags & 1) != 0) && ((oldslp->flags & 1) == 0) ) inode->i_size += 1; break; } /* * If this component record isn't continued, then append a '/'. */ if( (!rootflag) && ((oldslp->flags & 1) == 0) ) inode->i_size += 1; } } symlink_len = inode->i_size; break; case SIG('R','E'): printk("Attempt to read inode for relocated directory\n"); goto out; case SIG('C','L'): #ifdef DEBUG printk("RR CL (%x)\n",inode->i_ino); #endif inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location); reloc = iget(inode->i_sb, (inode->u.isofs_i.i_first_extent << inode -> i_sb -> u.isofs_sb.s_log_zone_size)); if (!reloc) goto out; inode->i_mode = reloc->i_mode; inode->i_nlink = reloc->i_nlink; inode->i_uid = reloc->i_uid; inode->i_gid = reloc->i_gid; inode->i_rdev = reloc->i_rdev; inode->i_size = reloc->i_size; inode->i_atime = reloc->i_atime; inode->i_ctime = reloc->i_ctime; inode->i_mtime = reloc->i_mtime; iput(reloc); break; default: break; } };
void *ns_get_path(struct path *path, struct task_struct *task, const struct proc_ns_operations *ns_ops) { struct vfsmount *mnt = mntget(nsfs_mnt); struct qstr qname = { .name = "", }; struct dentry *dentry; struct inode *inode; struct ns_common *ns; unsigned long d; again: ns = ns_ops->get(task); if (!ns) { mntput(mnt); return ERR_PTR(-ENOENT); } rcu_read_lock(); d = atomic_long_read(&ns->stashed); if (!d) goto slow; dentry = (struct dentry *)d; if (!lockref_get_not_dead(&dentry->d_lockref)) goto slow; rcu_read_unlock(); ns_ops->put(ns); got_it: path->mnt = mnt; path->dentry = dentry; return NULL; slow: rcu_read_unlock(); inode = new_inode_pseudo(mnt->mnt_sb); if (!inode) { ns_ops->put(ns); mntput(mnt); return ERR_PTR(-ENOMEM); } inode->i_ino = ns->inum; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_flags |= S_IMMUTABLE; inode->i_mode = S_IFREG | S_IRUGO; inode->i_fop = &ns_file_operations; inode->i_private = ns; dentry = d_alloc_pseudo(mnt->mnt_sb, &qname); if (!dentry) { iput(inode); mntput(mnt); return ERR_PTR(-ENOMEM); } d_instantiate(dentry, inode); dentry->d_fsdata = (void *)ns_ops; d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry); if (d) { d_delete(dentry); /* make sure ->d_prune() does nothing */ dput(dentry); cpu_relax(); goto again; } goto got_it; } int ns_get_name(char *buf, size_t size, struct task_struct *task, const struct proc_ns_operations *ns_ops) { struct ns_common *ns; int res = -ENOENT; ns = ns_ops->get(task); if (ns) { res = snprintf(buf, size, "%s:[%u]", ns_ops->name, ns->inum); ns_ops->put(ns); } return res; } struct file *proc_ns_fget(int fd) { struct file *file; file = fget(fd); if (!file) return ERR_PTR(-EBADF); if (file->f_op != &ns_file_operations) goto out_invalid; return file; out_invalid: fput(file); return ERR_PTR(-EINVAL); } static const struct super_operations nsfs_ops = { .statfs = simple_statfs, .evict_inode = nsfs_evict, }; static struct dentry *nsfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { return mount_pseudo(fs_type, "nsfs:", &nsfs_ops, &ns_dentry_operations, NSFS_MAGIC); } static struct file_system_type nsfs = { .name = "nsfs", .mount = nsfs_mount, .kill_sb = kill_anon_super, }; void __init nsfs_init(void) { nsfs_mnt = kern_mount(&nsfs); if (IS_ERR(nsfs_mnt)) panic("can't set nsfs up\n"); nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER; }
static int squashfs_fill_super(struct super_block *sb, void *data, int silent) { struct squashfs_sb_info *msblk; struct squashfs_super_block *sblk = NULL; struct inode *root; long long root_inode; unsigned short flags; unsigned int fragments; u64 lookup_table_start, xattr_id_table_start, next_table; int err; TRACE("Entered squashfs_fill_superblock\n"); sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL); if (sb->s_fs_info == NULL) { ERROR("Failed to allocate squashfs_sb_info\n"); return -ENOMEM; } msblk = sb->s_fs_info; msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE); msblk->devblksize_log2 = ffz(~msblk->devblksize); mutex_init(&msblk->meta_index_mutex); /* * msblk->bytes_used is checked in squashfs_read_table to ensure reads * are not beyond filesystem end. But as we're using * squashfs_read_table here to read the superblock (including the value * of bytes_used) we need to set it to an initial sensible dummy value */ msblk->bytes_used = sizeof(*sblk); sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk)); if (IS_ERR(sblk)) { ERROR("unable to read squashfs_super_block\n"); err = PTR_ERR(sblk); sblk = NULL; goto failed_mount; } err = -EINVAL; /* Check it is a SQUASHFS superblock */ sb->s_magic = le32_to_cpu(sblk->s_magic); if (sb->s_magic != SQUASHFS_MAGIC) { if (!silent) ERROR("Can't find a SQUASHFS superblock on %pg\n", sb->s_bdev); goto failed_mount; } /* Check the MAJOR & MINOR versions and lookup compression type */ msblk->decompressor = supported_squashfs_filesystem( le16_to_cpu(sblk->s_major), le16_to_cpu(sblk->s_minor), le16_to_cpu(sblk->compression)); if (msblk->decompressor == NULL) goto failed_mount; /* Check the filesystem does not extend beyond the end of the block device */ msblk->bytes_used = le64_to_cpu(sblk->bytes_used); if (msblk->bytes_used < 0 || msblk->bytes_used > i_size_read(sb->s_bdev->bd_inode)) goto failed_mount; /* Check block size for sanity */ msblk->block_size = le32_to_cpu(sblk->block_size); if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE) goto failed_mount; /* * Check the system page size is not larger than the filesystem * block size (by default 128K). This is currently not supported. */ if (PAGE_SIZE > msblk->block_size) { ERROR("Page size > filesystem block size (%d). This is " "currently not supported!\n", msblk->block_size); goto failed_mount; } /* Check block log for sanity */ msblk->block_log = le16_to_cpu(sblk->block_log); if (msblk->block_log > SQUASHFS_FILE_MAX_LOG) goto failed_mount; /* Check that block_size and block_log match */ if (msblk->block_size != (1 << msblk->block_log)) goto failed_mount; /* Check the root inode for sanity */ root_inode = le64_to_cpu(sblk->root_inode); if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE) goto failed_mount; msblk->inode_table = le64_to_cpu(sblk->inode_table_start); msblk->directory_table = le64_to_cpu(sblk->directory_table_start); msblk->inodes = le32_to_cpu(sblk->inodes); msblk->fragments = le32_to_cpu(sblk->fragments); flags = le16_to_cpu(sblk->flags); TRACE("Found valid superblock on %pg\n", sb->s_bdev); TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(flags) ? "un" : ""); TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(flags) ? "un" : ""); TRACE("Filesystem size %lld bytes\n", msblk->bytes_used); TRACE("Block size %d\n", msblk->block_size); TRACE("Number of inodes %d\n", msblk->inodes); TRACE("Number of fragments %d\n", msblk->fragments); TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids)); TRACE("sblk->inode_table_start %llx\n", msblk->inode_table); TRACE("sblk->directory_table_start %llx\n", msblk->directory_table); TRACE("sblk->fragment_table_start %llx\n", (u64) le64_to_cpu(sblk->fragment_table_start)); TRACE("sblk->id_table_start %llx\n", (u64) le64_to_cpu(sblk->id_table_start)); sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_flags |= SB_RDONLY; sb->s_op = &squashfs_super_ops; err = -ENOMEM; msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); if (msblk->block_cache == NULL) goto failed_mount; /* Allocate read_page block */ msblk->read_page = squashfs_cache_init("data", squashfs_max_decompressors(), msblk->block_size); if (msblk->read_page == NULL) { ERROR("Failed to allocate read_page block\n"); goto failed_mount; } msblk->stream = squashfs_decompressor_setup(sb, flags); if (IS_ERR(msblk->stream)) { err = PTR_ERR(msblk->stream); msblk->stream = NULL; goto failed_mount; } /* Handle xattrs */ sb->s_xattr = squashfs_xattr_handlers; xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start); if (xattr_id_table_start == SQUASHFS_INVALID_BLK) { next_table = msblk->bytes_used; goto allocate_id_index_table; } /* Allocate and read xattr id lookup table */ msblk->xattr_id_table = squashfs_read_xattr_id_table(sb, xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids); if (IS_ERR(msblk->xattr_id_table)) { ERROR("unable to read xattr id index table\n"); err = PTR_ERR(msblk->xattr_id_table); msblk->xattr_id_table = NULL; if (err != -ENOTSUPP) goto failed_mount; } next_table = msblk->xattr_table; allocate_id_index_table: /* Allocate and read id index table */ msblk->id_table = squashfs_read_id_index_table(sb, le64_to_cpu(sblk->id_table_start), next_table, le16_to_cpu(sblk->no_ids)); if (IS_ERR(msblk->id_table)) { ERROR("unable to read id index table\n"); err = PTR_ERR(msblk->id_table); msblk->id_table = NULL; goto failed_mount; } next_table = le64_to_cpu(msblk->id_table[0]); /* Handle inode lookup table */ lookup_table_start = le64_to_cpu(sblk->lookup_table_start); if (lookup_table_start == SQUASHFS_INVALID_BLK) goto handle_fragments; /* Allocate and read inode lookup table */ msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb, lookup_table_start, next_table, msblk->inodes); if (IS_ERR(msblk->inode_lookup_table)) { ERROR("unable to read inode lookup table\n"); err = PTR_ERR(msblk->inode_lookup_table); msblk->inode_lookup_table = NULL; goto failed_mount; } next_table = le64_to_cpu(msblk->inode_lookup_table[0]); sb->s_export_op = &squashfs_export_ops; handle_fragments: fragments = msblk->fragments; if (fragments == 0) goto check_directory_table; msblk->fragment_cache = squashfs_cache_init("fragment", SQUASHFS_CACHED_FRAGMENTS, msblk->block_size); if (msblk->fragment_cache == NULL) { err = -ENOMEM; goto failed_mount; } /* Allocate and read fragment index table */ msblk->fragment_index = squashfs_read_fragment_index_table(sb, le64_to_cpu(sblk->fragment_table_start), next_table, fragments); if (IS_ERR(msblk->fragment_index)) { ERROR("unable to read fragment index table\n"); err = PTR_ERR(msblk->fragment_index); msblk->fragment_index = NULL; goto failed_mount; } next_table = le64_to_cpu(msblk->fragment_index[0]); check_directory_table: /* Sanity check directory_table */ if (msblk->directory_table > next_table) { err = -EINVAL; goto failed_mount; } /* Sanity check inode_table */ if (msblk->inode_table >= msblk->directory_table) { err = -EINVAL; goto failed_mount; } /* allocate root */ root = new_inode(sb); if (!root) { err = -ENOMEM; goto failed_mount; } err = squashfs_read_inode(root, root_inode); if (err) { make_bad_inode(root); iput(root); goto failed_mount; } insert_inode_hash(root); sb->s_root = d_make_root(root); if (sb->s_root == NULL) { ERROR("Root inode create failed\n"); err = -ENOMEM; goto failed_mount; } TRACE("Leaving squashfs_fill_super\n"); kfree(sblk); return 0; failed_mount: squashfs_cache_delete(msblk->block_cache); squashfs_cache_delete(msblk->fragment_cache); squashfs_cache_delete(msblk->read_page); squashfs_decompressor_destroy(msblk); kfree(msblk->inode_lookup_table); kfree(msblk->fragment_index); kfree(msblk->id_table); kfree(msblk->xattr_id_table); kfree(sb->s_fs_info); sb->s_fs_info = NULL; kfree(sblk); return err; }
static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, struct inode *dir, struct dentry *entry, umode_t mode) { struct fuse_entry_out outarg; struct inode *inode; int err; struct fuse_forget_link *forget; forget = fuse_alloc_forget(); if (!forget) { fuse_put_request(fc, req); return -ENOMEM; } memset(&outarg, 0, sizeof(outarg)); req->in.h.nodeid = get_node_id(dir); req->out.numargs = 1; if (fc->minor < 9) req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; else req->out.args[0].size = sizeof(outarg); req->out.args[0].value = &outarg; fuse_request_send(fc, req); err = req->out.h.error; fuse_put_request(fc, req); if (err) goto out_put_forget_req; err = -EIO; if (invalid_nodeid(outarg.nodeid)) goto out_put_forget_req; if ((outarg.attr.mode ^ mode) & S_IFMT) goto out_put_forget_req; inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr, entry_attr_timeout(&outarg), 0); if (!inode) { fuse_queue_forget(fc, forget, outarg.nodeid, 1); return -ENOMEM; } kfree(forget); if (S_ISDIR(inode->i_mode)) { struct dentry *alias; mutex_lock(&fc->inst_mutex); alias = d_find_alias(inode); if (alias) { /* */ mutex_unlock(&fc->inst_mutex); dput(alias); iput(inode); return -EBUSY; } d_instantiate(entry, inode); mutex_unlock(&fc->inst_mutex); } else d_instantiate(entry, inode); fuse_change_entry_timeout(entry, &outarg); fuse_invalidate_attr(dir); return 0; out_put_forget_req: kfree(forget); return err; }
int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, u64 child_nodeid, struct qstr *name) { int err = -ENOTDIR; struct inode *parent; struct dentry *dir; struct dentry *entry; parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); if (!parent) return -ENOENT; mutex_lock(&parent->i_mutex); if (!S_ISDIR(parent->i_mode)) goto unlock; err = -ENOENT; dir = d_find_alias(parent); if (!dir) goto unlock; entry = d_lookup(dir, name); dput(dir); if (!entry) goto unlock; fuse_invalidate_attr(parent); fuse_invalidate_entry(entry); if (child_nodeid != 0 && entry->d_inode) { mutex_lock(&entry->d_inode->i_mutex); if (get_node_id(entry->d_inode) != child_nodeid) { err = -ENOENT; goto badentry; } if (d_mountpoint(entry)) { err = -EBUSY; goto badentry; } if (S_ISDIR(entry->d_inode->i_mode)) { shrink_dcache_parent(entry); if (!simple_empty(entry)) { err = -ENOTEMPTY; goto badentry; } entry->d_inode->i_flags |= S_DEAD; } dont_mount(entry); clear_nlink(entry->d_inode); err = 0; badentry: mutex_unlock(&entry->d_inode->i_mutex); if (!err) d_delete(entry); } else { err = 0; } dput(entry); unlock: mutex_unlock(&parent->i_mutex); iput(parent); return err; }
/* * Allocate a new inode, to be used when creating a new file or directory. */ struct inode *lab5fs_inode_new_inode(struct super_block *sb, int mode) { struct inode *child_ino = NULL; ino_t ino_num = 0; int inode_block_num = 0; int bi_block_num = 0; int err = 0; struct lab5fs_inode_info *inode_info = NULL; /* allocate a disk block to contain this inode's data. */ inode_block_num = lab5fs_alloc_block_num(sb); if (inode_block_num == 0) { err = -ENOSPC; goto ret_err; } /* allocate a disk block to contain the block index of this inode. */ bi_block_num = lab5fs_alloc_block_num(sb); if (bi_block_num == 0) { err = -ENOSPC; goto ret_err; } /* allocate a free inode number. */ ino_num = lab5fs_alloc_inode_num(sb, inode_block_num); if (ino_num == 0) { err = -ENOSPC; goto ret_err; } /* allocate a VFS inode object. */ child_ino = new_inode(sb); if (!child_ino) { printk("printk: new_inode() failed... inode %lu\n",ino_num); err = -ENOMEM; goto ret_err; } /* initialize the inode's block index. */ err = lab5fs_inode_init_block_index(child_ino, bi_block_num); if (err) goto ret_err; /* init the inode's data. */ child_ino->i_ino = ino_num; child_ino->i_mode = mode; child_ino->i_nlink = 1; /* this inode will be stored in a directory, * so there's at least one link to this inode, * from that directory. */ child_ino->i_size = 0; child_ino->i_blksize = LAB5FS_BLOCK_SIZE; child_ino->i_blkbits = 10; child_ino->i_blocks = 0; child_ino->i_uid = current->fsuid; child_ino->i_gid = current->fsgid; child_ino->i_atime = child_ino->i_mtime = child_ino->i_ctime = CURRENT_TIME; /* init the inode's lab5fs metadata. */ inode_info = kmalloc(sizeof(struct lab5fs_inode_info), GFP_KERNEL); if (!inode_info) { printk("not enough memory to allocate inode meta data.\n"); goto ret_err; } inode_info->i_block_num = inode_block_num; inode_info->i_bi_block_num = bi_block_num; child_ino->u.generic_ip = inode_info; /* set the inode operations structs. */ child_ino->i_op = &lab5fs_inode_ops; child_ino->i_fop = NULL; child_ino->i_mapping->a_ops = &lab5fs_address_ops; //we are not creating directories //child_ino->i_op = &lab5fs_dir_iops; //child_ino->i_fop = &slab5s_dir_fops; //child_ino->i_mapping->a_ops = &lab5fs_aops; insert_inode_hash(child_ino); /* make sure the inode gets written to disk by the inodes cache. */ mark_inode_dirty(child_ino); /* no errors*/ err = 0; goto ret; ret_err: if (child_ino) iput(child_ino); /* child_ino will be deleted here. */ if (ino_num > 0) lab5fs_release_inode_num(sb, ino_num); if (inode_block_num > 0) lab5fs_release_block_num(sb, inode_block_num); if (bi_block_num > 0) lab5fs_release_block_num(sb, bi_block_num); ret: return (err == 0 ? child_ino : NULL); }
static int affs_fill_super(struct super_block *sb, void *data, int silent) { struct affs_sb_info *sbi; struct buffer_head *root_bh = NULL; struct buffer_head *boot_bh; struct inode *root_inode = NULL; s32 root_block; int size, blocksize; u32 chksum; int num_bm; int i, j; s32 key; uid_t uid; gid_t gid; int reserved; unsigned long mount_flags; int tmp_flags; /* fix remount prototype... */ pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options"); sb->s_magic = AFFS_SUPER_MAGIC; sb->s_op = &affs_sops; sb->s_flags |= MS_NODIRATIME; sbi = kmalloc(sizeof(struct affs_sb_info), GFP_KERNEL); if (!sbi) return -ENOMEM; sb->s_fs_info = sbi; memset(sbi, 0, sizeof(*sbi)); init_MUTEX(&sbi->s_bmlock); if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, &blocksize,&sbi->s_prefix, sbi->s_volume, &mount_flags)) { printk(KERN_ERR "AFFS: Error parsing options\n"); return -EINVAL; } /* N.B. after this point s_prefix must be released */ sbi->s_flags = mount_flags; sbi->s_mode = i; sbi->s_uid = uid; sbi->s_gid = gid; sbi->s_reserved= reserved; /* Get the size of the device in 512-byte blocks. * If we later see that the partition uses bigger * blocks, we will have to change it. */ size = sb->s_bdev->bd_inode->i_size >> 9; pr_debug("AFFS: initial blocksize=%d, #blocks=%d\n", 512, size); affs_set_blocksize(sb, PAGE_SIZE); /* Try to find root block. Its location depends on the block size. */ i = 512; j = 4096; if (blocksize > 0) { i = j = blocksize; size = size / (blocksize / 512); } for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) { sbi->s_root_block = root_block; if (root_block < 0) sbi->s_root_block = (reserved + size - 1) / 2; pr_debug("AFFS: setting blocksize to %d\n", blocksize); affs_set_blocksize(sb, blocksize); sbi->s_partition_size = size; /* The root block location that was calculated above is not * correct if the partition size is an odd number of 512- * byte blocks, which will be rounded down to a number of * 1024-byte blocks, and if there were an even number of * reserved blocks. Ideally, all partition checkers should * report the real number of blocks of the real blocksize, * but since this just cannot be done, we have to try to * find the root block anyways. In the above case, it is one * block behind the calculated one. So we check this one, too. */ for (num_bm = 0; num_bm < 2; num_bm++) { pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, " "size=%d, reserved=%d\n", sb->s_id, sbi->s_root_block + num_bm, blocksize, size, reserved); root_bh = affs_bread(sb, sbi->s_root_block + num_bm); if (!root_bh) continue; if (!affs_checksum_block(sb, root_bh) && be32_to_cpu(AFFS_ROOT_HEAD(root_bh)->ptype) == T_SHORT && be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) { sbi->s_hashsize = blocksize / 4 - 56; sbi->s_root_block += num_bm; key = 1; goto got_root; } affs_brelse(root_bh); root_bh = NULL; } } if (!silent) printk(KERN_ERR "AFFS: No valid root block on device %s\n", sb->s_id); goto out_error; /* N.B. after this point bh must be released */ got_root: root_block = sbi->s_root_block; /* Find out which kind of FS we have */ boot_bh = sb_bread(sb, 0); if (!boot_bh) { printk(KERN_ERR "AFFS: Cannot read boot block\n"); goto out_error; } chksum = be32_to_cpu(*(u32 *)boot_bh->b_data); brelse(boot_bh); /* Dircache filesystems are compatible with non-dircache ones * when reading. As long as they aren't supported, writing is * not recommended. */ if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS || chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) { printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", sb->s_id); sb->s_flags |= MS_RDONLY; } switch (chksum) { case MUFS_FS: case MUFS_INTLFFS: case MUFS_DCFFS: sbi->s_flags |= SF_MUFS; /* fall thru */ case FS_INTLFFS: case FS_DCFFS: sbi->s_flags |= SF_INTL; break; case MUFS_FFS: sbi->s_flags |= SF_MUFS; break; case FS_FFS: break; case MUFS_OFS: sbi->s_flags |= SF_MUFS; /* fall thru */ case FS_OFS: sbi->s_flags |= SF_OFS; sb->s_flags |= MS_NOEXEC; break; case MUFS_DCOFS: case MUFS_INTLOFS: sbi->s_flags |= SF_MUFS; case FS_DCOFS: case FS_INTLOFS: sbi->s_flags |= SF_INTL | SF_OFS; sb->s_flags |= MS_NOEXEC; break; default: printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", sb->s_id, chksum); goto out_error; } if (mount_flags & SF_VERBOSE) { chksum = cpu_to_be32(chksum); printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0], AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1, (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); } sb->s_flags |= MS_NODEV | MS_NOSUID; sbi->s_data_blksize = sb->s_blocksize; if (sbi->s_flags & SF_OFS) sbi->s_data_blksize -= 24; /* Keep super block in cache */ sbi->s_root_bh = root_bh; /* N.B. after this point s_root_bh must be released */ tmp_flags = sb->s_flags; if (affs_init_bitmap(sb, &tmp_flags)) goto out_error; sb->s_flags = tmp_flags; /* set up enough so that it can read an inode */ root_inode = iget(sb, root_block); sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) { printk(KERN_ERR "AFFS: Get root inode failed\n"); goto out_error; } sb->s_root->d_op = &affs_dentry_operations; pr_debug("AFFS: s_flags=%lX\n",sb->s_flags); return 0; /* * Begin the cascaded cleanup ... */ out_error: if (root_inode) iput(root_inode); if (sbi->s_bitmap) kfree(sbi->s_bitmap); affs_brelse(root_bh); if (sbi->s_prefix) kfree(sbi->s_prefix); kfree(sbi); sb->s_fs_info = NULL; return -EINVAL; }
static int parse_rock_ridge_inode_internal(struct iso_directory_record *de, struct inode *inode, int regard_xa) { int symlink_len = 0; int cnt, sig; struct inode *reloc; struct rock_ridge *rr; int rootflag; struct rock_state rs; int ret = 0; if (!ISOFS_SB(inode->i_sb)->s_rock) return 0; init_rock_state(&rs, inode); setup_rock_ridge(de, inode, &rs); if (regard_xa) { rs.chr += 14; rs.len -= 14; if (rs.len < 0) rs.len = 0; } repeat: while (rs.len > 2) { rr = (struct rock_ridge *)rs.chr; if (rr->len < 3) goto out; sig = isonum_721(rs.chr); if (rock_check_overflow(&rs, sig)) goto eio; rs.chr += rr->len; rs.len -= rr->len; if (rs.len < 0) goto out; switch (sig) { #ifndef CONFIG_ZISOFS case SIG('R', 'R'): if ((rr->u.RR.flags[0] & (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out; break; #endif case SIG('S', 'P'): if (check_sp(rr, inode)) goto out; break; case SIG('C', 'E'): rs.cont_extent = isonum_733(rr->u.CE.extent); rs.cont_offset = isonum_733(rr->u.CE.offset); rs.cont_size = isonum_733(rr->u.CE.size); break; case SIG('E', 'R'): ISOFS_SB(inode->i_sb)->s_rock = 1; printk(KERN_DEBUG "ISO 9660 Extensions: "); { int p; for (p = 0; p < rr->u.ER.len_id; p++) printk("%c", rr->u.ER.data[p]); } printk("\n"); break; case SIG('P', 'X'): inode->i_mode = isonum_733(rr->u.PX.mode); set_nlink(inode, isonum_733(rr->u.PX.n_links)); inode->i_uid = isonum_733(rr->u.PX.uid); inode->i_gid = isonum_733(rr->u.PX.gid); break; case SIG('P', 'N'): { int high, low; high = isonum_733(rr->u.PN.dev_high); low = isonum_733(rr->u.PN.dev_low); if ((low & ~0xff) && high == 0) { inode->i_rdev = MKDEV(low >> 8, low & 0xff); } else { inode->i_rdev = MKDEV(high, low); } } break; case SIG('T', 'F'): cnt = 0; if (rr->u.TF.flags & TF_CREATE) { inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_ctime.tv_nsec = 0; } if (rr->u.TF.flags & TF_MODIFY) { inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_mtime.tv_nsec = 0; } if (rr->u.TF.flags & TF_ACCESS) { inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_atime.tv_nsec = 0; } if (rr->u.TF.flags & TF_ATTRIBUTES) { inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_ctime.tv_nsec = 0; } break; case SIG('S', 'L'): { int slen; struct SL_component *slp; struct SL_component *oldslp; slen = rr->len - 5; slp = &rr->u.SL.link; inode->i_size = symlink_len; while (slen > 1) { rootflag = 0; switch (slp->flags & ~1) { case 0: inode->i_size += slp->len; break; case 2: inode->i_size += 1; break; case 4: inode->i_size += 2; break; case 8: rootflag = 1; inode->i_size += 1; break; default: printk("Symlink component flag " "not implemented\n"); } slen -= slp->len + 2; oldslp = slp; slp = (struct SL_component *) (((char *)slp) + slp->len + 2); if (slen < 2) { if (((rr->u.SL. flags & 1) != 0) && ((oldslp-> flags & 1) == 0)) inode->i_size += 1; break; } if (!rootflag && (oldslp->flags & 1) == 0) inode->i_size += 1; } } symlink_len = inode->i_size; break; case SIG('R', 'E'): printk(KERN_WARNING "Attempt to read inode for " "relocated directory\n"); goto out; case SIG('C', 'L'): ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location); reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0); if (IS_ERR(reloc)) { ret = PTR_ERR(reloc); goto out; } inode->i_mode = reloc->i_mode; set_nlink(inode, reloc->i_nlink); inode->i_uid = reloc->i_uid; inode->i_gid = reloc->i_gid; inode->i_rdev = reloc->i_rdev; inode->i_size = reloc->i_size; inode->i_blocks = reloc->i_blocks; inode->i_atime = reloc->i_atime; inode->i_ctime = reloc->i_ctime; inode->i_mtime = reloc->i_mtime; iput(reloc); break; #ifdef CONFIG_ZISOFS case SIG('Z', 'F'): { int algo; if (ISOFS_SB(inode->i_sb)->s_nocompress) break; algo = isonum_721(rr->u.ZF.algorithm); if (algo == SIG('p', 'z')) { int block_shift = isonum_711(&rr->u.ZF.parms[1]); if (block_shift > 17) { printk(KERN_WARNING "isofs: " "Can't handle ZF block " "size of 2^%d\n", block_shift); } else { ISOFS_I(inode)->i_file_format = isofs_file_compressed; ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]); ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]); inode->i_size = isonum_733(rr->u.ZF. real_size); } } else { printk(KERN_WARNING "isofs: Unknown ZF compression " "algorithm: %c%c\n", rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]); } break; } #endif default: break; }
static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { int retval; struct inode *inode; struct reiserfs_transaction_handle th; struct reiserfs_security_handle security; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); if (!new_valid_dev(rdev)) return -EINVAL; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); jbegin_count += reiserfs_cache_default_acl(dir); retval = reiserfs_security_init(dir, inode, &security); if (retval < 0) { drop_new_inode(inode); return retval; } jbegin_count += retval; reiserfs_write_lock(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } retval = reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, inode, &security); if (retval) { goto out_failed; } inode->i_op = &reiserfs_special_inode_operations; init_special_inode(inode, inode->i_mode, rdev); //FIXME: needed for block and char devices only reiserfs_update_sd(&th, inode); reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; inode->i_nlink--; reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; unlock_new_inode(inode); iput(inode); goto out_failed; } d_instantiate(dentry, inode); unlock_new_inode(inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: reiserfs_write_unlock(dir->i_sb); return retval; }
/* * Allocate a new inode with the passed id and ops. */ static struct inode * zfsctl_inode_alloc(zfs_sb_t *zsb, uint64_t id, const struct file_operations *fops, const struct inode_operations *ops) { struct timespec now = current_fs_time(zsb->z_sb); struct inode *ip; znode_t *zp; ip = new_inode(zsb->z_sb); if (ip == NULL) return (NULL); zp = ITOZ(ip); ASSERT3P(zp->z_dirlocks, ==, NULL); ASSERT3P(zp->z_acl_cached, ==, NULL); ASSERT3P(zp->z_xattr_cached, ==, NULL); zp->z_id = id; zp->z_unlinked = 0; zp->z_atime_dirty = 0; zp->z_zn_prefetch = 0; zp->z_moved = 0; zp->z_sa_hdl = NULL; zp->z_blksz = 0; zp->z_seq = 0; zp->z_mapcnt = 0; zp->z_gen = 0; zp->z_size = 0; zp->z_atime[0] = 0; zp->z_atime[1] = 0; zp->z_links = 0; zp->z_pflags = 0; zp->z_uid = 0; zp->z_gid = 0; zp->z_mode = 0; zp->z_sync_cnt = 0; zp->z_is_zvol = B_FALSE; zp->z_is_mapped = B_FALSE; zp->z_is_ctldir = B_TRUE; zp->z_is_sa = B_FALSE; zp->z_is_stale = B_FALSE; ip->i_ino = id; ip->i_mode = (S_IFDIR | S_IRUGO | S_IXUGO); ip->i_uid = 0; ip->i_gid = 0; ip->i_blkbits = SPA_MINBLOCKSHIFT; ip->i_atime = now; ip->i_mtime = now; ip->i_ctime = now; ip->i_fop = fops; ip->i_op = ops; if (insert_inode_locked(ip)) { unlock_new_inode(ip); iput(ip); return (NULL); } mutex_enter(&zsb->z_znodes_lock); list_insert_tail(&zsb->z_all_znodes, zp); zsb->z_nr_znodes++; membar_producer(); mutex_exit(&zsb->z_znodes_lock); unlock_new_inode(ip); return (ip); }
static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { int retval; struct inode *inode; struct reiserfs_transaction_handle th; struct reiserfs_security_handle security; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); #ifdef DISPLACE_NEW_PACKING_LOCALITIES /* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */ REISERFS_I(dir)->new_packing_locality = 1; #endif mode = S_IFDIR | mode; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); jbegin_count += reiserfs_cache_default_acl(dir); retval = reiserfs_security_init(dir, inode, &security); if (retval < 0) { drop_new_inode(inode); return retval; } jbegin_count += retval; reiserfs_write_lock(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } /* inc the link count now, so another writer doesn't overflow it while ** we sleep later on. */ INC_DIR_INODE_NLINK(dir) retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ , old_format_only(dir->i_sb) ? EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, dentry, inode, &security); if (retval) { dir->i_nlink--; goto out_failed; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); inode->i_op = &reiserfs_dir_inode_operations; inode->i_fop = &reiserfs_dir_operations; // note, _this_ add_entry will not update dir's stat data retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; inode->i_nlink = 0; DEC_DIR_INODE_NLINK(dir); reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; unlock_new_inode(inode); iput(inode); goto out_failed; } // the above add_entry did not update dir's stat data reiserfs_update_sd(&th, dir); d_instantiate(dentry, inode); unlock_new_inode(inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: reiserfs_write_unlock(dir->i_sb); return retval; }
/* * Destroy the '.zfs' directory. Only called when the filesystem is unmounted. */ void zfsctl_destroy(zfs_sb_t *zsb) { iput(zsb->z_ctldir); zsb->z_ctldir = NULL; }
static int parse_rock_ridge_inode_internal(struct iso_directory_record *de, struct inode *inode, int regard_xa) { int symlink_len = 0; int cnt, sig; struct inode *reloc; struct rock_ridge *rr; int rootflag; struct rock_state rs; int ret = 0; if (!ISOFS_SB(inode->i_sb)->s_rock) return 0; init_rock_state(&rs, inode); setup_rock_ridge(de, inode, &rs); if (regard_xa) { rs.chr += 14; rs.len -= 14; if (rs.len < 0) rs.len = 0; } repeat: while (rs.len > 2) { /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *)rs.chr; /* * Ignore rock ridge info if rr->len is out of range, but * don't return -EIO because that would make the file * invisible. */ if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(rs.chr); if (rock_check_overflow(&rs, sig)) goto eio; rs.chr += rr->len; rs.len -= rr->len; /* * As above, just ignore the rock ridge info if rr->len * is bogus. */ if (rs.len < 0) goto out; /* Something got screwed up here */ switch (sig) { #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ case SIG('R', 'R'): if ((rr->u.RR.flags[0] & (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out; break; #endif case SIG('S', 'P'): if (check_sp(rr, inode)) goto out; break; case SIG('C', 'E'): rs.cont_extent = isonum_733(rr->u.CE.extent); rs.cont_offset = isonum_733(rr->u.CE.offset); rs.cont_size = isonum_733(rr->u.CE.size); break; case SIG('E', 'R'): ISOFS_SB(inode->i_sb)->s_rock = 1; printk(KERN_DEBUG "ISO 9660 Extensions: "); { int p; for (p = 0; p < rr->u.ER.len_id; p++) printk("%c", rr->u.ER.data[p]); } printk("\n"); break; case SIG('P', 'X'): inode->i_mode = isonum_733(rr->u.PX.mode); inode->i_nlink = isonum_733(rr->u.PX.n_links); inode->i_uid = isonum_733(rr->u.PX.uid); inode->i_gid = isonum_733(rr->u.PX.gid); break; case SIG('P', 'N'): { int high, low; high = isonum_733(rr->u.PN.dev_high); low = isonum_733(rr->u.PN.dev_low); /* * The Rock Ridge standard specifies that if * sizeof(dev_t) <= 4, then the high field is * unused, and the device number is completely * stored in the low field. Some writers may * ignore this subtlety, * and as a result we test to see if the entire * device number is * stored in the low field, and use that. */ if ((low & ~0xff) && high == 0) { inode->i_rdev = MKDEV(low >> 8, low & 0xff); } else { inode->i_rdev = MKDEV(high, low); } } break; case SIG('T', 'F'): /* * Some RRIP writers incorrectly place ctime in the * TF_CREATE field. Try to handle this correctly for * either case. */ /* Rock ridge never appears on a High Sierra disk */ cnt = 0; if (rr->u.TF.flags & TF_CREATE) { inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_ctime.tv_nsec = 0; } if (rr->u.TF.flags & TF_MODIFY) { inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_mtime.tv_nsec = 0; } if (rr->u.TF.flags & TF_ACCESS) { inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_atime.tv_nsec = 0; } if (rr->u.TF.flags & TF_ATTRIBUTES) { inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); inode->i_ctime.tv_nsec = 0; } break; case SIG('S', 'L'): { int slen; struct SL_component *slp; struct SL_component *oldslp; slen = rr->len - 5; slp = &rr->u.SL.link; inode->i_size = symlink_len; while (slen > 1) { rootflag = 0; switch (slp->flags & ~1) { case 0: inode->i_size += slp->len; break; case 2: inode->i_size += 1; break; case 4: inode->i_size += 2; break; case 8: rootflag = 1; inode->i_size += 1; break; default: printk("Symlink component flag " "not implemented\n"); } slen -= slp->len + 2; oldslp = slp; slp = (struct SL_component *) (((char *)slp) + slp->len + 2); if (slen < 2) { if (((rr->u.SL. flags & 1) != 0) && ((oldslp-> flags & 1) == 0)) inode->i_size += 1; break; } /* * If this component record isn't * continued, then append a '/'. */ if (!rootflag && (oldslp->flags & 1) == 0) inode->i_size += 1; } } symlink_len = inode->i_size; break; case SIG('R', 'E'): printk(KERN_WARNING "Attempt to read inode for " "relocated directory\n"); goto out; case SIG('C', 'L'): ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location); reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0); if (IS_ERR(reloc)) { ret = PTR_ERR(reloc); goto out; } inode->i_mode = reloc->i_mode; inode->i_nlink = reloc->i_nlink; inode->i_uid = reloc->i_uid; inode->i_gid = reloc->i_gid; inode->i_rdev = reloc->i_rdev; inode->i_size = reloc->i_size; inode->i_blocks = reloc->i_blocks; inode->i_atime = reloc->i_atime; inode->i_ctime = reloc->i_ctime; inode->i_mtime = reloc->i_mtime; iput(reloc); break; #ifdef CONFIG_ZISOFS case SIG('Z', 'F'): { int algo; if (ISOFS_SB(inode->i_sb)->s_nocompress) break; algo = isonum_721(rr->u.ZF.algorithm); if (algo == SIG('p', 'z')) { int block_shift = isonum_711(&rr->u.ZF.parms[1]); if (block_shift > 17) { printk(KERN_WARNING "isofs: " "Can't handle ZF block " "size of 2^%d\n", block_shift); } else { /* * Note: we don't change * i_blocks here */ ISOFS_I(inode)->i_file_format = isofs_file_compressed; /* * Parameters to compression * algorithm (header size, * block size) */ ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]); ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]); inode->i_size = isonum_733(rr->u.ZF. real_size); } } else { printk(KERN_WARNING "isofs: Unknown ZF compression " "algorithm: %c%c\n", rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]); } break; } #endif default: break; }
static int efs_fill_super(struct super_block *s, void *d, int silent) { struct efs_sb_info *sb; struct buffer_head *bh; struct inode *root; sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL); if (!sb) return -ENOMEM; s->s_fs_info = sb; s->s_magic = EFS_SUPER_MAGIC; if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) { printk(KERN_ERR "EFS: device does not support %d byte blocks\n", EFS_BLOCKSIZE); goto out_no_fs_ul; } /* read the vh (volume header) block */ bh = sb_bread(s, 0); if (!bh) { printk(KERN_ERR "EFS: cannot read volume header\n"); goto out_no_fs_ul; } /* * if this returns zero then we didn't find any partition table. * this isn't (yet) an error - just assume for the moment that * the device is valid and go on to search for a superblock. */ sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data); brelse(bh); if (sb->fs_start == -1) { goto out_no_fs_ul; } bh = sb_bread(s, sb->fs_start + EFS_SUPER); if (!bh) { printk(KERN_ERR "EFS: cannot read superblock\n"); goto out_no_fs_ul; } if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) { #ifdef DEBUG printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER); #endif brelse(bh); goto out_no_fs_ul; } brelse(bh); if (!(s->s_flags & MS_RDONLY)) { #ifdef DEBUG printk(KERN_INFO "EFS: forcing read-only mode\n"); #endif s->s_flags |= MS_RDONLY; } s->s_op = &efs_superblock_operations; s->s_export_op = &efs_export_ops; root = iget(s, EFS_ROOTINODE); s->s_root = d_alloc_root(root); if (!(s->s_root)) { printk(KERN_ERR "EFS: get root inode failed\n"); iput(root); goto out_no_fs; } return 0; out_no_fs_ul: out_no_fs: s->s_fs_info = NULL; kfree(sb); return -EINVAL; }
/* * get an NFS2/NFS3 root dentry from the root filehandle */ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) { struct nfs_server *server = NFS_SB(sb); struct nfs_fsinfo fsinfo; struct nfs_fattr fattr; struct dentry *mntroot; struct inode *inode; int error; /* create a dummy root dentry with dummy inode for this superblock */ if (!sb->s_root) { struct nfs_fh dummyfh; struct dentry *root; struct inode *iroot; memset(&dummyfh, 0, sizeof(dummyfh)); memset(&fattr, 0, sizeof(fattr)); nfs_fattr_init(&fattr); fattr.valid = NFS_ATTR_FATTR; fattr.type = NFDIR; fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; fattr.nlink = 2; iroot = nfs_fhget(sb, &dummyfh, &fattr); if (IS_ERR(iroot)) return ERR_PTR(PTR_ERR(iroot)); root = d_alloc_root(iroot); if (!root) { iput(iroot); return ERR_PTR(-ENOMEM); } sb->s_root = root; } /* get the actual root for this mount */ fsinfo.fattr = &fattr; error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); if (error < 0) { dprintk("nfs_get_root: getattr error = %d\n", -error); return ERR_PTR(error); } inode = nfs_fhget(sb, mntfh, fsinfo.fattr); if (IS_ERR(inode)) { dprintk("nfs_get_root: get root inode failed\n"); return ERR_PTR(PTR_ERR(inode)); } /* root dentries normally start off anonymous and get spliced in later * if the dentry tree reaches them; however if the dentry already * exists, we'll pick it up at this point and use it as the root */ mntroot = d_alloc_anon(inode); if (!mntroot) { iput(inode); dprintk("nfs_get_root: get root dentry failed\n"); return ERR_PTR(-ENOMEM); } security_d_instantiate(mntroot, inode); if (!mntroot->d_op) mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; return mntroot; }
struct inode * ext2_new_inode (struct inode * dir, int mode) { struct super_block * sb; struct buffer_head * bh; struct buffer_head * bh2; int group, i; ino_t ino; struct inode * inode; struct ext2_group_desc * desc; struct ext2_super_block * es; int err; sb = dir->i_sb; inode = new_inode(sb); if (!inode) return ERR_PTR(-ENOMEM); lock_super (sb); es = sb->u.ext2_sb.s_es; repeat: if (S_ISDIR(mode)) group = find_group_dir(sb, dir->u.ext2_i.i_block_group); else group = find_group_other(sb, dir->u.ext2_i.i_block_group); err = -ENOSPC; if (group == -1) goto fail; err = -EIO; bh = load_inode_bitmap (sb, group); if (IS_ERR(bh)) goto fail2; i = ext2_find_first_zero_bit ((unsigned long *) bh->b_data, EXT2_INODES_PER_GROUP(sb)); if (i >= EXT2_INODES_PER_GROUP(sb)) goto bad_count; ext2_set_bit (i, bh->b_data); mark_buffer_dirty(bh); if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } ino = group * EXT2_INODES_PER_GROUP(sb) + i + 1; if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) { ext2_error (sb, "ext2_new_inode", "reserved inode or inode > inodes count - " "block_group = %d,inode=%ld", group, ino); err = -EIO; goto fail2; } es->s_free_inodes_count = cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1); mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; inode->i_uid = current->fsuid; if (test_opt (sb, GRPID)) inode->i_gid = dir->i_gid; else if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; if (S_ISDIR(mode)) mode |= S_ISGID; } else inode->i_gid = current->fsgid; inode->i_mode = mode; inode->i_ino = ino; inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */ inode->i_blocks = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->u.ext2_i.i_new_inode = 1; inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags & ~EXT2_BTREE_FL; if (S_ISLNK(mode)) inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL); inode->u.ext2_i.i_block_group = group; ext2_set_inode_flags(inode); insert_inode_hash(inode); inode->i_generation = event++; mark_inode_dirty(inode); #ifdef CONFIG_EXT2_FS_XATTR init_rwsem(&inode->u.ext2_i.xattr_sem); #endif unlock_super (sb); if(DQUOT_ALLOC_INODE(inode)) { DQUOT_DROP(inode); err = -EDQUOT; goto fail3; } err = ext2_init_acl(inode, dir); if (err) { DQUOT_FREE_INODE(inode); goto fail3; } ext2_debug ("allocating inode %lu\n", inode->i_ino); return inode; fail3: inode->i_flags |= S_NOQUOTA; inode->i_nlink = 0; iput(inode); return ERR_PTR(err); fail2: desc = ext2_get_group_desc (sb, group, &bh2); desc->bg_free_inodes_count = cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1); if (S_ISDIR(mode)) desc->bg_used_dirs_count = cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1); mark_buffer_dirty(bh2); fail: unlock_super(sb); make_bad_inode(inode); iput(inode); return ERR_PTR(err); bad_count: ext2_error (sb, "ext2_new_inode", "Free inodes count corrupted in group %d", group); /* Is it really ENOSPC? */ err = -ENOSPC; if (sb->s_flags & MS_RDONLY) goto fail; desc = ext2_get_group_desc (sb, group, &bh2); desc->bg_free_inodes_count = 0; mark_buffer_dirty(bh2); goto repeat; }
/* * Lock a directory entry. A dirlock on <dzp, name> protects that name * in dzp's directory zap object. As long as you hold a dirlock, you can * assume two things: (1) dzp cannot be reaped, and (2) no other thread * can change the zap entry for (i.e. link or unlink) this name. * * Input arguments: * dzp - znode for directory * name - name of entry to lock * flag - ZNEW: if the entry already exists, fail with EEXIST. * ZEXISTS: if the entry does not exist, fail with ENOENT. * ZSHARED: allow concurrent access with other ZSHARED callers. * ZXATTR: we want dzp's xattr directory * ZCILOOK: On a mixed sensitivity file system, * this lookup should be case-insensitive. * ZCIEXACT: On a purely case-insensitive file system, * this lookup should be case-sensitive. * ZRENAMING: we are locking for renaming, force narrow locks * ZHAVELOCK: Don't grab the z_name_lock for this call. The * current thread already holds it. * * Output arguments: * zpp - pointer to the znode for the entry (NULL if there isn't one) * dlpp - pointer to the dirlock for this entry (NULL on error) * direntflags - (case-insensitive lookup only) * flags if multiple case-sensitive matches exist in directory * realpnp - (case-insensitive lookup only) * actual name matched within the directory * * Return value: 0 on success or errno on failure. * * NOTE: Always checks for, and rejects, '.' and '..'. * NOTE: For case-insensitive file systems we take wide locks (see below), * but return znode pointers to a single match. */ int zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp, int flag, int *direntflags, pathname_t *realpnp) { zfs_sb_t *zsb = ZTOZSB(dzp); zfs_dirlock_t *dl; boolean_t update; boolean_t exact; uint64_t zoid; #ifdef HAVE_DNLC vnode_t *vp = NULL; #endif /* HAVE_DNLC */ int error = 0; int cmpflags; *zpp = NULL; *dlpp = NULL; /* * Verify that we are not trying to lock '.', '..', or '.zfs' */ if ((name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) || (zfs_has_ctldir(dzp) && strcmp(name, ZFS_CTLDIR_NAME) == 0)) return (SET_ERROR(EEXIST)); /* * Case sensitivity and normalization preferences are set when * the file system is created. These are stored in the * zsb->z_case and zsb->z_norm fields. These choices * affect what vnodes can be cached in the DNLC, how we * perform zap lookups, and the "width" of our dirlocks. * * A normal dirlock locks a single name. Note that with * normalization a name can be composed multiple ways, but * when normalized, these names all compare equal. A wide * dirlock locks multiple names. We need these when the file * system is supporting mixed-mode access. It is sometimes * necessary to lock all case permutations of file name at * once so that simultaneous case-insensitive/case-sensitive * behaves as rationally as possible. */ /* * Decide if exact matches should be requested when performing * a zap lookup on file systems supporting case-insensitive * access. */ exact = ((zsb->z_case == ZFS_CASE_INSENSITIVE) && (flag & ZCIEXACT)) || ((zsb->z_case == ZFS_CASE_MIXED) && !(flag & ZCILOOK)); /* * Only look in or update the DNLC if we are looking for the * name on a file system that does not require normalization * or case folding. We can also look there if we happen to be * on a non-normalizing, mixed sensitivity file system IF we * are looking for the exact name. * * Maybe can add TO-UPPERed version of name to dnlc in ci-only * case for performance improvement? */ update = !zsb->z_norm || ((zsb->z_case == ZFS_CASE_MIXED) && !(zsb->z_norm & ~U8_TEXTPREP_TOUPPER) && !(flag & ZCILOOK)); /* * ZRENAMING indicates we are in a situation where we should * take narrow locks regardless of the file system's * preferences for normalizing and case folding. This will * prevent us deadlocking trying to grab the same wide lock * twice if the two names happen to be case-insensitive * matches. */ if (flag & ZRENAMING) cmpflags = 0; else cmpflags = zsb->z_norm; /* * Wait until there are no locks on this name. * * Don't grab the the lock if it is already held. However, cannot * have both ZSHARED and ZHAVELOCK together. */ ASSERT(!(flag & ZSHARED) || !(flag & ZHAVELOCK)); if (!(flag & ZHAVELOCK)) rw_enter(&dzp->z_name_lock, RW_READER); mutex_enter(&dzp->z_lock); for (;;) { if (dzp->z_unlinked) { mutex_exit(&dzp->z_lock); if (!(flag & ZHAVELOCK)) rw_exit(&dzp->z_name_lock); return (SET_ERROR(ENOENT)); } for (dl = dzp->z_dirlocks; dl != NULL; dl = dl->dl_next) { if ((u8_strcmp(name, dl->dl_name, 0, cmpflags, U8_UNICODE_LATEST, &error) == 0) || error != 0) break; } if (error != 0) { mutex_exit(&dzp->z_lock); if (!(flag & ZHAVELOCK)) rw_exit(&dzp->z_name_lock); return (SET_ERROR(ENOENT)); } if (dl == NULL) { /* * Allocate a new dirlock and add it to the list. */ dl = kmem_alloc(sizeof (zfs_dirlock_t), KM_SLEEP); cv_init(&dl->dl_cv, NULL, CV_DEFAULT, NULL); dl->dl_name = name; dl->dl_sharecnt = 0; dl->dl_namelock = 0; dl->dl_namesize = 0; dl->dl_dzp = dzp; dl->dl_next = dzp->z_dirlocks; dzp->z_dirlocks = dl; break; } if ((flag & ZSHARED) && dl->dl_sharecnt != 0) break; cv_wait(&dl->dl_cv, &dzp->z_lock); } /* * If the z_name_lock was NOT held for this dirlock record it. */ if (flag & ZHAVELOCK) dl->dl_namelock = 1; if ((flag & ZSHARED) && ++dl->dl_sharecnt > 1 && dl->dl_namesize == 0) { /* * We're the second shared reference to dl. Make a copy of * dl_name in case the first thread goes away before we do. * Note that we initialize the new name before storing its * pointer into dl_name, because the first thread may load * dl->dl_name at any time. He'll either see the old value, * which is his, or the new shared copy; either is OK. */ dl->dl_namesize = strlen(dl->dl_name) + 1; name = kmem_alloc(dl->dl_namesize, KM_SLEEP); bcopy(dl->dl_name, name, dl->dl_namesize); dl->dl_name = name; } mutex_exit(&dzp->z_lock); /* * We have a dirlock on the name. (Note that it is the dirlock, * not the dzp's z_lock, that protects the name in the zap object.) * See if there's an object by this name; if so, put a hold on it. */ if (flag & ZXATTR) { error = sa_lookup(dzp->z_sa_hdl, SA_ZPL_XATTR(zsb), &zoid, sizeof (zoid)); if (error == 0) error = (zoid == 0 ? SET_ERROR(ENOENT) : 0); } else { #ifdef HAVE_DNLC if (update) vp = dnlc_lookup(ZTOI(dzp), name); if (vp == DNLC_NO_VNODE) { iput(vp); error = SET_ERROR(ENOENT); } else if (vp) { if (flag & ZNEW) { zfs_dirent_unlock(dl); iput(vp); return (SET_ERROR(EEXIST)); } *dlpp = dl; *zpp = VTOZ(vp); return (0); } else { error = zfs_match_find(zsb, dzp, name, exact, update, direntflags, realpnp, &zoid); } #else error = zfs_match_find(zsb, dzp, name, exact, update, direntflags, realpnp, &zoid); #endif /* HAVE_DNLC */ } if (error) { if (error != ENOENT || (flag & ZEXISTS)) { zfs_dirent_unlock(dl); return (error); } } else { if (flag & ZNEW) { zfs_dirent_unlock(dl); return (SET_ERROR(EEXIST)); } error = zfs_zget(zsb, zoid, zpp); if (error) { zfs_dirent_unlock(dl); return (error); } #ifdef HAVE_DNLC if (!(flag & ZXATTR) && update) dnlc_update(ZTOI(dzp), name, ZTOI(*zpp)); #endif /* HAVE_DNLC */ } *dlpp = dl; return (0); }
/* * struct fs32_opencreate_parms { * PTR16 pfgenflag; * PTR16 pEABuf; * unsigned short attr; * PTR16 pAction; * unsigned short openflag; * unsigned long openmode; * PTR16 psffsd; * PTR16 psffsi; * unsigned short iCurDirEnd; * PTR16 pName; * PTR16 pcdfsd; * PTR16 pcdfsi; * }; */ int FS32ENTRY fs32_opencreate(struct fs32_opencreate_parms *parms) { char *pName; struct cdfsi32 *pcdfsi; union cdfsd32 *pcdfsd; struct sffsi32 *psffsi; union sffsd32 *psffsd; unsigned short *pAction; int rc; struct super_block *sb; struct file *p_file, *dir; UINT32 openmode, DOSmode; UINT32 accessmode; UINT16 newflag, existflag; char component[CCHMAXPATH]; char parent[CCHMAXPATH]; struct inode *inode; struct inode *inode_parent; struct inode *base; char *tmp; ino_t ino_no; psffsi = VDHQueryLin(parms->psffsi); psffsd = VDHQueryLin(parms->psffsd); if (parms->pcdfsi.seg) pcdfsi = VDHQueryLin(parms->pcdfsi); else pcdfsi = 0; if (parms->pcdfsd.seg) pcdfsd = VDHQueryLin(parms->pcdfsd); else pcdfsd = 0; pName = VDHQueryLin(parms->pName); pAction = VDHQueryLin(parms->pAction); if (trace_FS_OPENCREATE) { kernel_printf("FS_OPENCREATE(%s)", pName); } #ifdef FS_TRACE if (parms->ulOpenMode & OPEN_FLAGS_DASD) { fs_log("OPEN_FLAGS_DASD"); } if (parms->ulOpenMode & OPEN_FLAGS_WRITE_THROUGH) { fs_log("OPEN_FLAGS_WRITE_THROUGH"); } if (parms->ulOpenMode & OPEN_FLAGS_FAIL_ON_ERROR) { fs_log("OPEN_FLAGS_FAIL_ON_ERROR"); } if (parms->ulOpenMode & OPEN_FLAGS_NO_CACHE) { fs_log("OPEN_FLAGS_NO_CACHE"); } if (parms->ulOpenMode & OPEN_FLAGS_NOINHERIT) { fs_log("OPEN_FLAGS_NO_INHERIT"); } #endif accessmode = parms->ulOpenMode & OPEN_ACCESS_MASK; if (accessmode == OPEN_ACCESS_READONLY) { #ifdef FS_TRACE fs_log("OPEN_ACCESS_READONLY"); #endif openmode = OPENMODE_READONLY; } if (accessmode == OPEN_ACCESS_WRITEONLY) { #ifdef FS_TRACE fs_log("OPEN_ACCESS_WRITEONLY"); #endif openmode = OPENMODE_WRITEONLY; } if (accessmode == OPEN_ACCESS_READWRITE) { #ifdef FS_TRACE fs_log("OPEN_ACCESS_READWRITE"); #endif openmode = OPENMODE_READWRITE; } #ifdef FS_TRACE if (accessmode == OPEN_ACCESS_EXECUTE) { fs_log("OPEN_ACCESS_EXECUTE"); } #endif newflag = parms->openflag & OPEN_ACTION_NEW_MASK; #ifdef FS_TRACE if (newflag == OPEN_ACTION_FAIL_IF_NEW) { fs_log("OPEN_ACTION_FAIL_IF_NEW"); } if (newflag == OPEN_ACTION_CREATE_IF_NEW) { fs_log("OPEN_ACTION_CREATE_IF_NEW"); } #endif existflag = parms->openflag & OPEN_ACTION_EXIST_MASK; #ifdef FS_TRACE if (existflag == OPEN_ACTION_OPEN_IF_EXISTS) { fs_log("OPEN_ACTION_OPEN_IF_EXISTS"); } if (existflag == OPEN_ACTION_FAIL_IF_EXISTS) { fs_log("OPEN_ACTION_FAIL_IF_EXISTS"); } if (existflag == OPEN_ACTION_REPLACE_IF_EXISTS) { fs_log("OPEN_ACTION_REPLACE_IF_EXISTS"); } #endif if ((!Read_Write) && ((accessmode == OPEN_ACCESS_READWRITE) || (accessmode == OPEN_ACCESS_WRITEONLY))) { fs_log("FS_OPENCREATE() - Write access not enabled"); return ERROR_WRITE_PROTECT; } // // Direct access open of the whole device // if (parms->ulOpenMode & OPEN_FLAGS_DASD) { sb = getvolume(psffsi->sfi_hVPB); kernel_printf("OPEN_FLAGS_DASD"); if ((p_file = _open_by_inode(sb, INODE_DASD, openmode)) == 0) { kernel_printf("FS_OPENCREATE() - couldn't DASD open %s", pName); return ERROR_OPEN_FAILED; } psffsd->f = p_file; psffsi->sfi_tstamp = ST_SCREAT | ST_PCREAT; psffsi->sfi_size = p_file->f_inode->i_size; psffsi->sfi_position = p_file->f_pos; date_unix2dos(p_file->f_inode->i_ctime, &(psffsi->sfi_ctime), &(psffsi->sfi_cdate)); date_unix2dos(p_file->f_inode->i_atime, &(psffsi->sfi_atime), &(psffsi->sfi_adate)); date_unix2dos(p_file->f_inode->i_mtime, &(psffsi->sfi_mtime), &(psffsi->sfi_mdate)); return NO_ERROR; } // // Now that we treated the OPEN_FLAGS_DASD special case, lets treat the general case : // Try to open the file readonly // Success : the file exists // if !S_ISDIR && !S_ISREG => error // if OPEN_ACTION_FAIL_IF_EXISTS set => error // if OPEN_ACTION_OPEN_IF_EXISTS set // <test file attrs> // change the open mode and return OK // if OPEN_ACTION_REPLACE_IF_EXISTS set // OPEN_ACCESS_READONLY or OPEN_ACCESS_EXECUTE set => error // OPEN_ACCESS_READWRITE or OPEN_ACCESS_WRITEONLY set // truncate // change openmode and return // Failure : the file does not exist // OPEN_ACCESS_READONLY or OPEN_ACCESS_EXECUTE set => error // OPEN_ACCESS_READWRITE or OPEN_ACCESS_WRITEONLY set // if OPEN_ACTION_CREATE_IF_NEW set // try to create the file // open the file and return // if OPEN_ACTION_FAIL_IF_NEW set => error rc = ERROR_INVALID_PARAMETER; if (parms->iCurDirEnd != CURDIREND_INVALID) { tmp = pName + parms->iCurDirEnd; if ((pcdfsd->u.p_file) && (pcdfsd->u.p_file->f_magic == FILE_MAGIC)) { base = pcdfsd->u.p_file->f_inode; if (base) { sb = base->i_sb; rc = NO_ERROR; } } } else { sb = getvolume(psffsi->sfi_hVPB); if ((sb) && (sb->s_magic_internal == SUPER_MAGIC)) { tmp = skip_drive(pName); base = sb->s_mounted; if (base) { rc = NO_ERROR; } } } if (rc != NO_ERROR) { return rc; } p_file = open_by_name(base, tmp, openmode); if (p_file) { // The file exists // // If it's not a regular file or a directory we cannot open // if (!S_ISREG(p_file->f_inode->i_mode)) { // kernel_printf("Can't FS_OPENCREATE - %s is not a regular file", pName); if ((rc = vfs_close(p_file)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, FILE_TEST_C, __LINE__); return rc; } return ERROR_ACCESS_DENIED; } // // if OPEN_ACTION_FAIL_IF_EXISTS set => error // if (existflag == OPEN_ACTION_FAIL_IF_EXISTS) { #ifdef FS_TRACE fs_log("Can't FS_OPENCREATE() - File exists & OPEN_ACTION_FAIL_IF_EXISTS"); #endif if ((rc = vfs_close(p_file)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, FILE_TEST_C, __LINE__); return rc; } return ERROR_FILE_EXISTS; } // // if OPEN_ACTION_OPEN_IF_EXISTS : OK // if (existflag == OPEN_ACTION_OPEN_IF_EXISTS) { *pAction = FILE_EXISTED; } // // if OPEN_ACTION_REPLACE_IF_EXISTS : truncate // if (existflag == OPEN_ACTION_REPLACE_IF_EXISTS) { p_file->f_inode->i_size = psffsi->sfi_size; p_file->f_inode->i_op->truncate(p_file->f_inode); p_file->f_inode->i_dirt = 1; p_file->f_flags = O_TRUNC; *pAction = FILE_TRUNCATED; #if 0 psffsi->sfi_tstamp = ST_PWRITE | ST_SWRITE; #else /* * Time stamping is done by inode routines - Only propagate value. */ psffsi->sfi_tstamp = ST_PWRITE; #endif } } else { // The file doesn't exist ExtractPath(pName, __StackToFlat(parent)); ExtractName(pName, __StackToFlat(component)); // // We try to open the parent dir // if ((dir = open_by_name(sb->s_mounted, Skip_drive(__StackToFlat(parent)), OPENMODE_READONLY)) == 0) { // kernel_printf("FS_OPENCREATE() - The parent directory %s doesn't seem to exist", parent); return ERROR_PATH_NOT_FOUND; } // // The parent dir exists // // // If the file is open for execution : error (it doesn't even exist) // if (accessmode == OPEN_ACCESS_EXECUTE) { #ifdef FS_TRACE fs_log("Can't FS_OPENCREATE() - File doesn't exist & OPEN_ACCESS_EXECUTE"); #endif if ((rc = vfs_close(dir)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, FILE_TEST_C, __LINE__); return rc; } return ERROR_FILE_NOT_FOUND; } // // If the file is open for writing or readwrite ... // if ((accessmode == OPEN_ACCESS_READONLY) || (accessmode == OPEN_ACCESS_READWRITE) || (accessmode == OPEN_ACCESS_WRITEONLY)) { if (newflag == OPEN_ACTION_FAIL_IF_NEW) { #ifdef FS_TRACE fs_log("Can't FS_OPENCREATE() - File doesn't exist & OPEN_ACTION_FAIL_IF_NEW"); #endif if ((rc = vfs_close(dir)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, FILE_TEST_C, __LINE__); return rc; } return ERROR_OPEN_FAILED; } if (newflag == OPEN_ACTION_CREATE_IF_NEW) { // ino_no = dir->f_inode->i_ino; inode_parent = dir->f_inode; inode_parent->i_count++; if ((rc = vfs_close(dir)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, THISFILE, __LINE__); return rc; } // inode_parent = iget(sb, ino_no); inode_parent->i_count++; down(&inode_parent->i_sem); rc = inode_parent->i_op->create(inode_parent, __StackToFlat(component), strlen(component), S_IRWXU | S_IFREG, __StackToFlat(&inode)); up(&inode_parent->i_sem); if (rc) { kernel_printf("Couldn't create %s", pName); iput(inode_parent); return rc; } ino_no = inode->i_ino; iput(inode_parent); iput(inode); if ((p_file = _open_by_inode(sb, ino_no, openmode)) == 0) { kernel_printf("open_by_inode(%lu) failed in FS_OPENCREATE", ino_no); return ERROR_OPEN_FAILED; } p_file->f_inode->i_size = psffsi->sfi_size; p_file->f_inode->i_dirt = 1; p_file->f_flags = O_CREAT; *pAction = FILE_CREATED; #if 0 psffsi->sfi_tstamp = ST_SCREAT | ST_PCREAT | ST_PWRITE | ST_SWRITE; #else /* * Time stamping is done by inode routines - Only propagate value. */ psffsi->sfi_tstamp = ST_PCREAT | ST_PWRITE; #endif } } } psffsd->f = p_file; /* * Time stamping is done by inode routines - Only propagate value. */ #if 0 psffsi->sfi_tstamp |= ST_PREAD | ST_SREAD; #else /* * Time stamping is done by inode routines - Only propagate value. */ psffsi->sfi_tstamp |= ST_PREAD; #endif psffsi->sfi_size = p_file->f_inode->i_size; psffsi->sfi_position = p_file->f_pos; // kernel_printf("date = %u/%u/%u", (pCommon->dateCreate) & 31, (pCommon->dateCreate >> 5) & 15 , (pCommon->dateCreate) >> 9); date_unix2dos(p_file->f_inode->i_ctime, &(psffsi->sfi_ctime), &(psffsi->sfi_cdate)); date_unix2dos(p_file->f_inode->i_atime, &(psffsi->sfi_atime), &(psffsi->sfi_adate)); date_unix2dos(p_file->f_inode->i_mtime, &(psffsi->sfi_mtime), &(psffsi->sfi_mdate)); psffsi->sfi_DOSattr = (unsigned char)Linux_To_DOS_Attrs(p_file->f_inode, __StackToFlat(component)); if (write_through_support) { if ((parms->ulOpenMode & OPEN_FLAGS_WRITE_THROUGH) || (parms->ulOpenMode & OPEN_FLAGS_NO_CACHE)) { p_file->f_flags |= O_SYNC; p_file->f_inode->i_flags |= MS_SYNCHRONOUS; } } return NO_ERROR; }
/* * Construct a znode+inode and initialize. * * This does not do a call to dmu_set_user() that is * up to the caller to do, in case you don't want to * return the znode */ static znode_t * zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz, dmu_object_type_t obj_type, uint64_t obj, sa_handle_t *hdl, struct inode *dip) { znode_t *zp; struct inode *ip; uint64_t mode; uint64_t parent; sa_bulk_attr_t bulk[9]; int count = 0; ASSERT(zsb != NULL); ip = new_inode(zsb->z_sb); if (ip == NULL) return (NULL); zp = ITOZ(ip); ASSERT(zp->z_dirlocks == NULL); ASSERT3P(zp->z_acl_cached, ==, NULL); ASSERT3P(zp->z_xattr_cached, ==, NULL); ASSERT3P(zp->z_xattr_parent, ==, NULL); zp->z_moved = 0; zp->z_sa_hdl = NULL; zp->z_unlinked = 0; zp->z_atime_dirty = 0; zp->z_mapcnt = 0; zp->z_id = db->db_object; zp->z_blksz = blksz; zp->z_seq = 0x7A4653; zp->z_sync_cnt = 0; zp->z_is_zvol = B_FALSE; zp->z_is_mapped = B_FALSE; zp->z_is_ctldir = B_FALSE; zp->z_is_stale = B_FALSE; zfs_znode_sa_init(zsb, zp, db, obj_type, hdl); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zsb), NULL, &mode, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zsb), NULL, &zp->z_gen, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zsb), NULL, &zp->z_size, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zsb), NULL, &zp->z_links, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb), NULL, &zp->z_pflags, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zsb), NULL, &parent, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zsb), NULL, &zp->z_atime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zsb), NULL, &zp->z_uid, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zsb), NULL, &zp->z_gid, 8); if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) { if (hdl == NULL) sa_handle_destroy(zp->z_sa_hdl); goto error; } zp->z_mode = mode; /* * xattr znodes hold a reference on their unique parent */ if (dip && zp->z_pflags & ZFS_XATTR) { igrab(dip); zp->z_xattr_parent = ITOZ(dip); } ip->i_ino = obj; zfs_inode_update(zp); zfs_inode_set_ops(zsb, ip); /* * The only way insert_inode_locked() can fail is if the ip->i_ino * number is already hashed for this super block. This can never * happen because the inode numbers map 1:1 with the object numbers. * * The one exception is rolling back a mounted file system, but in * this case all the active inode are unhashed during the rollback. */ VERIFY3S(insert_inode_locked(ip), ==, 0); mutex_enter(&zsb->z_znodes_lock); list_insert_tail(&zsb->z_all_znodes, zp); zsb->z_nr_znodes++; membar_producer(); mutex_exit(&zsb->z_znodes_lock); unlock_new_inode(ip); return (zp); error: unlock_new_inode(ip); iput(ip); return (NULL); }
asmlinkage int sys_acct(const char *name) { struct inode *inode = (struct inode *)0; char *tmp; int error; if (!suser()) return -EPERM; if (name == (char *)0) { if (acct_active) { if (acct_file.f_op->release) acct_file.f_op->release(acct_file.f_inode, &acct_file); if (acct_file.f_inode != (struct inode *) 0) iput(acct_file.f_inode); acct_active = 0; } return 0; } else { if (!acct_active) { if ((error = getname(name, &tmp)) != 0) return (error); error = open_namei(tmp, O_RDWR, 0600, &inode, 0); putname(tmp); if (error) return (error); if (!S_ISREG(inode->i_mode)) { iput(inode); return -EACCES; } if (!inode->i_op || !inode->i_op->default_file_ops || !inode->i_op->default_file_ops->write) { iput(inode); return -EIO; } acct_file.f_mode = 3; acct_file.f_flags = 0; acct_file.f_count = 1; acct_file.f_inode = inode; acct_file.f_pos = inode->i_size; acct_file.f_reada = 0; acct_file.f_op = inode->i_op->default_file_ops; if (acct_file.f_op->open) if (acct_file.f_op->open(acct_file.f_inode, &acct_file)) { iput(inode); return -EIO; } acct_active = 1; return 0; } else return -EBUSY; } }
struct inode *amfs_iget(struct super_block *sb, struct inode *lower_inode) { struct amfs_inode_info *info; struct inode *inode; /* the new inode to return */ int err; inode = iget5_locked(sb, /* our superblock */ /* * hashval: we use inode number, but we can * also use "(unsigned long)lower_inode" * instead. */ lower_inode->i_ino, /* hashval */ amfs_inode_test, /* inode comparison function */ amfs_inode_set, /* inode init function */ lower_inode); /* data passed to test+set fxns */ // printk("\n lookup.c->struct inode amfs_iget"); //aditi if (!inode) { err = -EACCES; iput(lower_inode); return ERR_PTR(err); } /* if found a cached inode, then just return it */ if (!(inode->i_state & I_NEW)) return inode; /* initialize new inode */ info = AMFS_I(inode); inode->i_ino = lower_inode->i_ino; if (!igrab(lower_inode)) { err = -ESTALE; return ERR_PTR(err); } amfs_set_lower_inode(inode, lower_inode); inode->i_version++; /* use different set of inode ops for symlinks & directories */ if (S_ISDIR(lower_inode->i_mode)) inode->i_op = &amfs_dir_iops; else if (S_ISLNK(lower_inode->i_mode)) inode->i_op = &amfs_symlink_iops; else inode->i_op = &amfs_main_iops; /* use different set of file ops for directories */ if (S_ISDIR(lower_inode->i_mode)) inode->i_fop = &amfs_dir_fops; else inode->i_fop = &amfs_main_fops; inode->i_mapping->a_ops = &amfs_aops; inode->i_atime.tv_sec = 0; inode->i_atime.tv_nsec = 0; inode->i_mtime.tv_sec = 0; inode->i_mtime.tv_nsec = 0; inode->i_ctime.tv_sec = 0; inode->i_ctime.tv_nsec = 0; /* properly initialize special inodes */ if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) || S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode)) init_special_inode(inode, lower_inode->i_mode, lower_inode->i_rdev); /* all well, copy inode attributes */ fsstack_copy_attr_all(inode, lower_inode); fsstack_copy_inode_size(inode, lower_inode); unlock_new_inode(inode); return inode; }
static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct dentry *ret, *parent; struct inode *inode; struct super_block *sb; int err, npositive, lc_idx; IMustLock(dir); sb = dir->i_sb; err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ret = ERR_PTR(err); if (unlikely(err)) goto out; ret = ERR_PTR(-ENAMETOOLONG); if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) goto out_si; err = au_di_init(dentry); ret = ERR_PTR(err); if (unlikely(err)) goto out_si; inode = NULL; npositive = 0; /* suppress a warning */ parent = dentry->d_parent; /* dir inode is locked */ di_read_lock_parent(parent, AuLock_IR); err = au_alive_dir(parent); if (!err) err = au_digen_test(parent, au_sigen(sb)); if (!err) { npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd); err = npositive; } di_read_unlock(parent, AuLock_IR); ret = ERR_PTR(err); if (unlikely(err < 0)) goto out_unlock; if (npositive) { inode = au_new_inode(dentry, /*must_new*/0); ret = (void *)inode; } if (IS_ERR(inode)) { inode = NULL; goto out_unlock; } ret = d_splice_alias(inode, dentry); if (unlikely(IS_ERR(ret) && inode)) { ii_write_unlock(inode); lc_idx = AuLcNonDir_IIINFO; if (S_ISLNK(inode->i_mode)) lc_idx = AuLcSymlink_IIINFO; else if (S_ISDIR(inode->i_mode)) lc_idx = AuLcDir_IIINFO; au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx); iput(inode); } out_unlock: di_write_unlock(dentry); if (unlikely(IS_ERR(ret) && inode)) { lc_idx = AuLcNonDir_DIINFO; if (S_ISLNK(inode->i_mode)) lc_idx = AuLcSymlink_DIINFO; else if (S_ISDIR(inode->i_mode)) lc_idx = AuLcDir_DIINFO; au_rw_class(&au_di(dentry)->di_rwsem, au_lc_key + lc_idx); } out_si: si_read_unlock(sb); out: return ret; }
static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { int retval; struct inode *inode; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); struct reiserfs_transaction_handle th; struct reiserfs_security_handle security; dquot_initialize(dir); if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); jbegin_count += reiserfs_cache_default_acl(dir); retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); if (retval < 0) { drop_new_inode(inode); return retval; } jbegin_count += retval; reiserfs_write_lock(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } retval = reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, inode, &security); if (retval) goto out_failed; inode->i_op = &reiserfs_file_inode_operations; inode->i_fop = &reiserfs_file_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; inode->i_nlink--; reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; unlock_new_inode(inode); iput(inode); goto out_failed; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); d_instantiate(dentry, inode); unlock_new_inode(inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: reiserfs_write_unlock(dir->i_sb); return retval; }
static void do_directory(char *path, struct cramfs_inode *i) { int pathlen = strlen(path); int count = i->size; unsigned long offset = i->offset << 2; char *newpath = malloc(pathlen + 256); if (!newpath) { die(FSCK_ERROR, 1, "malloc failed"); } if (offset == 0 && count != 0) { die(FSCK_UNCORRECTED, 0, "directory inode has zero offset and non-zero size: %s", path); } if (offset != 0 && offset < start_dir) { start_dir = offset; } /* TODO: Do we need to check end_dir for empty case? */ memcpy(newpath, path, pathlen); newpath[pathlen] = '/'; pathlen++; if (opt_verbose) { print_node('d', i, path); } if (opt_extract) { if (mkdir(path, i->mode) < 0) { die(FSCK_ERROR, 1, "mkdir failed: %s", path); } change_file_status(path, i); } while (count > 0) { struct cramfs_inode *child = iget(offset); int size; int newlen = child->namelen << 2; size = sizeof(struct cramfs_inode) + newlen; count -= size; offset += sizeof(struct cramfs_inode); memcpy(newpath + pathlen, romfs_read(offset), newlen); newpath[pathlen + newlen] = 0; if (newlen == 0) { die(FSCK_UNCORRECTED, 0, "filename length is zero"); } if ((pathlen + newlen) - strlen(newpath) > 3) { die(FSCK_UNCORRECTED, 0, "bad filename length"); } expand_fs(newpath, child); offset += newlen; if (offset <= start_dir) { die(FSCK_UNCORRECTED, 0, "bad inode offset"); } if (offset > end_dir) { end_dir = offset; } iput(child); /* free(child) */ } free(newpath); }