rv.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
  4. *
  5. * This is the online Runtime Verification (RV) interface.
  6. *
  7. * RV is a lightweight (yet rigorous) method that complements classical
  8. * exhaustive verification techniques (such as model checking and
  9. * theorem proving) with a more practical approach to complex systems.
  10. *
  11. * RV works by analyzing the trace of the system's actual execution,
  12. * comparing it against a formal specification of the system behavior.
  13. * RV can give precise information on the runtime behavior of the
  14. * monitored system while enabling the reaction for unexpected
  15. * events, avoiding, for example, the propagation of a failure on
  16. * safety-critical systems.
  17. *
  18. * The development of this interface roots in the development of the
  19. * paper:
  20. *
  21. * De Oliveira, Daniel Bristot; Cucinotta, Tommaso; De Oliveira, Romulo
  22. * Silva. Efficient formal verification for the Linux kernel. In:
  23. * International Conference on Software Engineering and Formal Methods.
  24. * Springer, Cham, 2019. p. 315-332.
  25. *
  26. * And:
  27. *
  28. * De Oliveira, Daniel Bristot, et al. Automata-based formal analysis
  29. * and verification of the real-time Linux kernel. PhD Thesis, 2020.
  30. *
  31. * == Runtime monitor interface ==
  32. *
  33. * A monitor is the central part of the runtime verification of a system.
  34. *
  35. * The monitor stands in between the formal specification of the desired
  36. * (or undesired) behavior, and the trace of the actual system.
  37. *
  38. * In Linux terms, the runtime verification monitors are encapsulated
  39. * inside the "RV monitor" abstraction. A RV monitor includes a reference
  40. * model of the system, a set of instances of the monitor (per-cpu monitor,
  41. * per-task monitor, and so on), and the helper functions that glue the
  42. * monitor to the system via trace. Generally, a monitor includes some form
  43. * of trace output as a reaction for event parsing and exceptions,
  44. * as depicted bellow:
  45. *
  46. * Linux +----- RV Monitor ----------------------------------+ Formal
  47. * Realm | | Realm
  48. * +-------------------+ +----------------+ +-----------------+
  49. * | Linux kernel | | Monitor | | Reference |
  50. * | Tracing | -> | Instance(s) | <- | Model |
  51. * | (instrumentation) | | (verification) | | (specification) |
  52. * +-------------------+ +----------------+ +-----------------+
  53. * | | |
  54. * | V |
  55. * | +----------+ |
  56. * | | Reaction | |
  57. * | +--+--+--+-+ |
  58. * | | | | |
  59. * | | | +-> trace output ? |
  60. * +------------------------|--|----------------------+
  61. * | +----> panic ?
  62. * +-------> <user-specified>
  63. *
  64. * This file implements the interface for loading RV monitors, and
  65. * to control the verification session.
  66. *
  67. * == Registering monitors ==
  68. *
  69. * The struct rv_monitor defines a set of callback functions to control
  70. * a verification session. For instance, when a given monitor is enabled,
  71. * the "enable" callback function is called to hook the instrumentation
  72. * functions to the kernel trace events. The "disable" function is called
  73. * when disabling the verification session.
  74. *
  75. * A RV monitor is registered via:
  76. * int rv_register_monitor(struct rv_monitor *monitor);
  77. * And unregistered via:
  78. * int rv_unregister_monitor(struct rv_monitor *monitor);
  79. *
  80. * == User interface ==
  81. *
  82. * The user interface resembles kernel tracing interface. It presents
  83. * these files:
  84. *
  85. * "available_monitors"
  86. * - List the available monitors, one per line.
  87. *
  88. * For example:
  89. * # cat available_monitors
  90. * wip
  91. * wwnr
  92. *
  93. * "enabled_monitors"
  94. * - Lists the enabled monitors, one per line;
  95. * - Writing to it enables a given monitor;
  96. * - Writing a monitor name with a '!' prefix disables it;
  97. * - Truncating the file disables all enabled monitors.
  98. *
  99. * For example:
  100. * # cat enabled_monitors
  101. * # echo wip > enabled_monitors
  102. * # echo wwnr >> enabled_monitors
  103. * # cat enabled_monitors
  104. * wip
  105. * wwnr
  106. * # echo '!wip' >> enabled_monitors
  107. * # cat enabled_monitors
  108. * wwnr
  109. * # echo > enabled_monitors
  110. * # cat enabled_monitors
  111. * #
  112. *
  113. * Note that more than one monitor can be enabled concurrently.
  114. *
  115. * "monitoring_on"
  116. * - It is an on/off general switcher for monitoring. Note
  117. * that it does not disable enabled monitors or detach events,
  118. * but stops the per-entity monitors from monitoring the events
  119. * received from the instrumentation. It resembles the "tracing_on"
  120. * switcher.
  121. *
  122. * "monitors/"
  123. * Each monitor will have its own directory inside "monitors/". There
  124. * the monitor specific files will be presented.
  125. * The "monitors/" directory resembles the "events" directory on
  126. * tracefs.
  127. *
  128. * For example:
  129. * # cd monitors/wip/
  130. * # ls
  131. * desc enable
  132. * # cat desc
  133. * auto-generated wakeup in preemptive monitor.
  134. * # cat enable
  135. * 0
  136. *
  137. * For further information, see:
  138. * Documentation/trace/rv/runtime-verification.rst
  139. */
  140. #include <linux/kernel.h>
  141. #include <linux/module.h>
  142. #include <linux/init.h>
  143. #include <linux/slab.h>
  144. #ifdef CONFIG_DA_MON_EVENTS
  145. #define CREATE_TRACE_POINTS
  146. #include <trace/events/rv.h>
  147. #endif
  148. #include "rv.h"
  149. DEFINE_MUTEX(rv_interface_lock);
  150. static struct rv_interface rv_root;
  151. struct dentry *get_monitors_root(void)
  152. {
  153. return rv_root.monitors_dir;
  154. }
  155. /*
  156. * Interface for the monitor register.
  157. */
  158. static LIST_HEAD(rv_monitors_list);
  159. static int task_monitor_count;
  160. static bool task_monitor_slots[RV_PER_TASK_MONITORS];
  161. int rv_get_task_monitor_slot(void)
  162. {
  163. int i;
  164. lockdep_assert_held(&rv_interface_lock);
  165. if (task_monitor_count == RV_PER_TASK_MONITORS)
  166. return -EBUSY;
  167. task_monitor_count++;
  168. for (i = 0; i < RV_PER_TASK_MONITORS; i++) {
  169. if (task_monitor_slots[i] == false) {
  170. task_monitor_slots[i] = true;
  171. return i;
  172. }
  173. }
  174. WARN_ONCE(1, "RV task_monitor_count and slots are out of sync\n");
  175. return -EINVAL;
  176. }
  177. void rv_put_task_monitor_slot(int slot)
  178. {
  179. lockdep_assert_held(&rv_interface_lock);
  180. if (slot < 0 || slot >= RV_PER_TASK_MONITORS) {
  181. WARN_ONCE(1, "RV releasing an invalid slot!: %d\n", slot);
  182. return;
  183. }
  184. WARN_ONCE(!task_monitor_slots[slot], "RV releasing unused task_monitor_slots: %d\n",
  185. slot);
  186. task_monitor_count--;
  187. task_monitor_slots[slot] = false;
  188. }
  189. /*
  190. * This section collects the monitor/ files and folders.
  191. */
  192. static ssize_t monitor_enable_read_data(struct file *filp, char __user *user_buf, size_t count,
  193. loff_t *ppos)
  194. {
  195. struct rv_monitor_def *mdef = filp->private_data;
  196. const char *buff;
  197. buff = mdef->monitor->enabled ? "1\n" : "0\n";
  198. return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff)+1);
  199. }
  200. /*
  201. * __rv_disable_monitor - disabled an enabled monitor
  202. */
  203. static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
  204. {
  205. lockdep_assert_held(&rv_interface_lock);
  206. if (mdef->monitor->enabled) {
  207. mdef->monitor->enabled = 0;
  208. mdef->monitor->disable();
  209. /*
  210. * Wait for the execution of all events to finish.
  211. * Otherwise, the data used by the monitor could
  212. * be inconsistent. i.e., if the monitor is re-enabled.
  213. */
  214. if (sync)
  215. tracepoint_synchronize_unregister();
  216. return 1;
  217. }
  218. return 0;
  219. }
  220. /**
  221. * rv_disable_monitor - disable a given runtime monitor
  222. *
  223. * Returns 0 on success.
  224. */
  225. int rv_disable_monitor(struct rv_monitor_def *mdef)
  226. {
  227. __rv_disable_monitor(mdef, true);
  228. return 0;
  229. }
  230. /**
  231. * rv_enable_monitor - enable a given runtime monitor
  232. *
  233. * Returns 0 on success, error otherwise.
  234. */
  235. int rv_enable_monitor(struct rv_monitor_def *mdef)
  236. {
  237. int retval;
  238. lockdep_assert_held(&rv_interface_lock);
  239. if (mdef->monitor->enabled)
  240. return 0;
  241. retval = mdef->monitor->enable();
  242. if (!retval)
  243. mdef->monitor->enabled = 1;
  244. return retval;
  245. }
  246. /*
  247. * interface for enabling/disabling a monitor.
  248. */
  249. static ssize_t monitor_enable_write_data(struct file *filp, const char __user *user_buf,
  250. size_t count, loff_t *ppos)
  251. {
  252. struct rv_monitor_def *mdef = filp->private_data;
  253. int retval;
  254. bool val;
  255. retval = kstrtobool_from_user(user_buf, count, &val);
  256. if (retval)
  257. return retval;
  258. retval = count;
  259. mutex_lock(&rv_interface_lock);
  260. if (val)
  261. retval = rv_enable_monitor(mdef);
  262. else
  263. retval = rv_disable_monitor(mdef);
  264. mutex_unlock(&rv_interface_lock);
  265. return retval ? : count;
  266. }
  267. static const struct file_operations interface_enable_fops = {
  268. .open = simple_open,
  269. .llseek = no_llseek,
  270. .write = monitor_enable_write_data,
  271. .read = monitor_enable_read_data,
  272. };
  273. /*
  274. * Interface to read monitors description.
  275. */
  276. static ssize_t monitor_desc_read_data(struct file *filp, char __user *user_buf, size_t count,
  277. loff_t *ppos)
  278. {
  279. struct rv_monitor_def *mdef = filp->private_data;
  280. char buff[256];
  281. memset(buff, 0, sizeof(buff));
  282. snprintf(buff, sizeof(buff), "%s\n", mdef->monitor->description);
  283. return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff) + 1);
  284. }
  285. static const struct file_operations interface_desc_fops = {
  286. .open = simple_open,
  287. .llseek = no_llseek,
  288. .read = monitor_desc_read_data,
  289. };
  290. /*
  291. * During the registration of a monitor, this function creates
  292. * the monitor dir, where the specific options of the monitor
  293. * are exposed.
  294. */
  295. static int create_monitor_dir(struct rv_monitor_def *mdef)
  296. {
  297. struct dentry *root = get_monitors_root();
  298. const char *name = mdef->monitor->name;
  299. struct dentry *tmp;
  300. int retval;
  301. mdef->root_d = rv_create_dir(name, root);
  302. if (!mdef->root_d)
  303. return -ENOMEM;
  304. tmp = rv_create_file("enable", RV_MODE_WRITE, mdef->root_d, mdef, &interface_enable_fops);
  305. if (!tmp) {
  306. retval = -ENOMEM;
  307. goto out_remove_root;
  308. }
  309. tmp = rv_create_file("desc", RV_MODE_READ, mdef->root_d, mdef, &interface_desc_fops);
  310. if (!tmp) {
  311. retval = -ENOMEM;
  312. goto out_remove_root;
  313. }
  314. retval = reactor_populate_monitor(mdef);
  315. if (retval)
  316. goto out_remove_root;
  317. return 0;
  318. out_remove_root:
  319. rv_remove(mdef->root_d);
  320. return retval;
  321. }
  322. /*
  323. * Available/Enable monitor shared seq functions.
  324. */
  325. static int monitors_show(struct seq_file *m, void *p)
  326. {
  327. struct rv_monitor_def *mon_def = p;
  328. seq_printf(m, "%s\n", mon_def->monitor->name);
  329. return 0;
  330. }
  331. /*
  332. * Used by the seq file operations at the end of a read
  333. * operation.
  334. */
  335. static void monitors_stop(struct seq_file *m, void *p)
  336. {
  337. mutex_unlock(&rv_interface_lock);
  338. }
  339. /*
  340. * Available monitor seq functions.
  341. */
  342. static void *available_monitors_start(struct seq_file *m, loff_t *pos)
  343. {
  344. mutex_lock(&rv_interface_lock);
  345. return seq_list_start(&rv_monitors_list, *pos);
  346. }
  347. static void *available_monitors_next(struct seq_file *m, void *p, loff_t *pos)
  348. {
  349. return seq_list_next(p, &rv_monitors_list, pos);
  350. }
  351. /*
  352. * Enable monitor seq functions.
  353. */
  354. static void *enabled_monitors_next(struct seq_file *m, void *p, loff_t *pos)
  355. {
  356. struct rv_monitor_def *m_def = p;
  357. (*pos)++;
  358. list_for_each_entry_continue(m_def, &rv_monitors_list, list) {
  359. if (m_def->monitor->enabled)
  360. return m_def;
  361. }
  362. return NULL;
  363. }
  364. static void *enabled_monitors_start(struct seq_file *m, loff_t *pos)
  365. {
  366. struct rv_monitor_def *m_def;
  367. loff_t l;
  368. mutex_lock(&rv_interface_lock);
  369. if (list_empty(&rv_monitors_list))
  370. return NULL;
  371. m_def = list_entry(&rv_monitors_list, struct rv_monitor_def, list);
  372. for (l = 0; l <= *pos; ) {
  373. m_def = enabled_monitors_next(m, m_def, &l);
  374. if (!m_def)
  375. break;
  376. }
  377. return m_def;
  378. }
  379. /*
  380. * available/enabled monitors seq definition.
  381. */
  382. static const struct seq_operations available_monitors_seq_ops = {
  383. .start = available_monitors_start,
  384. .next = available_monitors_next,
  385. .stop = monitors_stop,
  386. .show = monitors_show
  387. };
  388. static const struct seq_operations enabled_monitors_seq_ops = {
  389. .start = enabled_monitors_start,
  390. .next = enabled_monitors_next,
  391. .stop = monitors_stop,
  392. .show = monitors_show
  393. };
  394. /*
  395. * available_monitors interface.
  396. */
  397. static int available_monitors_open(struct inode *inode, struct file *file)
  398. {
  399. return seq_open(file, &available_monitors_seq_ops);
  400. };
  401. static const struct file_operations available_monitors_ops = {
  402. .open = available_monitors_open,
  403. .read = seq_read,
  404. .llseek = seq_lseek,
  405. .release = seq_release
  406. };
  407. /*
  408. * enabled_monitors interface.
  409. */
  410. static void disable_all_monitors(void)
  411. {
  412. struct rv_monitor_def *mdef;
  413. int enabled = 0;
  414. mutex_lock(&rv_interface_lock);
  415. list_for_each_entry(mdef, &rv_monitors_list, list)
  416. enabled += __rv_disable_monitor(mdef, false);
  417. if (enabled) {
  418. /*
  419. * Wait for the execution of all events to finish.
  420. * Otherwise, the data used by the monitor could
  421. * be inconsistent. i.e., if the monitor is re-enabled.
  422. */
  423. tracepoint_synchronize_unregister();
  424. }
  425. mutex_unlock(&rv_interface_lock);
  426. }
  427. static int enabled_monitors_open(struct inode *inode, struct file *file)
  428. {
  429. if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
  430. disable_all_monitors();
  431. return seq_open(file, &enabled_monitors_seq_ops);
  432. };
  433. static ssize_t enabled_monitors_write(struct file *filp, const char __user *user_buf,
  434. size_t count, loff_t *ppos)
  435. {
  436. char buff[MAX_RV_MONITOR_NAME_SIZE + 2];
  437. struct rv_monitor_def *mdef;
  438. int retval = -EINVAL;
  439. bool enable = true;
  440. char *ptr = buff;
  441. int len;
  442. if (count < 1 || count > MAX_RV_MONITOR_NAME_SIZE + 1)
  443. return -EINVAL;
  444. memset(buff, 0, sizeof(buff));
  445. retval = simple_write_to_buffer(buff, sizeof(buff) - 1, ppos, user_buf, count);
  446. if (retval < 0)
  447. return -EFAULT;
  448. ptr = strim(buff);
  449. if (ptr[0] == '!') {
  450. enable = false;
  451. ptr++;
  452. }
  453. len = strlen(ptr);
  454. if (!len)
  455. return count;
  456. mutex_lock(&rv_interface_lock);
  457. retval = -EINVAL;
  458. list_for_each_entry(mdef, &rv_monitors_list, list) {
  459. if (strcmp(ptr, mdef->monitor->name) != 0)
  460. continue;
  461. /*
  462. * Monitor found!
  463. */
  464. if (enable)
  465. retval = rv_enable_monitor(mdef);
  466. else
  467. retval = rv_disable_monitor(mdef);
  468. if (!retval)
  469. retval = count;
  470. break;
  471. }
  472. mutex_unlock(&rv_interface_lock);
  473. return retval;
  474. }
  475. static const struct file_operations enabled_monitors_ops = {
  476. .open = enabled_monitors_open,
  477. .read = seq_read,
  478. .write = enabled_monitors_write,
  479. .llseek = seq_lseek,
  480. .release = seq_release,
  481. };
  482. /*
  483. * Monitoring on global switcher!
  484. */
  485. static bool __read_mostly monitoring_on;
  486. /**
  487. * rv_monitoring_on - checks if monitoring is on
  488. *
  489. * Returns 1 if on, 0 otherwise.
  490. */
  491. bool rv_monitoring_on(void)
  492. {
  493. /* Ensures that concurrent monitors read consistent monitoring_on */
  494. smp_rmb();
  495. return READ_ONCE(monitoring_on);
  496. }
  497. /*
  498. * monitoring_on general switcher.
  499. */
  500. static ssize_t monitoring_on_read_data(struct file *filp, char __user *user_buf,
  501. size_t count, loff_t *ppos)
  502. {
  503. const char *buff;
  504. buff = rv_monitoring_on() ? "1\n" : "0\n";
  505. return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff) + 1);
  506. }
  507. static void turn_monitoring_off(void)
  508. {
  509. WRITE_ONCE(monitoring_on, false);
  510. /* Ensures that concurrent monitors read consistent monitoring_on */
  511. smp_wmb();
  512. }
  513. static void reset_all_monitors(void)
  514. {
  515. struct rv_monitor_def *mdef;
  516. list_for_each_entry(mdef, &rv_monitors_list, list) {
  517. if (mdef->monitor->enabled)
  518. mdef->monitor->reset();
  519. }
  520. }
  521. static void turn_monitoring_on(void)
  522. {
  523. WRITE_ONCE(monitoring_on, true);
  524. /* Ensures that concurrent monitors read consistent monitoring_on */
  525. smp_wmb();
  526. }
  527. static void turn_monitoring_on_with_reset(void)
  528. {
  529. lockdep_assert_held(&rv_interface_lock);
  530. if (rv_monitoring_on())
  531. return;
  532. /*
  533. * Monitors might be out of sync with the system if events were not
  534. * processed because of !rv_monitoring_on().
  535. *
  536. * Reset all monitors, forcing a re-sync.
  537. */
  538. reset_all_monitors();
  539. turn_monitoring_on();
  540. }
  541. static ssize_t monitoring_on_write_data(struct file *filp, const char __user *user_buf,
  542. size_t count, loff_t *ppos)
  543. {
  544. int retval;
  545. bool val;
  546. retval = kstrtobool_from_user(user_buf, count, &val);
  547. if (retval)
  548. return retval;
  549. mutex_lock(&rv_interface_lock);
  550. if (val)
  551. turn_monitoring_on_with_reset();
  552. else
  553. turn_monitoring_off();
  554. /*
  555. * Wait for the execution of all events to finish
  556. * before returning to user-space.
  557. */
  558. tracepoint_synchronize_unregister();
  559. mutex_unlock(&rv_interface_lock);
  560. return count;
  561. }
  562. static const struct file_operations monitoring_on_fops = {
  563. .open = simple_open,
  564. .llseek = no_llseek,
  565. .write = monitoring_on_write_data,
  566. .read = monitoring_on_read_data,
  567. };
  568. static void destroy_monitor_dir(struct rv_monitor_def *mdef)
  569. {
  570. reactor_cleanup_monitor(mdef);
  571. rv_remove(mdef->root_d);
  572. }
  573. /**
  574. * rv_register_monitor - register a rv monitor.
  575. * @monitor: The rv_monitor to be registered.
  576. *
  577. * Returns 0 if successful, error otherwise.
  578. */
  579. int rv_register_monitor(struct rv_monitor *monitor)
  580. {
  581. struct rv_monitor_def *r;
  582. int retval = 0;
  583. if (strlen(monitor->name) >= MAX_RV_MONITOR_NAME_SIZE) {
  584. pr_info("Monitor %s has a name longer than %d\n", monitor->name,
  585. MAX_RV_MONITOR_NAME_SIZE);
  586. return -1;
  587. }
  588. mutex_lock(&rv_interface_lock);
  589. list_for_each_entry(r, &rv_monitors_list, list) {
  590. if (strcmp(monitor->name, r->monitor->name) == 0) {
  591. pr_info("Monitor %s is already registered\n", monitor->name);
  592. retval = -1;
  593. goto out_unlock;
  594. }
  595. }
  596. r = kzalloc(sizeof(struct rv_monitor_def), GFP_KERNEL);
  597. if (!r) {
  598. retval = -ENOMEM;
  599. goto out_unlock;
  600. }
  601. r->monitor = monitor;
  602. retval = create_monitor_dir(r);
  603. if (retval) {
  604. kfree(r);
  605. goto out_unlock;
  606. }
  607. list_add_tail(&r->list, &rv_monitors_list);
  608. out_unlock:
  609. mutex_unlock(&rv_interface_lock);
  610. return retval;
  611. }
  612. /**
  613. * rv_unregister_monitor - unregister a rv monitor.
  614. * @monitor: The rv_monitor to be unregistered.
  615. *
  616. * Returns 0 if successful, error otherwise.
  617. */
  618. int rv_unregister_monitor(struct rv_monitor *monitor)
  619. {
  620. struct rv_monitor_def *ptr, *next;
  621. mutex_lock(&rv_interface_lock);
  622. list_for_each_entry_safe(ptr, next, &rv_monitors_list, list) {
  623. if (strcmp(monitor->name, ptr->monitor->name) == 0) {
  624. rv_disable_monitor(ptr);
  625. list_del(&ptr->list);
  626. destroy_monitor_dir(ptr);
  627. }
  628. }
  629. mutex_unlock(&rv_interface_lock);
  630. return 0;
  631. }
  632. int __init rv_init_interface(void)
  633. {
  634. struct dentry *tmp;
  635. int retval;
  636. rv_root.root_dir = rv_create_dir("rv", NULL);
  637. if (!rv_root.root_dir)
  638. goto out_err;
  639. rv_root.monitors_dir = rv_create_dir("monitors", rv_root.root_dir);
  640. if (!rv_root.monitors_dir)
  641. goto out_err;
  642. tmp = rv_create_file("available_monitors", RV_MODE_READ, rv_root.root_dir, NULL,
  643. &available_monitors_ops);
  644. if (!tmp)
  645. goto out_err;
  646. tmp = rv_create_file("enabled_monitors", RV_MODE_WRITE, rv_root.root_dir, NULL,
  647. &enabled_monitors_ops);
  648. if (!tmp)
  649. goto out_err;
  650. tmp = rv_create_file("monitoring_on", RV_MODE_WRITE, rv_root.root_dir, NULL,
  651. &monitoring_on_fops);
  652. if (!tmp)
  653. goto out_err;
  654. retval = init_rv_reactors(rv_root.root_dir);
  655. if (retval)
  656. goto out_err;
  657. turn_monitoring_on();
  658. return 0;
  659. out_err:
  660. rv_remove(rv_root.root_dir);
  661. printk(KERN_ERR "RV: Error while creating the RV interface\n");
  662. return 1;
  663. }