diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index d8bfbee..60bd3f3 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -354,6 +354,31 @@ out: return err; } +struct dentry *ufs_get_parent(struct dentry *child) +{ + unsigned long ino; + struct dentry *parent; + struct inode *inode; + struct dentry dotdot; + + dotdot.d_name.name = ".."; + dotdot.d_name.len = 2; + + ino = ufs_inode_by_name(child->d_inode, &dotdot); + if (!ino) + return ERR_PTR(-ENOENT); + inode = iget(child->d_inode->i_sb, ino); + + if (!inode) + return ERR_PTR(-EACCES); + parent = d_alloc_anon(inode); + if (!parent) { + iput(inode); + parent = ERR_PTR(-ENOMEM); + } + return parent; +} + const struct inode_operations ufs_dir_inode_operations = { .create = ufs_create, .lookup = ufs_lookup, diff --git a/fs/ufs/super.c b/fs/ufs/super.c index c78c04f..7a0d6b5 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -90,6 +90,7 @@ #include #include #include +#include #include "ufs.h" #include "swab.h" @@ -218,6 +219,7 @@ static void ufs_print_cylinder_stuff(struct super_block *sb, #endif /* CONFIG_UFS_DEBUG */ static const struct super_operations ufs_super_ops; +static const struct export_operations ufs_export_ops; static char error_buf[1024]; @@ -978,6 +980,7 @@ magic_found: * Read ufs_super_block into internal data structures */ sb->s_op = &ufs_super_ops; + sb->s_export_op = &ufs_export_ops; sb->dq_op = NULL; /***/ sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic); @@ -1340,6 +1343,52 @@ static const struct super_operations ufs_super_ops = { #endif }; +static struct inode *ufs_nfs_get_inode(struct super_block *sb, + u64 ino, u32 generation) +{ + struct inode *inode; + + if (!(ino > 1 && + ino < UFS_SB(sb)->s_uspi->s_ipg * UFS_SB(sb)->s_uspi->s_ncg)) + return ERR_PTR(-ESTALE); + + /* iget isn't really right if the inode is currently unallocated!! + * ext2_read_inode currently does appropriate checks, but + * it might be "neater" to call ext2_get_inode first and check + * if the inode is valid..... + */ + inode = iget(sb, ino); + if (inode == NULL) + return ERR_PTR(-ENOMEM); + if (is_bad_inode(inode) || + (generation && inode->i_generation != generation)) { + /* we didn't find the right inode.. */ + iput(inode); + return ERR_PTR(-ESTALE); + } + return inode; +} + +static struct dentry *ufs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + ufs_nfs_get_inode); +} + +static struct dentry *ufs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + ufs_nfs_get_inode); +} + +static const struct export_operations ufs_export_ops = { + .fh_to_dentry = ufs_fh_to_dentry, + .fh_to_parent = ufs_fh_to_parent, + .get_parent = ufs_get_parent, +}; + #ifdef CONFIG_QUOTA /* Read data from quotafile - avoid pagecache and such because we cannot afford diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 7faa4cd..973f717 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -116,6 +116,7 @@ extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf /* namei.c */ extern const struct file_operations ufs_dir_operations; +extern struct dentry *ufs_get_parent(struct dentry *); /* super.c */ extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));