sysctl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  2.  * vim:expandtab:shiftwidth=8:tabstop=8:
  3.  *
  4.  *  Copyright (C) 1999 Peter J. Braam <braam@clusterfs.com>
  5.  *
  6.  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
  7.  *
  8.  *   InterMezzo is free software; you can redistribute it and/or
  9.  *   modify it under the terms of version 2 of the GNU General Public
  10.  *   License as published by the Free Software Foundation.
  11.  *
  12.  *   InterMezzo is distributed in the hope that it will be useful,
  13.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *   GNU General Public License for more details.
  16.  *
  17.  *   You should have received a copy of the GNU General Public License
  18.  *   along with InterMezzo; if not, write to the Free Software
  19.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *  Sysctrl entries for Intermezzo!
  22.  */
  23. #define __NO_VERSION__
  24. #include <linux/config.h> /* for CONFIG_PROC_FS */
  25. #include <linux/module.h>
  26. #include <linux/sched.h>
  27. #include <linux/mm.h>
  28. #include <linux/sysctl.h>
  29. #include <linux/swapctl.h>
  30. #include <linux/proc_fs.h>
  31. #include <linux/slab.h>
  32. #include <linux/vmalloc.h>
  33. #include <linux/stat.h>
  34. #include <linux/ctype.h>
  35. #include <linux/init.h>
  36. #include <asm/bitops.h>
  37. #include <asm/segment.h>
  38. #include <asm/uaccess.h>
  39. #include <linux/utsname.h>
  40. #include <linux/blk.h>
  41. #include <linux/intermezzo_fs.h>
  42. #include <linux/intermezzo_psdev.h>
  43. /* /proc entries */
  44. #ifdef CONFIG_PROC_FS
  45. struct proc_dir_entry *proc_fs_intermezzo;
  46. int intermezzo_mount_get_info( char * buffer, char ** start, off_t offset,
  47.        int length)
  48. {
  49. int len=0;
  50. /* this works as long as we are below 1024 characters! */
  51. *start = buffer + offset;
  52. len -= offset;
  53. if ( len < 0 )
  54. return -EINVAL;
  55. return len;
  56. }
  57. #endif
  58. /* SYSCTL below */
  59. static struct ctl_table_header *intermezzo_table_header = NULL;
  60. /* 0x100 to avoid any chance of collisions at any point in the tree with
  61.  * non-directories
  62.  */
  63. #define PSDEV_INTERMEZZO  (0x100)
  64. #define PSDEV_DEBUG    1      /* control debugging */
  65. #define PSDEV_TRACE    2      /* control enter/leave pattern */
  66. #define PSDEV_TIMEOUT      3      /* timeout on upcalls to become intrble */
  67. #define PSDEV_HARD         4      /* mount type "hard" or "soft" */
  68. #define PSDEV_NO_FILTER    5      /* controls presto_chk */
  69. #define PSDEV_NO_JOURNAL   6      /* controls presto_chk */
  70. #define PSDEV_NO_UPCALL    7      /* controls lento_upcall */
  71. #define PSDEV_ERRORVAL     8      /* controls presto_debug_fail_blkdev */
  72. #define PSDEV_EXCL_GID     9      /* which GID is ignored by presto */
  73. #define PSDEV_BYTES_TO_CLOSE 11   /* bytes to write before close */
  74. /* These are global presto control options */
  75. #define PRESTO_PRIMARY_CTLCNT 2
  76. static struct ctl_table presto_table[ PRESTO_PRIMARY_CTLCNT + MAX_CHANNEL + 1] =
  77. {
  78. {PSDEV_DEBUG, "debug", &presto_debug, sizeof(int), 0644, NULL, &proc_dointvec},
  79. {PSDEV_TRACE, "trace", &presto_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
  80. };
  81. /*
  82.  * Intalling the sysctl entries: strategy
  83.  * - have templates for each /proc/sys/intermezzo/ entry
  84.  *   such an entry exists for each /dev/presto
  85.  *    (proto_channel_entry)
  86.  * - have a template for the contents of such directories
  87.  *    (proto_psdev_table)
  88.  * - have the master table (presto_table)
  89.  *
  90.  * When installing, malloc, memcpy and fix up the pointers to point to
  91.  * the appropriate constants in izo_channels[your_minor]
  92.  */
  93. static ctl_table proto_psdev_table[] = {
  94. {PSDEV_HARD, "hard", 0, sizeof(int), 0644, NULL, &proc_dointvec},
  95. {PSDEV_NO_FILTER, "no_filter", 0, sizeof(int), 0644, NULL, &proc_dointvec},
  96. {PSDEV_NO_JOURNAL, "no_journal", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
  97. {PSDEV_NO_UPCALL, "no_upcall", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
  98. {PSDEV_TIMEOUT, "timeout", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
  99. #ifdef PRESTO_DEBUG
  100. {PSDEV_ERRORVAL, "errorval", NULL, sizeof(int), 0644, NULL, &proc_dointvec},
  101. #endif
  102. { 0 }
  103. };
  104. static ctl_table proto_channel_entry = {
  105. PSDEV_INTERMEZZO, 0,  NULL, 0, 0555, 0,
  106. };
  107. static ctl_table intermezzo_table[2] = {
  108. {PSDEV_INTERMEZZO, "intermezzo",    NULL, 0, 0555, presto_table},
  109. {0}
  110. };
  111. /* support for external setting and getting of opts. */
  112. /* particularly via ioctl. The Right way to do this is via sysctl,
  113.  * but that will have to wait until intermezzo gets its own nice set of
  114.  * sysctl IDs
  115.  */
  116. /* we made these separate as setting may in future be more restricted
  117.  * than getting
  118.  */
  119. #ifdef RON_MINNICH
  120. int dosetopt(int minor, struct psdev_opt *opt)
  121. {
  122. int retval = 0;
  123. int newval = opt->optval;
  124. ENTRY;
  125. switch(opt->optname) {
  126. case PSDEV_TIMEOUT:
  127. izo_channels[minor].uc_timeout = newval;
  128. break;
  129. case PSDEV_HARD:
  130. izo_channels[minor].uc_hard = newval;
  131. break;
  132. case PSDEV_NO_FILTER:
  133. izo_channels[minor].uc_no_filter = newval;
  134. break;
  135. case PSDEV_NO_JOURNAL:
  136. izo_channels[minor].uc_no_journal = newval;
  137. break;
  138. case PSDEV_NO_UPCALL:
  139. izo_channels[minor].uc_no_upcall = newval;
  140. break;
  141. #ifdef PRESTO_DEBUG
  142. case PSDEV_ERRORVAL: {
  143. /* If we have a positive arg, set a breakpoint for that
  144.  * value.  If we have a negative arg, make that device
  145.  * read-only.  FIXME  It would be much better to only
  146.  * allow setting the underlying device read-only for the
  147.  * current presto cache.
  148.  */
  149. int errorval = izo_channels[minor].uc_errorval;
  150. if (errorval < 0) {
  151. if (newval == 0)
  152. set_device_ro(-errorval, 0);
  153. else
  154. CERROR("device %s already read onlyn",
  155.        kdevname(-errorval));
  156. } else {
  157. if (newval < 0)
  158. set_device_ro(-newval, 1);
  159. izo_channels[minor].uc_errorval = newval;
  160. CDEBUG(D_PSDEV, "setting errorval to %dn", newval);
  161. }
  162. break;
  163. }
  164. #endif
  165. case PSDEV_TRACE:
  166. case PSDEV_DEBUG:
  167. case PSDEV_BYTES_TO_CLOSE:
  168. default:
  169. CDEBUG(D_PSDEV,
  170.        "ioctl: dosetopt: minor %d, bad optname 0x%x, n",
  171.        minor, opt->optname);
  172. retval = -EINVAL;
  173. }
  174. EXIT;
  175. return retval;
  176. }
  177. int dogetopt(int minor, struct psdev_opt *opt)
  178. {
  179. int retval = 0;
  180. ENTRY;
  181. switch(opt->optname) {
  182. case PSDEV_TIMEOUT:
  183. opt->optval = izo_channels[minor].uc_timeout;
  184. break;
  185. case PSDEV_HARD:
  186. opt->optval = izo_channels[minor].uc_hard;
  187. break;
  188. case PSDEV_NO_FILTER:
  189. opt->optval = izo_channels[minor].uc_no_filter;
  190. break;
  191. case PSDEV_NO_JOURNAL:
  192. opt->optval = izo_channels[minor].uc_no_journal;
  193. break;
  194. case PSDEV_NO_UPCALL:
  195. opt->optval = izo_channels[minor].uc_no_upcall;
  196. break;
  197. #ifdef PSDEV_DEBUG
  198. case PSDEV_ERRORVAL: {
  199. int errorval = izo_channels[minor].uc_errorval;
  200. if (errorval < 0 && is_read_only(-errorval))
  201. CERROR("device %s has been set read-onlyn",
  202.        kdevname(-errorval));
  203. opt->optval = izo_channels[minor].uc_errorval;
  204. break;
  205. }
  206. #endif
  207. case PSDEV_TRACE:
  208. case PSDEV_DEBUG:
  209. case PSDEV_BYTES_TO_CLOSE:
  210. default:
  211. CDEBUG(D_PSDEV,
  212.        "ioctl: dogetopt: minor %d, bad optval 0x%x, n",
  213.        minor, opt->optname);
  214. retval = -EINVAL;
  215. }
  216. EXIT;
  217. return retval;
  218. }
  219. #endif
  220. /* allocate the tables for the presto devices. We need
  221.  * sizeof(proto_channel_table)/sizeof(proto_channel_table[0])
  222.  * entries for each dev
  223.  */
  224. int /* __init */ init_intermezzo_sysctl(void)
  225. {
  226. int i;
  227. int total_dev = MAX_CHANNEL;
  228. int entries_per_dev = sizeof(proto_psdev_table) /
  229. sizeof(proto_psdev_table[0]);
  230. int total_entries = entries_per_dev * total_dev;
  231. ctl_table *dev_ctl_table;
  232. PRESTO_ALLOC(dev_ctl_table, sizeof(ctl_table) * total_entries);
  233. if (! dev_ctl_table) {
  234. CERROR("WARNING: presto couldn't allocate dev_ctl_tablen");
  235. EXIT;
  236. return -ENOMEM;
  237. }
  238. /* now fill in the entries ... we put the individual presto<x>
  239.  * entries at the end of the table, and the per-presto stuff
  240.  * starting at the front.  We assume that the compiler makes
  241.  * this code more efficient, but really, who cares ... it
  242.  * happens once per reboot.
  243.  */
  244. for(i = 0; i < total_dev; i++) {
  245. /* entry for this /proc/sys/intermezzo/intermezzo"i" */
  246. ctl_table *psdev = &presto_table[i + PRESTO_PRIMARY_CTLCNT];
  247. /* entries for the individual "files" in this "directory" */
  248. ctl_table *psdev_entries = &dev_ctl_table[i * entries_per_dev];
  249. /* init the psdev and psdev_entries with the prototypes */
  250. *psdev = proto_channel_entry;
  251. memcpy(psdev_entries, proto_psdev_table,
  252.        sizeof(proto_psdev_table));
  253. /* now specialize them ... */
  254. /* the psdev has to point to psdev_entries, and fix the number */
  255. psdev->ctl_name = psdev->ctl_name + i + 1; /* sorry */
  256. PRESTO_ALLOC((void*)psdev->procname, PROCNAME_SIZE);
  257. if (!psdev->procname) {
  258. PRESTO_FREE(dev_ctl_table,
  259.     sizeof(ctl_table) * total_entries);
  260. return -ENOMEM;
  261. }
  262. sprintf((char *) psdev->procname, "intermezzo%d", i);
  263. /* hook presto into */
  264. psdev->child = psdev_entries;
  265. /* now for each psdev entry ... */
  266. psdev_entries[0].data = &(izo_channels[i].uc_hard);
  267. psdev_entries[1].data = &(izo_channels[i].uc_no_filter);
  268. psdev_entries[2].data = &(izo_channels[i].uc_no_journal);
  269. psdev_entries[3].data = &(izo_channels[i].uc_no_upcall);
  270. psdev_entries[4].data = &(izo_channels[i].uc_timeout);
  271. #ifdef PRESTO_DEBUG
  272. psdev_entries[5].data = &(izo_channels[i].uc_errorval);
  273. #endif
  274. }
  275. #ifdef CONFIG_SYSCTL
  276. if ( !intermezzo_table_header )
  277. intermezzo_table_header =
  278. register_sysctl_table(intermezzo_table, 0);
  279. #endif
  280. #ifdef CONFIG_PROC_FS
  281. proc_fs_intermezzo = proc_mkdir("intermezzo", proc_root_fs);
  282. proc_fs_intermezzo->owner = THIS_MODULE;
  283. create_proc_info_entry("mounts", 0, proc_fs_intermezzo, 
  284.        intermezzo_mount_get_info);
  285. #endif
  286. return 0;
  287. }
  288. void cleanup_intermezzo_sysctl(void)
  289. {
  290. int total_dev = MAX_CHANNEL;
  291. int entries_per_dev = sizeof(proto_psdev_table) /
  292. sizeof(proto_psdev_table[0]);
  293. int total_entries = entries_per_dev * total_dev;
  294. int i;
  295. #ifdef CONFIG_SYSCTL
  296. if ( intermezzo_table_header )
  297. unregister_sysctl_table(intermezzo_table_header);
  298. intermezzo_table_header = NULL;
  299. #endif
  300. for(i = 0; i < total_dev; i++) {
  301. /* entry for this /proc/sys/intermezzo/intermezzo"i" */
  302. ctl_table *psdev = &presto_table[i + PRESTO_PRIMARY_CTLCNT];
  303. PRESTO_FREE(psdev->procname, PROCNAME_SIZE);
  304. }
  305. /* presto_table[PRESTO_PRIMARY_CTLCNT].child points to the
  306.  * dev_ctl_table previously allocated in init_intermezzo_psdev()
  307.  */
  308. PRESTO_FREE(presto_table[PRESTO_PRIMARY_CTLCNT].child, sizeof(ctl_table) * total_entries);
  309. #if CONFIG_PROC_FS
  310. remove_proc_entry("mounts", proc_fs_intermezzo);
  311. remove_proc_entry("intermezzo", proc_root_fs);
  312. #endif
  313. }