diff --git a/fs/inode.c b/fs/inode.c index 26cdb11..9d7da59 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -524,7 +524,7 @@ repeat: */ struct inode *new_inode(struct super_block *sb) { - static unsigned long last_ino; + static unsigned int last_ino; struct inode * inode; spin_lock_prefetch(&inode_lock); @@ -683,7 +683,7 @@ static unsigned long hash(struct super_b */ ino_t iunique(struct super_block *sb, ino_t max_reserved) { - static ino_t counter; + static unsigned int counter; struct inode *inode; struct hlist_head * head; ino_t res; diff --git a/fs/libfs.c b/fs/libfs.c index bd08e0e..75f8371 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -20,6 +20,18 @@ int simple_getattr(struct vfsmount *mnt, return 0; } +/* same as simple_getattr, but get a unique inode number and hash the inode + * prior to doing the getattr */ +int lazy_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat) +{ + if (dentry->d_inode->i_ino == 0) { + dentry->d_inode->i_ino = iunique(dentry->d_sb, 0); + insert_inode_hash(dentry->d_inode); + } + return simple_getattr(mnt, dentry, stat); +} + int simple_statfs(struct dentry *dentry, struct kstatfs *buf) { buf->f_type = dentry->d_sb->s_magic; @@ -639,3 +651,4 @@ EXPORT_SYMBOL_GPL(simple_attr_open); EXPORT_SYMBOL_GPL(simple_attr_close); EXPORT_SYMBOL_GPL(simple_attr_read); EXPORT_SYMBOL_GPL(simple_attr_write); +EXPORT_SYMBOL_GPL(lazy_getattr); diff --git a/fs/pipe.c b/fs/pipe.c index b1626f2..6910081 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -837,6 +837,10 @@ static struct dentry_operations pipefs_d .d_delete = pipefs_delete_dentry, }; +static struct inode_operations pipefs_inode_operations = { + .getattr = lazy_getattr, +}; + static struct inode * get_pipe_inode(void) { struct inode *inode = new_inode(pipe_mnt->mnt_sb); @@ -845,6 +849,10 @@ static struct inode * get_pipe_inode(voi if (!inode) goto fail_inode; + /* reset this to 0 to cue lazy_getattr to give us a unique i_ino value + * if this ever has a getattr run against it */ + inode->i_ino = 0; + pipe = alloc_pipe_info(inode); if (!pipe) goto fail_iput; @@ -852,6 +860,7 @@ static struct inode * get_pipe_inode(voi pipe->readers = pipe->writers = 1; inode->i_fop = &rdwr_pipe_fops; + inode->i_op = &pipefs_inode_operations; /* * Mark the inode dirty from the very beginning, @@ -998,7 +1007,12 @@ static int pipefs_get_sb(struct file_sys int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC, mnt); + static struct super_operations default_ops = { + .statfs = simple_statfs, + .drop_inode = generic_delete_inode, + }; + + return get_sb_pseudo(fs_type, "pipe:", &default_ops, PIPEFS_MAGIC, mnt); } static struct file_system_type pipe_fs_type = { diff --git a/include/linux/fs.h b/include/linux/fs.h index 2fe6e3f..41571c1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1885,6 +1885,7 @@ extern int dcache_dir_close(struct inode extern loff_t dcache_dir_lseek(struct file *, loff_t, int); extern int dcache_readdir(struct file *, void *, filldir_t); extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); +extern int lazy_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int simple_statfs(struct dentry *, struct kstatfs *); extern int simple_link(struct dentry *, struct inode *, struct dentry *); extern int simple_unlink(struct inode *, struct dentry *);