1 /* Copyright 2005 by Hans Reiser, licensing governed by
5 #include "plugin/plugin.h"
8 * Supported file-handle types
11 FH_WITH_PARENT
= 0x10, /* file handle with parent */
12 FH_WITHOUT_PARENT
= 0x11 /* file handle without parent */
15 #define NFSERROR (255)
17 /* initialize place-holder for object */
18 static void object_on_wire_init(reiser4_object_on_wire
*o
)
24 static void object_on_wire_done(reiser4_object_on_wire
*o
)
26 if (o
->plugin
!= NULL
)
27 o
->plugin
->wire
.done(o
);
31 * read serialized object identity from @addr and store information about
32 * object in @obj. This is dual to encode_inode().
34 static char *decode_inode(struct super_block
*s
, char *addr
,
35 reiser4_object_on_wire
* obj
)
39 /* identifier of object plugin is stored in the first two bytes,
41 fplug
= file_plugin_by_disk_id(reiser4_get_tree(s
), (d16
*) addr
);
45 assert("nikita-3520", fplug
->wire
.read
!= NULL
);
46 /* plugin specific encoding of object identity. */
47 addr
= fplug
->wire
.read(addr
, obj
);
49 addr
= ERR_PTR(RETERR(-EINVAL
));
54 * reiser4_decode_fh - decode_fh of export operations
56 * @fh: nfsd file handle
57 * @len: length of file handle
58 * @fhtype: type of file handle
59 * @acceptable: acceptability testing function
60 * @context: argument for @acceptable
62 * Returns dentry referring to the same file as @fh.
64 static struct dentry
*reiser4_decode_fh(struct super_block
*super
, __u32
*fh
,
66 int (*acceptable
) (void *context
,
71 reiser4_object_on_wire object
;
72 reiser4_object_on_wire parent
;
76 ctx
= reiser4_init_context(super
);
78 return (struct dentry
*)ctx
;
81 fhtype
== FH_WITH_PARENT
|| fhtype
== FH_WITHOUT_PARENT
);
83 with_parent
= (fhtype
== FH_WITH_PARENT
);
87 object_on_wire_init(&object
);
88 object_on_wire_init(&parent
);
90 addr
= decode_inode(super
, addr
, &object
);
93 addr
= decode_inode(super
, addr
, &parent
);
96 typeof(super
->s_export_op
->find_exported_dentry
) fn
;
98 fn
= super
->s_export_op
->find_exported_dentry
;
99 assert("nikita-3521", fn
!= NULL
);
100 d
= fn(super
, &object
, with_parent
? &parent
: NULL
,
101 acceptable
, context
);
102 if (d
!= NULL
&& !IS_ERR(d
))
103 /* FIXME check for -ENOMEM */
104 reiser4_get_dentry_fsdata(d
)->stateless
= 1;
108 object_on_wire_done(&object
);
109 object_on_wire_done(&parent
);
111 reiser4_exit_context(ctx
);
114 return ERR_PTR(-EINVAL
);
119 * Object serialization support.
121 * To support knfsd file system provides export_operations that are used to
122 * construct and interpret NFS file handles. As a generalization of this,
123 * reiser4 object plugins have serialization support: it provides methods to
124 * create on-wire representation of identity of reiser4 object, and
125 * re-create/locate object given its on-wire identity.
130 * return number of bytes that on-wire representation of @inode's identity
133 static int encode_inode_size(struct inode
*inode
)
135 assert("nikita-3514", inode
!= NULL
);
136 assert("nikita-3515", inode_file_plugin(inode
) != NULL
);
137 assert("nikita-3516", inode_file_plugin(inode
)->wire
.size
!= NULL
);
139 return inode_file_plugin(inode
)->wire
.size(inode
) + sizeof(d16
);
143 * store on-wire representation of @inode's identity at the area beginning at
146 static char *encode_inode(struct inode
*inode
, char *start
)
148 assert("nikita-3517", inode
!= NULL
);
149 assert("nikita-3518", inode_file_plugin(inode
) != NULL
);
150 assert("nikita-3519", inode_file_plugin(inode
)->wire
.write
!= NULL
);
153 * first, store two-byte identifier of object plugin, then
155 save_plugin_id(file_plugin_to_plugin(inode_file_plugin(inode
)),
157 start
+= sizeof(d16
);
159 * call plugin to serialize object's identity
161 return inode_file_plugin(inode
)->wire
.write(inode
, start
);
164 /* this returns number of 32 bit long numbers encoded in @lenp. 255 is
165 * returned if file handle can not be stored */
167 * reiser4_encode_fh - encode_fh of export operations
175 reiser4_encode_fh(struct dentry
*dentry
, __u32
*fh
, int *lenp
,
179 struct inode
*parent
;
184 reiser4_context
*ctx
;
187 * knfsd asks as to serialize object in @dentry, and, optionally its
188 * parent (if need_parent != 0).
190 * encode_inode() and encode_inode_size() is used to build
191 * representation of object and its parent. All hard work is done by
194 inode
= dentry
->d_inode
;
195 parent
= dentry
->d_parent
->d_inode
;
199 need
= encode_inode_size(inode
);
203 delta
= encode_inode_size(parent
);
209 ctx
= reiser4_init_context(dentry
->d_inode
->i_sb
);
213 if (need
<= sizeof(__u32
) * (*lenp
)) {
214 addr
= encode_inode(inode
, addr
);
216 addr
= encode_inode(parent
, addr
);
218 /* store in lenp number of 32bit words required for file
220 *lenp
= (need
+ sizeof(__u32
) - 1) >> 2;
221 result
= need_parent
? FH_WITH_PARENT
: FH_WITHOUT_PARENT
;
223 /* no enough space in file handle */
225 reiser4_exit_context(ctx
);
230 * reiser4_get_dentry_parent - get_parent of export operations
234 static struct dentry
*reiser4_get_dentry_parent(struct dentry
*child
)
239 assert("nikita-3527", child
!= NULL
);
240 /* see comment in reiser4_get_dentry() about following assertion */
241 assert("nikita-3528", is_in_reiser4_context());
243 dir
= child
->d_inode
;
244 assert("nikita-3529", dir
!= NULL
);
245 dplug
= inode_dir_plugin(dir
);
246 assert("nikita-3531", ergo(dplug
!= NULL
, dplug
->get_parent
!= NULL
));
248 return dplug
->get_parent(dir
);
250 return ERR_PTR(RETERR(-ENOTDIR
));
254 * reiser4_get_dentry - get_dentry of export operations
260 static struct dentry
*reiser4_get_dentry(struct super_block
*super
, void *data
)
262 reiser4_object_on_wire
*o
;
264 assert("nikita-3522", super
!= NULL
);
265 assert("nikita-3523", data
!= NULL
);
267 * this is only supposed to be called by
269 * reiser4_decode_fh->find_exported_dentry
271 * so, reiser4_context should be here already.
273 assert("nikita-3526", is_in_reiser4_context());
275 o
= (reiser4_object_on_wire
*)data
;
276 assert("nikita-3524", o
->plugin
!= NULL
);
277 assert("nikita-3525", o
->plugin
->wire
.get
!= NULL
);
279 return o
->plugin
->wire
.get(super
, o
);
282 struct export_operations reiser4_export_operations
= {
283 .encode_fh
= reiser4_encode_fh
,
284 // .decode_fh = reiser4_decode_fh,
285 .get_parent
= reiser4_get_dentry_parent
,
286 // .get_dentry = reiser4_get_dentry
291 * c-indentation-style: "K&R"