aboutsummaryrefslogtreecommitdiff
path: root/fs/isofs/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/isofs/export.c')
-rw-r--r--fs/isofs/export.c59
1 files changed, 18 insertions, 41 deletions
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
index bb219138331..12088d8de3f 100644
--- a/fs/isofs/export.c
+++ b/fs/isofs/export.c
@@ -9,7 +9,7 @@
*
* The following files are helpful:
*
- * Documentation/filesystems/Exporting
+ * Documentation/filesystems/nfs/Exporting
* fs/exportfs/expfs.c.
*/
@@ -22,7 +22,7 @@ isofs_export_iget(struct super_block *sb,
__u32 generation)
{
struct inode *inode;
- struct dentry *result;
+
if (block == 0)
return ERR_PTR(-ESTALE);
inode = isofs_iget(sb, block, offset);
@@ -32,12 +32,7 @@ isofs_export_iget(struct super_block *sb,
iput(inode);
return ERR_PTR(-ESTALE);
}
- result = d_alloc_anon(inode);
- if (!result) {
- iput(inode);
- return ERR_PTR(-ENOMEM);
- }
- return result;
+ return d_obtain_alias(inode);
}
/* This function is surprisingly simple. The trick is understanding
@@ -51,7 +46,6 @@ static struct dentry *isofs_export_get_parent(struct dentry *child)
unsigned long parent_offset = 0;
struct inode *child_inode = child->d_inode;
struct iso_inode_info *e_child_inode = ISOFS_I(child_inode);
- struct inode *parent_inode = NULL;
struct iso_directory_record *de = NULL;
struct buffer_head * bh = NULL;
struct dentry *rv = NULL;
@@ -104,38 +98,20 @@ static struct dentry *isofs_export_get_parent(struct dentry *child)
/* Normalize */
isofs_normalize_block_and_offset(de, &parent_block, &parent_offset);
- /* Get the inode. */
- parent_inode = isofs_iget(child_inode->i_sb,
- parent_block,
- parent_offset);
- if (IS_ERR(parent_inode)) {
- rv = ERR_CAST(parent_inode);
- if (rv != ERR_PTR(-ENOMEM))
- rv = ERR_PTR(-EACCES);
- goto out;
- }
-
- /* Allocate the dentry. */
- rv = d_alloc_anon(parent_inode);
- if (rv == NULL) {
- rv = ERR_PTR(-ENOMEM);
- goto out;
- }
-
+ rv = d_obtain_alias(isofs_iget(child_inode->i_sb, parent_block,
+ parent_offset));
out:
- if (bh) {
+ if (bh)
brelse(bh);
- }
return rv;
}
static int
-isofs_export_encode_fh(struct dentry *dentry,
+isofs_export_encode_fh(struct inode *inode,
__u32 *fh32,
int *max_len,
- int connectable)
+ struct inode *parent)
{
- struct inode * inode = dentry->d_inode;
struct iso_inode_info * ei = ISOFS_I(inode);
int len = *max_len;
int type = 1;
@@ -147,24 +123,25 @@ isofs_export_encode_fh(struct dentry *dentry,
* offset of the inode and the upper 16 bits of fh32[1] to
* hold the offset of the parent.
*/
-
- if (len < 3 || (connectable && len < 5))
- return 255;
+ if (parent && (len < 5)) {
+ *max_len = 5;
+ return FILEID_INVALID;
+ } else if (len < 3) {
+ *max_len = 3;
+ return FILEID_INVALID;
+ }
len = 3;
fh32[0] = ei->i_iget5_block;
fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */
+ fh16[3] = 0; /* avoid leaking uninitialized data */
fh32[2] = inode->i_generation;
- if (connectable && !S_ISDIR(inode->i_mode)) {
- struct inode *parent;
+ if (parent) {
struct iso_inode_info *eparent;
- spin_lock(&dentry->d_lock);
- parent = dentry->d_parent->d_inode;
eparent = ISOFS_I(parent);
fh32[3] = eparent->i_iget5_block;
fh16[3] = (__u16)eparent->i_iget5_offset; /* fh16 [sic] */
fh32[4] = parent->i_generation;
- spin_unlock(&dentry->d_lock);
len = 5;
type = 2;
}
@@ -198,7 +175,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb,
{
struct isofs_fid *ifid = (struct isofs_fid *)fid;
- if (fh_type != 2)
+ if (fh_len < 2 || fh_type != 2)
return NULL;
return isofs_export_iget(sb,