4 * (C) 2004 Paul Serice - The new inode scheme requires switching
5 * from iget() to iget5_locked() which means
6 * the NFS export operations have to be hand
7 * coded because the default routines rely on
10 * The following files are helpful:
12 * Documentation/filesystems/Exporting
13 * fs/exportfs/expfs.c.
18 static struct dentry
*
19 isofs_export_iget(struct super_block
*sb
,
25 struct dentry
*result
;
27 return ERR_PTR(-ESTALE
);
28 inode
= isofs_iget(sb
, block
, offset
);
30 return ERR_PTR(-ENOMEM
);
31 if (is_bad_inode(inode
)
32 || (generation
&& inode
->i_generation
!= generation
))
35 return ERR_PTR(-ESTALE
);
37 result
= d_alloc_anon(inode
);
40 return ERR_PTR(-ENOMEM
);
45 static struct dentry
*
46 isofs_export_get_dentry(struct super_block
*sb
, void *vobjp
)
49 unsigned long block
= objp
[0];
50 unsigned long offset
= objp
[1];
51 __u32 generation
= objp
[2];
52 return isofs_export_iget(sb
, block
, offset
, generation
);
55 /* This function is surprisingly simple. The trick is understanding
56 * that "child" is always a directory. So, to find its parent, you
57 * simply need to find its ".." entry, normalize its block and offset,
58 * and return the underlying inode. See the comments for
59 * isofs_normalize_block_and_offset(). */
60 static struct dentry
*isofs_export_get_parent(struct dentry
*child
)
62 unsigned long parent_block
= 0;
63 unsigned long parent_offset
= 0;
64 struct inode
*child_inode
= child
->d_inode
;
65 struct iso_inode_info
*e_child_inode
= ISOFS_I(child_inode
);
66 struct inode
*parent_inode
= NULL
;
67 struct iso_directory_record
*de
= NULL
;
68 struct buffer_head
* bh
= NULL
;
69 struct dentry
*rv
= NULL
;
71 /* "child" must always be a directory. */
72 if (!S_ISDIR(child_inode
->i_mode
)) {
73 printk(KERN_ERR
"isofs: isofs_export_get_parent(): "
74 "child is not a directory!\n");
75 rv
= ERR_PTR(-EACCES
);
79 /* It is an invariant that the directory offset is zero. If
80 * it is not zero, it means the directory failed to be
81 * normalized for some reason. */
82 if (e_child_inode
->i_iget5_offset
!= 0) {
83 printk(KERN_ERR
"isofs: isofs_export_get_parent(): "
84 "child directory not normalized!\n");
85 rv
= ERR_PTR(-EACCES
);
89 /* The child inode has been normalized such that its
90 * i_iget5_block value points to the "." entry. Fortunately,
91 * the ".." entry is located in the same block. */
92 parent_block
= e_child_inode
->i_iget5_block
;
94 /* Get the block in question. */
95 bh
= sb_bread(child_inode
->i_sb
, parent_block
);
97 rv
= ERR_PTR(-EACCES
);
101 /* This is the "." entry. */
102 de
= (struct iso_directory_record
*)bh
->b_data
;
104 /* The ".." entry is always the second entry. */
105 parent_offset
= (unsigned long)isonum_711(de
->length
);
106 de
= (struct iso_directory_record
*)(bh
->b_data
+ parent_offset
);
108 /* Verify it is in fact the ".." entry. */
109 if ((isonum_711(de
->name_len
) != 1) || (de
->name
[0] != 1)) {
110 printk(KERN_ERR
"isofs: Unable to find the \"..\" "
111 "directory for NFS.\n");
112 rv
= ERR_PTR(-EACCES
);
117 isofs_normalize_block_and_offset(de
, &parent_block
, &parent_offset
);
120 parent_inode
= isofs_iget(child_inode
->i_sb
,
123 if (parent_inode
== NULL
) {
124 rv
= ERR_PTR(-EACCES
);
128 /* Allocate the dentry. */
129 rv
= d_alloc_anon(parent_inode
);
131 rv
= ERR_PTR(-ENOMEM
);
143 isofs_export_encode_fh(struct dentry
*dentry
,
148 struct inode
* inode
= dentry
->d_inode
;
149 struct iso_inode_info
* ei
= ISOFS_I(inode
);
152 __u16
*fh16
= (__u16
*)fh32
;
155 * WARNING: max_len is 5 for NFSv2. Because of this
156 * limitation, we use the lower 16 bits of fh32[1] to hold the
157 * offset of the inode and the upper 16 bits of fh32[1] to
158 * hold the offset of the parent.
161 if (len
< 3 || (connectable
&& len
< 5))
165 fh32
[0] = ei
->i_iget5_block
;
166 fh16
[2] = (__u16
)ei
->i_iget5_offset
; /* fh16 [sic] */
167 fh32
[2] = inode
->i_generation
;
168 if (connectable
&& !S_ISDIR(inode
->i_mode
)) {
169 struct inode
*parent
;
170 struct iso_inode_info
*eparent
;
171 spin_lock(&dentry
->d_lock
);
172 parent
= dentry
->d_parent
->d_inode
;
173 eparent
= ISOFS_I(parent
);
174 fh32
[3] = eparent
->i_iget5_block
;
175 fh16
[3] = (__u16
)eparent
->i_iget5_offset
; /* fh16 [sic] */
176 fh32
[4] = parent
->i_generation
;
177 spin_unlock(&dentry
->d_lock
);
186 static struct dentry
*
187 isofs_export_decode_fh(struct super_block
*sb
,
191 int (*acceptable
)(void *context
, struct dentry
*de
),
194 __u16
*fh16
= (__u16
*)fh32
;
195 __u32 child
[3]; /* The child is what triggered all this. */
196 __u32 parent
[3]; /* The parent is just along for the ride. */
198 if (fh_len
< 3 || fileid_type
> 2)
202 child
[1] = fh16
[2]; /* fh16 [sic] */
208 if (fileid_type
== 2) {
209 if (fh_len
> 2) parent
[0] = fh32
[3];
210 parent
[1] = fh16
[3]; /* fh16 [sic] */
211 if (fh_len
> 4) parent
[2] = fh32
[4];
214 return sb
->s_export_op
->find_exported_dentry(sb
, child
, parent
,
215 acceptable
, context
);
219 struct export_operations isofs_export_ops
= {
220 .decode_fh
= isofs_export_decode_fh
,
221 .encode_fh
= isofs_export_encode_fh
,
222 .get_dentry
= isofs_export_get_dentry
,
223 .get_parent
= isofs_export_get_parent
,