Whamcloud - gitweb
import older libsysio snapshot.
[fs/lustre-release.git] / libsysio / src / file.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 <assert.h>
46 #include <errno.h>
47 #include <sys/types.h>
48 #include <sys/queue.h>
49
50 #include "sysio.h"
51 #include "file.h"
52 #include "inode.h"
53 #include "xtio.h"
54
55 /*
56  * Support for file IO.
57  */
58
59 /*
60  * The open files table and it's size.
61  */
62 static struct file **_sysio_oftab = NULL;
63 static size_t _sysio_oftab_size = 0;
64
65 /*
66  * Create and initialize open file record.
67  */
68 struct file *
69 _sysio_fnew(struct inode *ino, int flags)
70 {
71         struct file *fil;
72
73         fil = malloc(sizeof(struct file));
74         if (!fil)
75                 return NULL;
76
77         _SYSIO_FINIT(fil, ino, flags);
78         I_REF(ino);
79
80         return fil;
81 }
82
83 /*
84  * Destroy open file record.
85  */
86 void
87 _sysio_fgone(struct file *fil)
88 {
89         int     err;
90
91         assert(!fil->f_ref);
92         assert(fil->f_ino);
93         err = (*fil->f_ino->i_ops.inop_close)(fil->f_ino);
94         assert(!err);
95         free(fil);
96 }
97
98 /*
99  * IO operation completion handler.
100  */
101 void
102 _sysio_fcompletio(struct ioctx *ioctx, struct file *fil)
103 {
104         _SYSIO_OFF_T off;
105
106         if (ioctx->ioctx_cc <= 0)
107                 return;
108
109         assert(ioctx->ioctx_ino == fil->f_ino);
110         off = fil->f_pos + ioctx->ioctx_cc;
111         if (fil->f_pos && off <= fil->f_pos)
112                 abort();
113         fil->f_pos = off;
114 }
115
116 /*
117  * Grow (or truncate) the file descriptor table.
118  */
119 static int
120 fd_grow(size_t n)
121 {
122         int     fd;
123         size_t  count;
124         struct file **noftab, **filp;
125
126         /*
127          * Sanity check the new size.
128          */
129         fd = (int )n;
130         if ((size_t )fd != n)
131                 return -EMFILE;
132
133         if (n < 8)
134                 n = 8;
135         if (n >= _sysio_oftab_size && n - _sysio_oftab_size < _sysio_oftab_size)
136                 n = (n + 1) * 2;
137         noftab = realloc(_sysio_oftab, n * sizeof(struct file *));
138         if (!noftab)
139                 return -ENOMEM;
140         _sysio_oftab = noftab;
141         count = _sysio_oftab_size;
142         _sysio_oftab_size = n;
143         if (n < count)
144                 return 0;
145         filp = _sysio_oftab + count;
146         n -= count;
147         while (n--)
148                 *filp++ = NULL;
149         return 0;
150 }
151
152 #if ZERO_SUM_MEMORY
153 void
154 _sysio_fd_shutdown()
155 {
156
157         free(_sysio_oftab);
158         _sysio_oftab_size = 0;
159 }
160 #endif
161
162 /*
163  * Find a free slot in the open files table.
164  */
165 static int
166 find_free_fildes()
167 {
168         size_t  n;
169         int     err;
170         struct file **filp;
171
172         for (n = 0, filp = _sysio_oftab;
173              n < _sysio_oftab_size && *filp;
174              n++, filp++)
175                 ;
176         if (n >= _sysio_oftab_size) {
177                 err = fd_grow(n);
178                 if (err)
179                         return err;
180                 filp = &_sysio_oftab[n];
181                 assert(!*filp);
182         }
183
184         return n;
185 }
186
187 /*
188  * Find open file record from file descriptor.
189  */
190 struct file *
191 _sysio_fd_find(int fd)
192 {
193         if (fd < 0 || (unsigned )fd >= _sysio_oftab_size)
194                 return NULL;
195
196         return _sysio_oftab[fd];
197 }
198
199 /*
200  * Close an open descriptor.
201  */
202 int
203 _sysio_fd_close(int fd)
204 {
205         struct file *fil;
206
207         fil = _sysio_fd_find(fd);
208         if (!fil)
209                 return -EBADF;
210
211         _sysio_oftab[fd] = NULL;
212
213         F_RELE(fil);
214
215         return 0;
216 }
217
218 /*
219  * Associate open file record with given file descriptor or any available
220  * file descriptor if less than zero.
221  */
222 int
223 _sysio_fd_set(struct file *fil, int fd)
224 {
225         int     err;
226         struct file *ofil;
227
228         /*
229          * New fd < 0 => any available descriptor.
230          */
231         if (fd < 0) {
232                 fd = find_free_fildes();
233                 if (fd < 0)
234                         return fd;
235         }
236
237         if ((unsigned )fd >= _sysio_oftab_size) {
238                 err = fd_grow(fd);
239                 if (err)
240                         return err;
241         }
242
243         /*
244          * Remember old.
245          */
246         ofil = _sysio_fd_find(fd);
247         /*
248          * Take the entry.
249          */
250         _sysio_oftab[fd] = fil;
251         if (ofil)
252                 F_RELE(ofil);
253
254         return fd;
255 }
256
257 /*
258  * Duplicate old file descriptor.
259  *
260  * If the new file descriptor is less than zero, the new file descriptor
261  * is chosen freely.
262  */
263 int
264 _sysio_fd_dup2(int oldfd, int newfd)
265 {
266         struct file *fil;
267         int     fd;
268
269         if (oldfd == newfd)
270                 return 0;
271
272         fil = _sysio_fd_find(oldfd);
273         if (!fil)
274                 return -EBADF;
275
276         fd = _sysio_fd_set(fil, newfd);
277         if (fd >= 0)
278                 F_REF(fil);
279         return fd;
280 }
281
282 int
283 _sysio_fd_close_all()
284 {
285         int     fd;
286         struct file **filp;
287
288         /*
289          * Close all open descriptors.
290          */
291         for (fd = 0, filp = _sysio_oftab;
292              (size_t )fd < _sysio_oftab_size;
293              fd++, filp++) {
294                 if (!*filp)
295                         continue;
296                 F_RELE(*filp);
297                 *filp = NULL;
298         }
299
300         /*
301          * Release current working directory.
302          */
303         if (_sysio_cwd) {
304                 P_RELE(_sysio_cwd);
305                 _sysio_cwd = NULL;
306         }
307
308         return 0;
309 }