revert-mm-fix-blkdev-size-calculation-in-generic_write_checks
[linux-2.6/linux-trees-mm.git] / fs / reiser4 / export_ops.c
blobca4552d4d9a1ffdc6b6fd5cc6ed4ae1eb0774f21
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 /**
54 * reiser4_decode_fh - decode_fh of export operations
55 * @super: super block
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,
65 int len, int fhtype,
66 int (*acceptable) (void *context,
67 struct dentry *de),
68 void *context)
70 reiser4_context *ctx;
71 reiser4_object_on_wire object;
72 reiser4_object_on_wire parent;
73 char *addr;
74 int with_parent;
76 ctx = reiser4_init_context(super);
77 if (IS_ERR(ctx))
78 return (struct dentry *)ctx;
80 assert("vs-1482",
81 fhtype == FH_WITH_PARENT || fhtype == FH_WITHOUT_PARENT);
83 with_parent = (fhtype == FH_WITH_PARENT);
85 addr = (char *)fh;
87 object_on_wire_init(&object);
88 object_on_wire_init(&parent);
89 #if 0
90 addr = decode_inode(super, addr, &object);
91 if (!IS_ERR(addr)) {
92 if (with_parent)
93 addr = decode_inode(super, addr, &parent);
94 if (!IS_ERR(addr)) {
95 struct dentry *d;
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;
105 addr = (char *)d;
108 object_on_wire_done(&object);
109 object_on_wire_done(&parent);
111 reiser4_exit_context(ctx);
112 return (void *)addr;
113 #else
114 return ERR_PTR(-EINVAL);
115 #endif
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
131 * consumes.
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
144 * @start.
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)),
156 (d16 *) start);
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
168 * @dentry:
169 * @fh:
170 * @lenp:
171 * @need_parent:
174 static int
175 reiser4_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp,
176 int need_parent)
178 struct inode *inode;
179 struct inode *parent;
180 char *addr;
181 int need;
182 int delta;
183 int result;
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
192 * object plugins.
194 inode = dentry->d_inode;
195 parent = dentry->d_parent->d_inode;
197 addr = (char *)fh;
199 need = encode_inode_size(inode);
200 if (need < 0)
201 return NFSERROR;
202 if (need_parent) {
203 delta = encode_inode_size(parent);
204 if (delta < 0)
205 return NFSERROR;
206 need += delta;
209 ctx = reiser4_init_context(dentry->d_inode->i_sb);
210 if (IS_ERR(ctx))
211 return PTR_ERR(ctx);
213 if (need <= sizeof(__u32) * (*lenp)) {
214 addr = encode_inode(inode, addr);
215 if (need_parent)
216 addr = encode_inode(parent, addr);
218 /* store in lenp number of 32bit words required for file
219 * handle. */
220 *lenp = (need + sizeof(__u32) - 1) >> 2;
221 result = need_parent ? FH_WITH_PARENT : FH_WITHOUT_PARENT;
222 } else
223 /* no enough space in file handle */
224 result = NFSERROR;
225 reiser4_exit_context(ctx);
226 return result;
230 * reiser4_get_dentry_parent - get_parent of export operations
231 * @child:
234 static struct dentry *reiser4_get_dentry_parent(struct dentry *child)
236 struct inode *dir;
237 dir_plugin *dplug;
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));
247 if (dplug != NULL)
248 return dplug->get_parent(dir);
249 else
250 return ERR_PTR(RETERR(-ENOTDIR));
254 * reiser4_get_dentry - get_dentry of export operations
255 * @super:
256 * @data:
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
290 * Local variables:
291 * c-indentation-style: "K&R"
292 * mode-name: "LC"
293 * c-basic-offset: 8
294 * tab-width: 8
295 * fill-column: 79
296 * End: