fed up with those stupid warnings
[mmotm.git] / fs / reiser4 / export_ops.c
blobc09fdf18abaf866916b6715434c9eb76e75c863d
1 /* Copyright 2005 by Hans Reiser, licensing governed by
2 * reiser4/README */
4 #include "inode.h"
5 #include "plugin/plugin.h"
7 /*
8 * Supported file-handle types
9 */
10 typedef enum {
11 FH_WITH_PARENT = 0x10, /* file handle with parent */
12 FH_WITHOUT_PARENT = 0x11 /* file handle without parent */
13 } reiser4_fhtype;
15 #define NFSERROR (255)
17 /* initialize place-holder for object */
18 static void object_on_wire_init(reiser4_object_on_wire *o)
20 o->plugin = NULL;
23 /* finish with @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)
37 file_plugin *fplug;
39 /* identifier of object plugin is stored in the first two bytes,
40 * followed by... */
41 fplug = file_plugin_by_disk_id(reiser4_get_tree(s), (d16 *) addr);
42 if (fplug != NULL) {
43 addr += sizeof(d16);
44 obj->plugin = fplug;
45 assert("nikita-3520", fplug->wire.read != NULL);
46 /* plugin specific encoding of object identity. */
47 addr = fplug->wire.read(addr, obj);
48 } else
49 addr = ERR_PTR(RETERR(-EINVAL));
50 return addr;
53 static struct dentry *reiser4_get_dentry(struct super_block *super,
54 void *data);
55 /**
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,
64 char * addr)
66 reiser4_object_on_wire object;
68 object_on_wire_init(&object);
70 addr = decode_inode(super, addr, &object);
71 if (!IS_ERR(addr)) {
72 struct dentry *d;
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;
77 addr = (char *)d;
79 object_on_wire_done(&object);
80 return (void *)addr;
83 static struct dentry *reiser4_fh_to_dentry(struct super_block *sb,
84 struct fid *fid,
85 int fh_len, int fh_type)
87 reiser4_context *ctx;
88 struct dentry *d;
90 assert("edward-1536",
91 fh_type == FH_WITH_PARENT || fh_type == FH_WITHOUT_PARENT);
93 ctx = reiser4_init_context(sb);
94 if (IS_ERR(ctx))
95 return (struct dentry *)ctx;
97 d = reiser4_decode_fh(sb, (char *)fid->raw);
99 reiser4_exit_context(ctx);
100 return d;
103 static struct dentry *reiser4_fh_to_parent(struct super_block *sb,
104 struct fid *fid,
105 int fh_len, int fh_type)
107 char * addr;
108 struct dentry * d;
109 reiser4_context *ctx;
110 file_plugin *fplug;
112 if (fh_type == FH_WITHOUT_PARENT)
113 return NULL;
114 assert("edward-1537", fh_type == FH_WITH_PARENT);
116 ctx = reiser4_init_context(sb);
117 if (IS_ERR(ctx))
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);
122 if (fplug == NULL) {
123 d = ERR_PTR(RETERR(-EINVAL));
124 goto exit;
126 addr += sizeof(d16);
127 /* skip previously encoded object */
128 addr = fplug->wire.read(addr, NULL /* skip */);
129 if (IS_ERR(addr)) {
130 d = (struct dentry *)addr;
131 goto exit;
133 /* @extract and decode parent object */
134 d = reiser4_decode_fh(sb, addr);
135 exit:
136 reiser4_exit_context(ctx);
137 return d;
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
153 * consumes.
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
166 * @start.
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)),
178 (d16 *) start);
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
190 * @dentry:
191 * @fh:
192 * @lenp:
193 * @need_parent:
196 static int
197 reiser4_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp,
198 int need_parent)
200 struct inode *inode;
201 struct inode *parent;
202 char *addr;
203 int need;
204 int delta;
205 int result;
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
214 * object plugins.
216 inode = dentry->d_inode;
217 parent = dentry->d_parent->d_inode;
219 addr = (char *)fh;
221 need = encode_inode_size(inode);
222 if (need < 0)
223 return NFSERROR;
224 if (need_parent) {
225 delta = encode_inode_size(parent);
226 if (delta < 0)
227 return NFSERROR;
228 need += delta;
231 ctx = reiser4_init_context(dentry->d_inode->i_sb);
232 if (IS_ERR(ctx))
233 return PTR_ERR(ctx);
235 if (need <= sizeof(__u32) * (*lenp)) {
236 addr = encode_inode(inode, addr);
237 if (need_parent)
238 addr = encode_inode(parent, addr);
240 /* store in lenp number of 32bit words required for file
241 * handle. */
242 *lenp = (need + sizeof(__u32) - 1) >> 2;
243 result = need_parent ? FH_WITH_PARENT : FH_WITHOUT_PARENT;
244 } else
245 /* no enough space in file handle */
246 result = NFSERROR;
247 reiser4_exit_context(ctx);
248 return result;
252 * reiser4_get_dentry_parent - get_parent of export operations
253 * @child:
256 static struct dentry *reiser4_get_dentry_parent(struct dentry *child)
258 struct inode *dir;
259 dir_plugin *dplug;
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);
269 if (IS_ERR(ctx))
270 return (void *)ctx;
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);
281 return result;
285 * reiser4_get_dentry - get_dentry of export operations
286 * @super:
287 * @data:
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,
321 * Local variables:
322 * c-indentation-style: "K&R"
323 * mode-name: "LC"
324 * c-basic-offset: 8
325 * tab-width: 8
326 * fill-column: 79
327 * End: