/* * 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 wrapfs_evict_inode(struct inode *inode) { struct inode *lower_inode; truncate_inode_pages(&inode->i_data, 0); end_writeback(inode); /* * Decrement a reference to a lower_inode, which was incremented * by our read_inode when it was created initially. */ lower_inode = wrapfs_lower_inode(inode); wrapfs_set_lower_inode(inode, NULL); iput(lower_inode); }
struct inode *wrapfs_iget(struct super_block *sb, struct inode *lower_inode) { struct wrapfs_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 */ wrapfs_inode_test, /* inode comparison function */ wrapfs_inode_set, /* inode init function */ lower_inode); /* data passed to test+set fxns */ 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 = WRAPFS_I(inode); inode->i_ino = lower_inode->i_ino; if (!igrab(lower_inode)) { err = -ESTALE; return ERR_PTR(err); } wrapfs_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 = &wrapfs_dir_iops; else if (S_ISLNK(lower_inode->i_mode)) inode->i_op = &wrapfs_symlink_iops; else inode->i_op = &wrapfs_main_iops; /* use different set of file ops for directories */ if (S_ISDIR(lower_inode->i_mode)) inode->i_fop = &wrapfs_dir_fops; else inode->i_fop = &wrapfs_main_fops; inode->i_mapping->a_ops = &wrapfs_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; }