/ addons / rtdm / vfile.h
vfile.h
  1  /**
  2   * @file
  3   * This file is part of the Xenomai project.
  4   *
  5   * @note Copyright (C) 2010 Philippe Gerum <rpm@xenomai.org>
  6   *
  7   * adapted to RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
  8   *
  9   * This program is free software; you can redistribute it and/or
 10   * modify it under the terms of the GNU General Public License as
 11   * published by the Free Software Foundation; either version 2 of the
 12   * License, or (at your option) any later version.
 13   *
 14   * This program is distributed in the hope that it will be useful,
 15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17   * GNU General Public License for more details.
 18   *
 19   * You should have received a copy of the GNU General Public License
 20   * along with this program; if not, write to the Free Software
 21   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 22   *
 23   * @ingroup vfile
 24   */
 25  
 26  #ifndef RTAI_RTDM_VFILE_H
 27  #define RTAI_RTDM_VFILE_H
 28  
 29  #ifdef CONFIG_PROC_FS
 30  
 31  /** @addtogroup vfile
 32   *@{*/
 33  
 34  #include <linux/proc_fs.h>
 35  #include <linux/seq_file.h>
 36  
 37  #include <rtdm/xn.h>
 38  
 39  #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
 40  
 41  #define PDE_DATA(inode) PDE(inode)->data
 42  
 43  static inline void proc_remove(struct proc_dir_entry *pde)
 44  {
 45          remove_proc_entry(pde->name, pde->parent);
 46  }
 47  
 48  #endif
 49  
 50  #define wrap_f_inode(file)                ((file)->f_path.dentry->d_inode)
 51  #define wrap_proc_dir_entry_owner(entry)  do { (void)entry; } while(0)
 52  
 53  struct xnvfile_directory;
 54  struct xnvfile_regular_iterator;
 55  struct xnvfile_snapshot_iterator;
 56  struct xnvfile_lock_ops;
 57  
 58  struct xnvfile {
 59  	struct proc_dir_entry *pde;
 60  	struct file *file;
 61  	struct xnvfile_lock_ops *lockops;
 62  	int refcnt;
 63  	void *private;
 64  };
 65  
 66  /**
 67   * @brief Vfile locking operations
 68   * @anchor vfile_lockops
 69   *
 70   * This structure describes the operations to be provided for
 71   * implementing locking support on vfiles. They apply to both
 72   * snapshot-driven and regular vfiles.
 73   */
 74  struct xnvfile_lock_ops {
 75  	/**
 76  	 * @anchor lockops_get
 77  	 * This handler should grab the desired lock.
 78  	 *
 79  	 * @param vfile A pointer to the virtual file which needs
 80  	 * locking.
 81  	 *
 82  	 * @return zero should be returned if the call
 83  	 * succeeds. Otherwise, a negative error code can be returned;
 84  	 * upon error, the current vfile operation is aborted, and the
 85  	 * user-space caller is passed back the error value.
 86  	 */
 87  	int (*get)(struct xnvfile *vfile);
 88  	/**
 89  	 * @anchor lockops_put This handler should release the lock
 90  	 * previously grabbed by the @ref lockops_get "get() handler".
 91  	 *
 92  	 * @param vfile A pointer to the virtual file which currently
 93  	 * holds the lock to release.
 94  	 */
 95  	void (*put)(struct xnvfile *vfile);
 96  };
 97  
 98  /*
 99   * XXX: struct semaphore is legacy for mutual exclusion, but supported
100   * on both 2.4 and 2.6 kernels. Will be changed to mutex when 2.4
101   * support is dropped from RTAI.
102   */
103  struct xnvfile_hostlock_class {
104  	struct xnvfile_lock_ops ops;
105  	struct semaphore sem;
106  };
107  
108  struct xnvfile_nklock_class {
109  	struct xnvfile_lock_ops ops;
110  	spl_t s;
111  };
112  
113  struct xnvfile_input {
114  	const char __user *u_buf;
115  	size_t size;
116  	struct xnvfile *vfile;
117  };
118  
119  /**
120   * @brief Regular vfile operation descriptor
121   * @anchor regular_ops
122   *
123   * This structure describes the operations available with a regular
124   * vfile. It defines handlers for sending back formatted kernel data
125   * upon a user-space read request, and for obtaining user data upon a
126   * user-space write request.
127   */
128  struct xnvfile_regular_ops {
129  	/**
130  	 * @anchor regular_rewind This handler is called only once,
131  	 * when the virtual file is opened, before the @ref
132  	 * regular_begin "begin() handler" is invoked.
133  	 *
134  	 * @param it A pointer to the vfile iterator which will be
135  	 * used to read the file contents.
136  	 *
137  	 * @return Zero should be returned upon success. Otherwise, a
138  	 * negative error code aborts the operation, and is passed
139  	 * back to the reader.
140  	 *
141  	 * @note This handler is optional. It should not be used to
142  	 * allocate resources but rather to perform consistency
143  	 * checks, since no closure call is issued in case the open
144  	 * sequence eventually fails.
145  	 */
146  	int (*rewind)(struct xnvfile_regular_iterator *it);
147  	/**
148  	 * @anchor regular_begin
149  	 * This handler should prepare for iterating over the records
150  	 * upon a read request, starting from the specified position.
151  	 *
152  	 * @param it A pointer to the current vfile iterator. On
153  	 * entry, it->pos is set to the (0-based) position of the
154  	 * first record to output. This handler may be called multiple
155  	 * times with different position requests.
156  	 *
157  	 * @return A pointer to the first record to format and output,
158  	 * to be passed to the @ref regular_show "show() handler" as
159  	 * its @a data parameter, if the call succeeds. Otherwise:
160  	 *
161  	 * - NULL in case no record is available, in which case the
162  	 * read operation will terminate immediately with no output.
163  	 *
164  	 * - VFILE_SEQ_START, a special value indicating that @ref
165  	 * regular_show "the show() handler" should receive a NULL
166  	 * data pointer first, in order to output a header.
167  	 *
168  	 * - ERR_PTR(errno), where errno is a negative error code;
169  	 * upon error, the current operation will be aborted
170  	 * immediately.
171  	 *
172  	 * @note This handler is optional; if none is given in the
173  	 * operation descriptor (i.e. NULL value), the @ref
174  	 * regular_show "show() handler()" will be called only once
175  	 * for a read operation, with a NULL @a data parameter. This
176  	 * particular setting is convenient for simple regular vfiles
177  	 * having a single, fixed record to output.
178  	 */
179  	void *(*begin)(struct xnvfile_regular_iterator *it);
180  	/**
181  	 * @anchor regular_next
182  	 * This handler should return the address of the next record
183  	 * to format and output by the @ref regular_show "show()
184  	 * handler".
185  	 *
186  	 * @param it A pointer to the current vfile iterator. On
187  	 * entry, it->pos is set to the (0-based) position of the
188  	 * next record to output.
189  	 *
190  	 * @return A pointer to the next record to format and output,
191  	 * to be passed to the @ref regular_show "show() handler" as
192  	 * its @a data parameter, if the call succeeds. Otherwise:
193  	 *
194  	 * - NULL in case no record is available, in which case the
195  	 * read operation will terminate immediately with no output.
196  	 *
197  	 * - ERR_PTR(errno), where errno is a negative error code;
198  	 * upon error, the current operation will be aborted
199  	 * immediately.
200  	 *
201  	 * @note This handler is optional; if none is given in the
202  	 * operation descriptor (i.e. NULL value), the read operation
203  	 * will stop after the first invocation of the @ref regular_show
204  	 * "show() handler".
205  	 */
206  	void *(*next)(struct xnvfile_regular_iterator *it);
207  	/**
208  	 * @anchor regular_end
209  	 * This handler is called after all records have been output.
210  	 *
211  	 * @param it A pointer to the current vfile iterator.
212  	 *
213  	 * @note This handler is optional and the pointer may be NULL.
214  	 */
215  	void (*end)(struct xnvfile_regular_iterator *it);
216  	/**
217  	 * @anchor regular_show
218  	 * This handler should format and output a record.
219  	 *
220  	 * xnvfile_printf(), xnvfile_write(), xnvfile_puts() and
221  	 * xnvfile_putc() are available to format and/or emit the
222  	 * output. All routines take the iterator argument @a it as
223  	 * their first parameter.
224  	 *
225  	 * @param it A pointer to the current vfile iterator.
226  	 *
227  	 * @param data A pointer to the record to format then
228  	 * output. The first call to the handler may receive a NULL @a
229  	 * data pointer, depending on the presence and/or return of a
230  	 * @ref regular_begin "hander"; the show handler should test
231  	 * this special value to output any header that fits, prior to
232  	 * receiving more calls with actual records.
233  	 *
234  	 * @return zero if the call succeeds, also indicating that the
235  	 * handler should be called for the next record if
236  	 * any. Otherwise:
237  	 *
238  	 * - A negative error code. This will abort the output phase,
239  	 * and return this status to the reader.
240  	 *
241  	 * - VFILE_SEQ_SKIP, a special value indicating that the
242  	 * current record should be skipped and will not be output.
243  	 */
244  	int (*show)(struct xnvfile_regular_iterator *it, void *data);
245  	/**
246  	 * @anchor regular_store
247  	 * This handler receives data written to the vfile, likely for
248  	 * updating some kernel setting, or triggering any other
249  	 * action which fits. This is the only handler which deals
250  	 * with the write-side of a vfile.  It is called when writing
251  	 * to the /proc entry of the vfile from a user-space process.
252  	 *
253  	 * The input data is described by a descriptor passed to the
254  	 * handler, which may be subsequently passed to parsing helper
255  	 * routines.  For instance, xnvfile_get_string() will accept
256  	 * the input descriptor for returning the written data as a
257  	 * null-terminated character string. On the other hand,
258  	 * xnvfile_get_integer() will attempt to return a long integer
259  	 * from the input data.
260  	 *
261  	 * @param input A pointer to an input descriptor. It refers to
262  	 * an opaque data from the handler's standpoint.
263  	 *
264  	 * @return the number of bytes read from the input descriptor
265  	 * if the call succeeds. Otherwise, a negative error code.
266  	 * Return values from parsing helper routines are commonly
267  	 * passed back to the caller by the @ref store
268  	 * "store() handler".
269  	 *
270  	 * @note This handler is optional, and may be omitted for
271  	 * read-only vfiles.
272  	 */
273  	ssize_t (*store)(struct xnvfile_input *input);
274  };
275  
276  struct xnvfile_regular {
277  	struct xnvfile entry;
278  	size_t privsz;
279  	struct xnvfile_regular_ops *ops;
280  };
281  
282  struct xnvfile_regular_template {
283  	size_t privsz;
284  	struct xnvfile_regular_ops *ops;
285  	struct xnvfile_lock_ops *lockops;
286  };
287  
288  /**
289   * @brief Regular vfile iterator
290   * @anchor regular_iterator
291   *
292   * This structure defines an iterator over a regular vfile.
293   */
294  struct xnvfile_regular_iterator {
295  	/** Current record position while iterating. */
296  	loff_t pos;
297  	/** Backlink to the host sequential file supporting the vfile. */
298  	struct seq_file *seq;
299  	/** Backlink to the vfile being read. */
300  	struct xnvfile_regular *vfile;
301  	/**
302  	 * Start of private area. Use xnvfile_iterator_priv() to
303  	 * address it.
304  	 */
305  	char private[0];
306  };
307  
308  /**
309   * @brief Snapshot vfile operation descriptor
310   * @anchor snapshot_ops
311   *
312   * This structure describes the operations available with a
313   * snapshot-driven vfile. It defines handlers for returning a
314   * printable snapshot of some RTAI object contents upon a
315   * user-space read request, and for updating this object upon a
316   * user-space write request.
317   */
318  struct xnvfile_snapshot_ops {
319  	/**
320  	 * @anchor snapshot_rewind
321  	 * This handler (re-)initializes the data collection, moving
322  	 * the seek pointer at the first record. When the file
323  	 * revision tag is touched while collecting data, the current
324  	 * reading is aborted, all collected data dropped, and the
325  	 * vfile is eventually rewound.
326  	 *
327  	 * @param it A pointer to the current snapshot iterator. Two
328  	 * useful information can be retrieved from this iterator in
329  	 * this context:
330  	 *
331  	 * - it->vfile is a pointer to the descriptor of the virtual
332  	 * file being rewound.
333  	 *
334  	 * - xnvfile_iterator_priv(it) returns a pointer to the
335  	 * private data area, available from the descriptor, which
336  	 * size is vfile->privsz. If the latter size is zero, the
337  	 * returned pointer is meaningless and should not be used.
338  	 *
339  	 * @return A negative error code aborts the data collection,
340  	 * and is passed back to the reader. Otherwise:
341  	 *
342  	 * - a strictly positive value is interpreted as the total
343  	 * number of records which will be returned by the @ref
344  	 * snapshot_next "next() handler" during the data collection
345  	 * phase. If no @ref snapshot_begin "begin() handler" is
346  	 * provided in the @ref snapshot_ops "operation descriptor",
347  	 * this value is used to allocate the snapshot buffer
348  	 * internally. The size of this buffer would then be
349  	 * vfile->datasz * value.
350  	 *
351  	 * - zero leaves the allocation to the @ref snapshot_begin
352  	 * "begin() handler" if present, or indicates that no record
353  	 * is to be output in case such handler is not given.
354  	 *
355  	 * @note This handler is optional; a NULL value indicates that
356  	 * nothing needs to be done for rewinding the vfile.  It is
357  	 * called with the vfile lock held.
358  	 */
359  	int (*rewind)(struct xnvfile_snapshot_iterator *it);
360  	/**
361  	 * @anchor snapshot_begin
362  	 * This handler should allocate the snapshot buffer to hold
363  	 * records during the data collection phase.  When specified,
364  	 * all records collected via the @ref snapshot_next "next()
365  	 * handler" will be written to a cell from the memory area
366  	 * returned by begin().
367  	 *
368  	 * @param it A pointer to the current snapshot iterator.
369  	 *
370  	 * @return A pointer to the record buffer, if the call
371  	 * succeeds. Otherwise:
372  	 *
373  	 * - NULL in case of allocation error. This will abort the data
374  	 * collection, and return -ENOMEM to the reader.
375  	 *
376  	 * - VFILE_SEQ_EMPTY, a special value indicating that no
377  	 * record will be output. In such a case, the @ref
378  	 * snapshot_next "next() handler" will not be called, and the
379  	 * data collection will stop immediately. However, the @ref
380  	 * snapshot_show "show() handler" will still be called once,
381  	 * with a NULL data pointer (i.e. header display request).
382  	 *
383  	 * @note This handler is optional; if none is given, an
384  	 * internal allocation depending on the value returned by the
385  	 * @ref snapshot_rewind "rewind() handler" can be obtained.
386  	 */
387  	void *(*begin)(struct xnvfile_snapshot_iterator *it);
388  	/**
389  	 * @anchor snapshot_end
390  	 * This handler releases the memory buffer previously obtained
391  	 * from begin(). It is usually called after the snapshot data
392  	 * has been output by show(), but it may also be called before
393  	 * rewinding the vfile after a revision change, to release the
394  	 * dropped buffer.
395  	 *
396  	 * @param it A pointer to the current snapshot iterator.
397  	 *
398  	 * @param buf A pointer to the buffer to release.
399  	 *
400  	 * @note This routine is optional and the pointer may be
401  	 * NULL. It is not needed upon internal buffer allocation;
402  	 * see the description of the @ref snapshot_rewind "rewind()
403  	 * handler".
404  	 */
405  	void (*end)(struct xnvfile_snapshot_iterator *it, void *buf);
406  	/**
407  	 * @anchor snapshot_next
408  	 * This handler fetches the next record, as part of the
409  	 * snapshot data to be sent back to the reader via the
410  	 * show().
411  	 *
412  	 * @param it A pointer to the current snapshot iterator.
413  	 *
414  	 * @param data A pointer to the record to fill in.
415  	 *
416  	 * @return a strictly positive value, if the call succeeds and
417  	 * leaves a valid record into @a data, which should be passed
418  	 * to the @ref snapshot_show "show() handler()" during the
419  	 * formatting and output phase. Otherwise:
420  	 *
421  	 * - A negative error code. This will abort the data
422  	 * collection, and return this status to the reader.
423  	 *
424  	 * - VFILE_SEQ_SKIP, a special value indicating that the
425  	 * current record should be skipped. In such a case, the @a
426  	 * data pointer is not advanced to the next position before
427  	 * the @ref snapshot_next "next() handler" is called anew.
428  	 *
429  	 * @note This handler is called with the vfile lock
430  	 * held. Before each invocation of this handler, the vfile
431  	 * core checks whether the revision tag has been touched, in
432  	 * which case the data collection is restarted from scratch. A
433  	 * data collection phase succeeds whenever all records can be
434  	 * fetched via the @ref snapshot_next "next() handler", while
435  	 * the revision tag remains unchanged, which indicates that a
436  	 * consistent snapshot of the object state was taken.
437  	 */
438  	int (*next)(struct xnvfile_snapshot_iterator *it, void *data);
439  	/**
440  	 * @anchor snapshot_show
441  	 * This handler should format and output a record from the
442  	 * collected data.
443  	 *
444  	 * xnvfile_printf(), xnvfile_write(), xnvfile_puts() and
445  	 * xnvfile_putc() are available to format and/or emit the
446  	 * output. All routines take the iterator argument @a it as
447  	 * their first parameter.
448  	 *
449  	 * @param it A pointer to the current snapshot iterator.
450  	 *
451  	 * @param data A pointer to the record to format then
452  	 * output. The first call to the handler is always passed a
453  	 * NULL @a data pointer; the show handler should test this
454  	 * special value to output any header that fits, prior to
455  	 * receiving more calls with actual records.
456  	 *
457  	 * @return zero if the call succeeds, also indicating that the
458  	 * handler should be called for the next record if
459  	 * any. Otherwise:
460  	 *
461  	 * - A negative error code. This will abort the output phase,
462  	 * and return this status to the reader.
463  	 *
464  	 * - VFILE_SEQ_SKIP, a special value indicating that the
465  	 * current record should be skipped and will not be output.
466  	 */
467  	int (*show)(struct xnvfile_snapshot_iterator *it, void *data);
468  	/**
469  	 * @anchor snapshot_store
470  	 * This handler receives data written to the vfile, likely for
471  	 * updating the associated RTAI object's state, or
472  	 * triggering any other action which fits. This is the only
473  	 * handler which deals with the write-side of a vfile.  It is
474  	 * called when writing to the /proc entry of the vfile
475  	 * from a user-space process.
476  	 *
477  	 * The input data is described by a descriptor passed to the
478  	 * handler, which may be subsequently passed to parsing helper
479  	 * routines.  For instance, xnvfile_get_string() will accept
480  	 * the input descriptor for returning the written data as a
481  	 * null-terminated character string. On the other hand,
482  	 * xnvfile_get_integer() will attempt to return a long integer
483  	 * from the input data.
484  	 *
485  	 * @param input A pointer to an input descriptor. It refers to
486  	 * an opaque data from the handler's standpoint.
487  	 *
488  	 * @return the number of bytes read from the input descriptor
489  	 * if the call succeeds. Otherwise, a negative error code.
490  	 * Return values from parsing helper routines are commonly
491  	 * passed back to the caller by the @ref snapshot_store
492  	 * "store() handler".
493  	 *
494  	 * @note This handler is optional, and may be omitted for
495  	 * read-only vfiles.
496  	 */
497  	ssize_t (*store)(struct xnvfile_input *input);
498  };
499  
500  /**
501   * @brief Snapshot revision tag
502   * @anchor revision_tag
503   *
504   * This structure defines a revision tag to be used with @ref
505   * snapshot_vfile "snapshot-driven vfiles".
506   */
507  struct xnvfile_rev_tag {
508  	/** Current revision number. */
509  	int rev;
510  };
511  
512  struct xnvfile_snapshot_template {
513  	size_t privsz;
514  	size_t datasz;
515  	struct xnvfile_rev_tag *tag;
516  	struct xnvfile_snapshot_ops *ops;
517  	struct xnvfile_lock_ops *lockops;
518  };
519  
520  /**
521   * @brief Snapshot vfile descriptor
522   * @anchor snapshot_vfile
523   *
524   * This structure describes a snapshot-driven vfile.  Reading from
525   * such a vfile involves a preliminary data collection phase under
526   * lock protection, and a subsequent formatting and output phase of
527   * the collected data records. Locking is done in a way that does not
528   * increase worst-case latency, regardless of the number of records to
529   * be collected for output.
530   */
531  struct xnvfile_snapshot {
532  	struct xnvfile entry;
533  	size_t privsz;
534  	size_t datasz;
535  	struct xnvfile_rev_tag *tag;
536  	struct xnvfile_snapshot_ops *ops;
537  };
538  
539  /**
540   * @brief Snapshot-driven vfile iterator
541   * @anchor snapshot_iterator
542   *
543   * This structure defines an iterator over a snapshot-driven vfile.
544   */
545  struct xnvfile_snapshot_iterator {
546  	/** Number of collected records. */
547  	int nrdata;
548  	/** Address of record buffer. */
549  	caddr_t databuf;
550  	/** Backlink to the host sequential file supporting the vfile. */
551  	struct seq_file *seq;
552  	/** Backlink to the vfile being read. */
553  	struct xnvfile_snapshot *vfile;
554  	/** Buffer release handler. */
555  	void (*endfn)(struct xnvfile_snapshot_iterator *it, void *buf);
556  	/**
557  	 * Start of private area. Use xnvfile_iterator_priv() to
558  	 * address it.
559  	 */
560  	char private[0];
561  };
562  
563  struct xnvfile_directory {
564  	struct xnvfile entry;
565  };
566  
567  struct xnvfile_link {
568  	struct xnvfile entry;
569  };
570  
571  /* vfile.begin()=> */
572  #define VFILE_SEQ_EMPTY			((void *)-1)
573  /* =>vfile.show() */
574  #define VFILE_SEQ_START			SEQ_START_TOKEN
575  /* vfile.next/show()=> */
576  #define VFILE_SEQ_SKIP			2
577  
578  #define xnvfile_printf(it, args...)	seq_printf((it)->seq, ##args)
579  #define xnvfile_write(it, data, len)	seq_write((it)->seq, (data),(len))
580  #define xnvfile_puts(it, s)		seq_puts((it)->seq, (s))
581  #define xnvfile_putc(it, c)		seq_putc((it)->seq, (c))
582  
583  static inline void xnvfile_touch_tag(struct xnvfile_rev_tag *tag)
584  {
585  	tag->rev++;
586  }
587  
588  static inline void xnvfile_touch(struct xnvfile_snapshot *vfile)
589  {
590  	xnvfile_touch_tag(vfile->tag);
591  }
592  
593  #define xnvfile_noentry			\
594  	{				\
595  		.pde = NULL,		\
596  		.private = NULL,	\
597  		.file = NULL,		\
598  		.refcnt = 0,		\
599  	}
600  
601  #define xnvfile_nodir	{ .entry = xnvfile_noentry }
602  #define xnvfile_nolink	{ .entry = xnvfile_noentry }
603  #define xnvfile_nofile	{ .entry = xnvfile_noentry }
604  
605  #define xnvfile_priv(e)			((e)->entry.private)
606  #define xnvfile_nref(e)			((e)->entry.refcnt)
607  #define xnvfile_file(e)			((e)->entry.file)
608  #define xnvfile_iterator_priv(it)	((void *)(&(it)->private))
609  
610  extern struct xnvfile_nklock_class xnvfile_nucleus_lock;
611  
612  extern struct xnvfile_directory nkvfroot;
613  
614  int xnvfile_init_root(void);
615  
616  void xnvfile_destroy_root(void);
617  
618  #ifdef __cplusplus
619  extern "C" {
620  #endif
621  
622  int xnvfile_init_snapshot(const char *name,
623  			  struct xnvfile_snapshot *vfile,
624  			  struct xnvfile_directory *parent);
625  
626  int xnvfile_init_regular(const char *name,
627  			 struct xnvfile_regular *vfile,
628  			 struct xnvfile_directory *parent);
629  
630  int xnvfile_init_dir(const char *name,
631  		     struct xnvfile_directory *vdir,
632  		     struct xnvfile_directory *parent);
633  
634  int xnvfile_init_link(const char *from,
635  		      const char *to,
636  		      struct xnvfile_link *vlink,
637  		      struct xnvfile_directory *parent);
638  
639  void xnvfile_destroy(struct xnvfile *vfile);
640  
641  ssize_t xnvfile_get_blob(struct xnvfile_input *input,
642  			 void *data, size_t size);
643  
644  ssize_t xnvfile_get_string(struct xnvfile_input *input,
645  			   char *s, size_t maxlen);
646  
647  ssize_t xnvfile_get_integer(struct xnvfile_input *input, long *valp);
648  
649  int __vfile_hostlock_get(struct xnvfile *vfile);
650  
651  void __vfile_hostlock_put(struct xnvfile *vfile);
652  
653  #ifdef __cplusplus
654  }
655  #endif
656  
657  static inline
658  void xnvfile_destroy_snapshot(struct xnvfile_snapshot *vfile)
659  {
660  	xnvfile_destroy(&vfile->entry);
661  }
662  
663  static inline
664  void xnvfile_destroy_regular(struct xnvfile_regular *vfile)
665  {
666  	xnvfile_destroy(&vfile->entry);
667  }
668  
669  static inline
670  void xnvfile_destroy_dir(struct xnvfile_directory *vdir)
671  {
672  	xnvfile_destroy(&vdir->entry);
673  }
674  
675  static inline
676  void xnvfile_destroy_link(struct xnvfile_link *vlink)
677  {
678  	xnvfile_destroy(&vlink->entry);
679  }
680  
681  #define DEFINE_VFILE_HOSTLOCK(name)					\
682  	struct xnvfile_hostlock_class name = {				\
683  		.ops = {						\
684  			.get = __vfile_hostlock_get,			\
685  			.put = __vfile_hostlock_put,			\
686  		},							\
687  		.sem = __SEMAPHORE_INITIALIZER(name.sem, 1),		\
688  	}
689  
690  #else /* !CONFIG_PROC_FS */
691  
692  #define xnvfile_touch_tag(tag)	do { } while (0)
693  
694  #define xnvfile_touch(vfile)	do { } while (0)
695  
696  #endif /* !CONFIG_PROC_FS */
697  
698  /*@}*/
699  
700  #endif /* !RTAI_RTDM_VFILE_H */