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
));
53 static struct dentry
*reiser4_get_dentry(struct super_block
*super
,
56 * reiser4_decode_fh: decode on-wire object - helper function
57 * for fh_to_dentry, fh_to_parent export operations;
58 * @super: super block;
59 * @addr: onwire object to be decoded;
61 * Returns dentry referring to the object being decoded.
63 static struct dentry
*reiser4_decode_fh(struct super_block
* super
,
66 reiser4_object_on_wire object
;
68 object_on_wire_init(&object
);
70 addr
= decode_inode(super
, addr
, &object
);
73 d
= reiser4_get_dentry(super
, &object
);
74 if (d
!= NULL
&& !IS_ERR(d
))
75 /* FIXME check for -ENOMEM */
76 reiser4_get_dentry_fsdata(d
)->stateless
= 1;
79 object_on_wire_done(&object
);
83 static struct dentry
*reiser4_fh_to_dentry(struct super_block
*sb
,
85 int fh_len
, int fh_type
)
91 fh_type
== FH_WITH_PARENT
|| fh_type
== FH_WITHOUT_PARENT
);
93 ctx
= reiser4_init_context(sb
);
95 return (struct dentry
*)ctx
;
97 d
= reiser4_decode_fh(sb
, (char *)fid
->raw
);
99 reiser4_exit_context(ctx
);
103 static struct dentry
*reiser4_fh_to_parent(struct super_block
*sb
,
105 int fh_len
, int fh_type
)
109 reiser4_context
*ctx
;
112 if (fh_type
== FH_WITHOUT_PARENT
)
114 assert("edward-1537", fh_type
== FH_WITH_PARENT
);
116 ctx
= reiser4_init_context(sb
);
118 return (struct dentry
*)ctx
;
119 addr
= (char *)fid
->raw
;
120 /* extract 2-bytes file plugin id */
121 fplug
= file_plugin_by_disk_id(reiser4_get_tree(sb
), (d16
*)addr
);
123 d
= ERR_PTR(RETERR(-EINVAL
));
127 /* skip previously encoded object */
128 addr
= fplug
->wire
.read(addr
, NULL
/* skip */);
130 d
= (struct dentry
*)addr
;
133 /* @extract and decode parent object */
134 d
= reiser4_decode_fh(sb
, addr
);
136 reiser4_exit_context(ctx
);
141 * Object serialization support.
143 * To support knfsd file system provides export_operations that are used to
144 * construct and interpret NFS file handles. As a generalization of this,
145 * reiser4 object plugins have serialization support: it provides methods to
146 * create on-wire representation of identity of reiser4 object, and
147 * re-create/locate object given its on-wire identity.
152 * return number of bytes that on-wire representation of @inode's identity
155 static int encode_inode_size(struct inode
*inode
)
157 assert("nikita-3514", inode
!= NULL
);
158 assert("nikita-3515", inode_file_plugin(inode
) != NULL
);
159 assert("nikita-3516", inode_file_plugin(inode
)->wire
.size
!= NULL
);
161 return inode_file_plugin(inode
)->wire
.size(inode
) + sizeof(d16
);
165 * store on-wire representation of @inode's identity at the area beginning at
168 static char *encode_inode(struct inode
*inode
, char *start
)
170 assert("nikita-3517", inode
!= NULL
);
171 assert("nikita-3518", inode_file_plugin(inode
) != NULL
);
172 assert("nikita-3519", inode_file_plugin(inode
)->wire
.write
!= NULL
);
175 * first, store two-byte identifier of object plugin, then
177 save_plugin_id(file_plugin_to_plugin(inode_file_plugin(inode
)),
179 start
+= sizeof(d16
);
181 * call plugin to serialize object's identity
183 return inode_file_plugin(inode
)->wire
.write(inode
, start
);
186 /* this returns number of 32 bit long numbers encoded in @lenp. 255 is
187 * returned if file handle can not be stored */
189 * reiser4_encode_fh - encode_fh of export operations
197 reiser4_encode_fh(struct dentry
*dentry
, __u32
*fh
, int *lenp
,
201 struct inode
*parent
;
206 reiser4_context
*ctx
;
209 * knfsd asks as to serialize object in @dentry, and, optionally its
210 * parent (if need_parent != 0).
212 * encode_inode() and encode_inode_size() is used to build
213 * representation of object and its parent. All hard work is done by
216 inode
= dentry
->d_inode
;
217 parent
= dentry
->d_parent
->d_inode
;
221 need
= encode_inode_size(inode
);
225 delta
= encode_inode_size(parent
);
231 ctx
= reiser4_init_context(dentry
->d_inode
->i_sb
);
235 if (need
<= sizeof(__u32
) * (*lenp
)) {
236 addr
= encode_inode(inode
, addr
);
238 addr
= encode_inode(parent
, addr
);
240 /* store in lenp number of 32bit words required for file
242 *lenp
= (need
+ sizeof(__u32
) - 1) >> 2;
243 result
= need_parent
? FH_WITH_PARENT
: FH_WITHOUT_PARENT
;
245 /* no enough space in file handle */
247 reiser4_exit_context(ctx
);
252 * reiser4_get_dentry_parent - get_parent of export operations
256 static struct dentry
*reiser4_get_dentry_parent(struct dentry
*child
)
260 struct dentry
*result
;
261 reiser4_context
*ctx
;
263 assert("nikita-3527", child
!= NULL
);
265 dir
= child
->d_inode
;
266 assert("nikita-3529", dir
!= NULL
);
268 ctx
= reiser4_init_context(dir
->i_sb
);
272 dplug
= inode_dir_plugin(dir
);
273 assert("nikita-3531", ergo(dplug
!= NULL
, dplug
->get_parent
!= NULL
));
275 if (unlikely(dplug
== NULL
)) {
276 reiser4_exit_context(ctx
);
277 return ERR_PTR(RETERR(-ENOTDIR
));
279 result
= dplug
->get_parent(dir
);
280 reiser4_exit_context(ctx
);
285 * reiser4_get_dentry - get_dentry of export operations
291 static struct dentry
*reiser4_get_dentry(struct super_block
*super
, void *data
)
293 reiser4_object_on_wire
*o
;
295 assert("nikita-3522", super
!= NULL
);
296 assert("nikita-3523", data
!= NULL
);
298 * this is only supposed to be called by
300 * reiser4_decode_fh->find_exported_dentry
302 * so, reiser4_context should be here already.
304 assert("nikita-3526", is_in_reiser4_context());
306 o
= (reiser4_object_on_wire
*)data
;
307 assert("nikita-3524", o
->plugin
!= NULL
);
308 assert("nikita-3525", o
->plugin
->wire
.get
!= NULL
);
310 return o
->plugin
->wire
.get(super
, o
);
313 struct export_operations reiser4_export_operations
= {
314 .encode_fh
= reiser4_encode_fh
,
315 .fh_to_dentry
= reiser4_fh_to_dentry
,
316 .fh_to_parent
= reiser4_fh_to_parent
,
317 .get_parent
= reiser4_get_dentry_parent
,
322 * c-indentation-style: "K&R"