Whamcloud - gitweb
Revert "b=19808 2.6.29-fc11 patchless client support"
[fs/lustre-release.git] / libsysio / src / dev.c
1 /*
2  *    This Cplant(TM) source code is the property of Sandia National
3  *    Laboratories.
4  *
5  *    This Cplant(TM) source code is copyrighted by Sandia National
6  *    Laboratories.
7  *
8  *    The redistribution of this Cplant(TM) source code is subject to the
9  *    terms of the GNU Lesser General Public License
10  *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
11  *
12  *    Cplant(TM) Copyright 1998-2003 Sandia Corporation. 
13  *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
14  *    license for use of this work by or on behalf of the US Government.
15  *    Export of this program may require a license from the United States
16  *    Government.
17  */
18
19 /*
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  * 
25  * This library is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  * 
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33  *
34  * Questions or comments about this library should be sent to:
35  *
36  * Lee Ward
37  * Sandia National Laboratories, New Mexico
38  * P.O. Box 5800
39  * Albuquerque, NM 87185-1110
40  *
41  * lee@sandia.gov
42  */
43
44 #include <stdlib.h>
45 #include <errno.h>
46 #include <assert.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <sys/queue.h>
50
51 #include "sysio.h"
52 #include "inode.h"
53 #include "dev.h"
54
55 const struct inode_ops _sysio_nodev_ops = {
56         _sysio_nodev_inop_lookup,
57         _sysio_nodev_inop_getattr,
58         _sysio_nodev_inop_setattr,
59         _sysio_nodev_filldirentries,
60         _sysio_nodev_inop_mkdir,
61         _sysio_nodev_inop_rmdir,
62         _sysio_nodev_inop_symlink,
63         _sysio_nodev_inop_readlink,
64         _sysio_nodev_inop_open,
65         _sysio_nodev_inop_close,
66         _sysio_nodev_inop_link,
67         _sysio_nodev_inop_unlink,
68         _sysio_nodev_inop_rename,
69         _sysio_nodev_inop_read,
70         _sysio_nodev_inop_write,
71         _sysio_nodev_inop_pos,
72         _sysio_nodev_inop_iodone,
73         _sysio_nodev_inop_fcntl,
74         _sysio_nodev_inop_sync,
75         _sysio_nodev_inop_datasync,
76         _sysio_nodev_inop_ioctl,
77         _sysio_nodev_inop_mknod,
78 #ifdef _HAVE_STATVFS
79         _sysio_nodev_inop_statvfs,
80 #endif
81         _sysio_nodev_inop_gone
82 };
83
84 /*
85  * Support for pseudo-devices.
86  */
87
88 struct device {
89         const char *dev_name;
90         struct inode_ops dev_ops;
91 };
92
93 static struct device cdev[128];
94
95 int
96 _sysio_dev_init()
97 {
98         unsigned major;
99
100         major = 0;
101         do {
102                 cdev[major].dev_name = NULL;
103                 cdev[major].dev_ops = _sysio_nodev_ops;
104         } while (++major < sizeof(cdev) / sizeof(struct device));
105
106         return 0;
107 }
108
109 /*
110  * Allocate major dev number in the dynamic range [128-255].
111  */
112 dev_t
113 _sysio_dev_alloc()
114 {
115         unsigned short major;
116         static unsigned char c_major = 128;
117
118         assert(c_major);
119         major = c_major++;
120         return SYSIO_MKDEV(major, 0);
121 }
122
123 static int
124 dev_register(struct device devtbl[],
125              int major,
126              const char *name,
127              struct inode_ops *ops)
128 {
129
130         assert(major < 128);
131
132         if (major < 0) {
133                 major = sizeof(cdev) / sizeof(struct device);
134                 while (major--) {
135                         if (!devtbl[major].dev_name)
136                                 break;
137                 }
138         }
139         if (major < 0)
140                 return -ENXIO;                          /* I dunno, what? */
141         if (devtbl[major].dev_name)
142                 return -EEXIST;
143         devtbl[major].dev_name = name;
144         devtbl[major].dev_ops = *ops;
145
146         return major;
147 }
148
149 int
150 _sysio_char_dev_register(int major, const char *name, struct inode_ops *ops)
151 {
152
153         return dev_register(cdev, major, name, ops);
154 }
155
156 struct inode_ops *
157 _sysio_dev_lookup(mode_t mode, dev_t dev)
158 {
159         struct device *devtbl;
160         dev_t   major;
161
162         if (S_ISCHR(mode) || S_ISFIFO(mode))
163                 devtbl = cdev;
164         else
165                 return (struct inode_ops *)&_sysio_nodev_ops;
166
167         major = SYSIO_MAJOR_DEV(dev);
168         if (!(major < 128) || !devtbl[major].dev_name)
169                 return (struct inode_ops *)&_sysio_nodev_ops;
170
171         return &devtbl[major].dev_ops;
172 }