/* * Called by iput() when the inode reference count reached zero * and the inode is not hashed anywhere. Used to clear anything * that needs to be, before the inode is completely destroyed and put * on the inode free list. */ STATIC void mini_fo_clear_inode(inode_t *inode) { /* * Decrement a reference to a hidden_inode, which was incremented * by our read_inode when it was created initially. */ /* release the wol_list */ if(S_ISDIR(inode->i_mode)) { __meta_put_lists(inode); } /* mk: fan out fun */ if(itohi(inode)) iput(itohi(inode)); if(itohi2(inode)) iput(itohi2(inode)); // XXX: why this assertion fails? // because it doesn't like us // ASSERT((inode->i_state & I_DIRTY) == 0); kfree(itopd(inode)); __itopd(inode) = NULL; }
STATIC void mini_fo_read_inode(inode_t *inode) { static struct address_space_operations mini_fo_empty_aops; __itopd(inode) = kmalloc(sizeof(struct mini_fo_inode_info), GFP_KERNEL); if (!itopd(inode)) { printk("<0>%s:%s:%d: No kernel memory!\n", __FILE__, __FUNCTION__, __LINE__); ASSERT(NULL); } itohi(inode) = NULL; itohi2(inode) = NULL; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) inode->i_version++; #else inode->i_version = ++event; /* increment inode version */ #endif inode->i_op = &mini_fo_main_iops; inode->i_fop = &mini_fo_main_fops; #if 0 /* * XXX: To export a file system via NFS, it has to have the * FS_REQUIRES_DEV flag, so turn it on. But should we inherit it from * the lower file system, or can we allow our file system to be exported * even if the lower one cannot be natively exported. */ inode->i_sb->s_type->fs_flags |= FS_REQUIRES_DEV; /* * OK, the above was a hack, which is now turned off because it may * cause a panic/oops on some systems. The correct way to export a * "nodev" filesystem is via using nfs-utils > 1.0 and the "fsid=" export * parameter, which requires 2.4.20 or later. */ #endif /* I don't think ->a_ops is ever allowed to be NULL */ inode->i_mapping->a_ops = &mini_fo_empty_aops; }
int create_sto_reg_file(dentry_t *dentry, int mode) #endif { int err = 0; inode_t *dir; dentry_t *hidden_sto_dentry; dentry_t *hidden_sto_dir_dentry; if(exists_in_storage(dentry)) { printk(KERN_CRIT "mini_fo: create_sto_file: wrong type or state.\n"); err = -EINVAL; goto out; } err = get_neg_sto_dentry(dentry); if (err) { printk(KERN_CRIT "mini_fo: create_sto_file: ERROR getting neg. sto dentry.\n"); goto out; } dir = dentry->d_parent->d_inode; hidden_sto_dentry = dtohd2(dentry); /* lock parent */ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); err = PTR_ERR(hidden_sto_dir_dentry); if (IS_ERR(hidden_sto_dir_dentry)) goto out; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) err = vfs_create(hidden_sto_dir_dentry->d_inode, hidden_sto_dentry, mode, nd); #else err = vfs_create(hidden_sto_dir_dentry->d_inode, hidden_sto_dentry, mode); #endif if(err) { printk(KERN_CRIT "mini_fo: create_sto_file: ERROR creating sto file.\n"); goto out_lock; } if(!dtohd2(dentry)->d_inode) { printk(KERN_CRIT "mini_fo: create_sto_file: ERROR creating sto file [2].\n"); err = -EINVAL; goto out_lock; } /* interpose the new inode */ if(dtost(dentry) == DELETED) { dtost(dentry) = DEL_REWRITTEN; err = mini_fo_tri_interpose(NULL, hidden_sto_dentry, dentry, dir->i_sb, 0); if(err) goto out_lock; } else if(dtost(dentry) == NON_EXISTANT) { dtost(dentry) = CREATED; err = mini_fo_tri_interpose(dtohd(dentry), hidden_sto_dentry, dentry, dir->i_sb, 0); if(err) goto out_lock; } else if(dtost(dentry) == UNMODIFIED) { dtost(dentry) = MODIFIED; /* interpose on new inode */ if(itohi2(dentry->d_inode) != NULL) { printk(KERN_CRIT "mini_fo: create_sto_file: invalid inode detected.\n"); err = -EINVAL; goto out_lock; } itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode); } fist_copy_attr_timesizes(dentry->d_parent->d_inode, hidden_sto_dir_dentry->d_inode); out_lock: dput(hidden_sto_dir_dentry); out: return err; }
int create_sto_nod(dentry_t *dentry, int mode, int dev) #endif { int err = 0; inode_t *dir; dentry_t *hidden_sto_dentry; dentry_t *hidden_sto_dir_dentry; if(exists_in_storage(dentry)) { err = -EEXIST; goto out; } err = get_neg_sto_dentry(dentry); if (err) { printk(KERN_CRIT "mini_fo: create_sto_nod: ERROR getting neg. sto dentry.\n"); goto out; } dir = dentry->d_parent->d_inode; hidden_sto_dentry = dtohd2(dentry); /* lock parent */ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); err = PTR_ERR(hidden_sto_dir_dentry); if (IS_ERR(hidden_sto_dir_dentry)) goto out; err = vfs_mknod(hidden_sto_dir_dentry->d_inode, hidden_sto_dentry, mode, dev); if(err) goto out_lock; if(!dtohd2(dentry)->d_inode) { printk(KERN_CRIT "mini_fo: create_sto_nod: creating storage inode failed [1].\n"); err = -EINVAL; /* return something indicating failure */ goto out_lock; } /* interpose the new inode */ if(dtost(dentry) == DELETED) { dtost(dentry) = DEL_REWRITTEN; err = mini_fo_tri_interpose(NULL, hidden_sto_dentry, dentry, dir->i_sb, 0); if(err) goto out_lock; } else if(dtost(dentry) == NON_EXISTANT) { dtost(dentry) = CREATED; err = mini_fo_tri_interpose(dtohd(dentry), hidden_sto_dentry, dentry, dir->i_sb, 0); if(err) goto out_lock; } else if(dtost(dentry) == UNMODIFIED) { dtost(dentry) = MODIFIED; /* interpose on new inode */ if(itohi2(dentry->d_inode) != NULL) { printk(KERN_CRIT "mini_fo: create_sto_nod: error, invalid inode detected.\n"); err = -EINVAL; goto out_lock; } itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode); } fist_copy_attr_timesizes(dir, hidden_sto_dir_dentry->d_inode); out_lock: dput(hidden_sto_dir_dentry); out: return err; }
/* create the sto dir, setup states */ int create_sto_dir(dentry_t *dentry, int mode) { int err = 0; inode_t *dir; dentry_t *hidden_sto_dentry; dentry_t *hidden_sto_dir_dentry; /* had to take the "!S_ISDIR(mode))" check out, because it failed */ if(exists_in_storage(dentry)) { printk(KERN_CRIT "mini_fo: create_sto_dir: wrong type or state.\\ n"); err = -EINVAL; goto out; } err = get_neg_sto_dentry(dentry); if(err) { err = -EINVAL; goto out; } dir = dentry->d_parent->d_inode; hidden_sto_dentry = dtohd2(dentry); /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); err = PTR_ERR(hidden_sto_dir_dentry); if (IS_ERR(hidden_sto_dir_dentry)) goto out; err = vfs_mkdir(hidden_sto_dir_dentry->d_inode, hidden_sto_dentry, mode); if(err) { printk(KERN_CRIT "mini_fo: create_sto_dir: ERROR creating sto dir.\n"); goto out_lock; } if(!dtohd2(dentry)->d_inode) { printk(KERN_CRIT "mini_fo: create_sto_dir: ERROR creating sto dir [2].\n"); err = -EINVAL; goto out_lock; } /* interpose the new inode */ if(dtost(dentry) == DELETED) { dtost(dentry) = DEL_REWRITTEN; err = mini_fo_tri_interpose(NULL, hidden_sto_dentry, dentry, dir->i_sb, 0); if(err) goto out_lock; } else if(dtopd(dentry)->state == NON_EXISTANT) { dtopd(dentry)->state = CREATED; err = mini_fo_tri_interpose(dtohd(dentry), hidden_sto_dentry, dentry, dir->i_sb, 0); if(err) goto out_lock; } else if(dtopd(dentry)->state == UNMODIFIED) { dtopd(dentry)->state = MODIFIED; /* interpose on new inode */ if(itohi2(dentry->d_inode) != NULL) { printk(KERN_CRIT "mini_fo: create_sto_dir: ERROR, invalid inode detected.\n"); err = -EINVAL; goto out_lock; } itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode); } fist_copy_attr_timesizes(dir, hidden_sto_dir_dentry->d_inode); /* initalize the wol list */ itopd(dentry->d_inode)->deleted_list_size = -1; itopd(dentry->d_inode)->renamed_list_size = -1; meta_build_lists(dentry); out_lock: /* was: unlock_dir(hidden_sto_dir_dentry); */ dput(hidden_sto_dir_dentry); out: return err; }