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 */