2 * This Cplant(TM) source code is the property of Sandia National
5 * This Cplant(TM) source code is copyrighted by Sandia National
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)
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
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.
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.
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
34 * Questions or comments about this library should be sent to:
37 * Sandia National Laboratories, New Mexico
39 * Albuquerque, NM 87185-1110
56 #include <sys/types.h>
60 #include <sys/statvfs.h>
62 #include <sys/queue.h>
71 #include "fs_incore.h"
75 * In-core file system pseudo-driver.
81 #define INCORE_BLKSIZE (8192)
84 * Format of an incore inode.
87 LIST_ENTRY(incore_inode) ici_link; /* i-nodes list link */
88 unsigned ici_revalidate : 1; /* synch sys inode? */
89 struct intnl_stat ici_st; /* attrs */
90 struct file_identifier ici_fileid; /* file ID */
91 void *ici_data; /* file data */
95 * Given pointer to inode, return pointer to incore-inode.
97 #define I2IC(ino) ((struct incore_inode *)(ino)->i_private)
99 struct incore_filesys {
100 LIST_HEAD(, incore_inode) icfs_icinodes; /* all i-nodes list */
104 * Given pointer to filesys, return pointer to incore-filesys.
106 #define FS2ICFS(fs) ((struct incore_filesys *)(fs)->fs_private)
108 static int _sysio_incore_fsswop_mount(const char *source,
111 struct pnode *tocover,
112 struct mount **mntp);
114 static struct fssw_ops incore_fssw_ops = {
115 _sysio_incore_fsswop_mount
118 static void _sysio_incore_fsop_gone(struct filesys *fs);
120 static struct filesys_ops incore_fs_ops = {
121 _sysio_incore_fsop_gone,
124 static int _sysio_incore_dirop_lookup(struct pnode *pno,
126 struct intent *intnt,
128 static int _sysio_incore_inop_getattr(struct pnode *pno,
130 struct intnl_stat *stbuf);
131 static int _sysio_incore_inop_setattr(struct pnode *pno,
134 struct intnl_stat *stbuf);
135 static ssize_t _sysio_incore_dirop_getdirentries(struct inode *ino,
138 _SYSIO_OFF_T *basep);
139 static int _sysio_incore_dirop_mkdir(struct pnode *pno, mode_t mode);
140 static int _sysio_incore_dirop_rmdir(struct pnode *pno);
141 static int _sysio_incore_inop_open(struct pnode *pno, int flags, mode_t mode);
142 static int _sysio_incore_inop_close(struct inode *ino);
143 static int _sysio_incore_dirop_link(struct pnode *old, struct pnode *new);
144 static int _sysio_incore_dirop_unlink(struct pnode *pno);
145 static int _sysio_incore_dirop_rename(struct pnode *old, struct pnode *new);
146 static int _sysio_incore_filop_read(struct inode *ino, struct ioctx *ioctx);
147 static int _sysio_incore_filop_write(struct inode *ino, struct ioctx *ioctx);
148 static _SYSIO_OFF_T _sysio_incore_filop_pos(struct inode *ino,
150 static int _sysio_incore_filop_iodone(struct ioctx *ioctx);
151 static int _sysio_incore_filop_fcntl(struct inode *ino,
152 int cmd, va_list ap, int *rtn);
153 static int _sysio_incore_inop_sync(struct inode *ino);
154 static int _sysio_incore_filop_ioctl(struct inode *ino,
155 unsigned long int request,
157 static int _sysio_incore_dirop_mknod(struct pnode *pno, mode_t mode, dev_t dev);
159 static int _sysio_incore_inop_statvfs(struct pnode *pno,
161 struct intnl_statvfs *buf);
163 static void _sysio_incore_inop_gone(struct inode *ino);
165 #define _sysio_incore_dirop_symlink \
166 (int (*)(struct pnode *, const char *))_sysio_do_enosys
167 #define _sysio_incore_dirop_readlink \
168 (int (*)(struct pnode *, char *, size_t))_sysio_do_einval
169 #define _sysio_incore_dirop_read \
170 (int (*)(struct inode *, \
171 struct ioctx *))_sysio_do_eisdir
172 #define _sysio_incore_dirop_write \
173 (int (*)(struct inode *, \
174 struct ioctx *))_sysio_do_eisdir
175 #define _sysio_incore_dirop_pos \
176 (_SYSIO_OFF_T (*)(struct inode *, \
177 _SYSIO_OFF_T))_sysio_do_eisdir
178 #define _sysio_incore_dirop_iodone \
179 (int (*)(struct ioctx *))_sysio_do_illop
180 #define _sysio_incore_dirop_fcntl \
181 (int (*)(struct inode *, int, va_list, int *))_sysio_do_eisdir
182 #define _sysio_incore_dirop_ioctl \
183 (int (*)(struct inode *, \
185 va_list))_sysio_do_eisdir
187 static struct inode_ops _sysio_incore_dir_ops = {
188 _sysio_incore_dirop_lookup,
189 _sysio_incore_inop_getattr,
190 _sysio_incore_inop_setattr,
191 _sysio_incore_dirop_getdirentries,
192 _sysio_incore_dirop_mkdir,
193 _sysio_incore_dirop_rmdir,
194 _sysio_incore_dirop_symlink,
195 _sysio_incore_dirop_readlink,
196 _sysio_incore_inop_open,
197 _sysio_incore_inop_close,
198 _sysio_incore_dirop_link,
199 _sysio_incore_dirop_unlink,
200 _sysio_incore_dirop_rename,
201 _sysio_incore_dirop_read,
202 _sysio_incore_dirop_write,
203 _sysio_incore_dirop_pos,
204 _sysio_incore_dirop_iodone,
205 _sysio_incore_dirop_fcntl,
206 _sysio_incore_inop_sync,
207 _sysio_incore_inop_sync,
208 _sysio_incore_dirop_ioctl,
209 _sysio_incore_dirop_mknod,
211 _sysio_incore_inop_statvfs,
213 _sysio_incore_inop_gone
216 #define _sysio_incore_filop_lookup \
217 (int (*)(struct pnode *, \
220 const char *))_sysio_do_illop
221 #define _sysio_incore_filop_getdirentries \
222 (ssize_t (*)(struct inode *, \
225 _SYSIO_OFF_T *))_sysio_do_illop
226 #define _sysio_incore_filop_mkdir \
227 (int (*)(struct pnode *, mode_t))_sysio_do_illop
228 #define _sysio_incore_filop_rmdir \
229 (int (*)(struct pnode *))_sysio_do_illop
230 #define _sysio_incore_filop_symlink \
231 (int (*)(struct pnode *, const char *))_sysio_do_illop
232 #define _sysio_incore_symlinkop_readlink \
233 (int (*)(struct pnode *, char *, size_t))_sysio_do_illop
234 #define _sysio_incore_filop_link \
235 (int (*)(struct pnode *old, struct pnode *new))_sysio_do_illop
236 #define _sysio_incore_filop_unlink \
237 (int (*)(struct pnode *pno))_sysio_do_illop
238 #define _sysio_incore_filop_rename \
239 (int (*)(struct pnode *old, struct pnode *new))_sysio_do_illop
240 #define _sysio_incore_filop_mknod \
241 (int (*)(struct pnode *pno, mode_t, dev_t))_sysio_do_illop
243 static struct inode_ops _sysio_incore_file_ops = {
244 _sysio_incore_filop_lookup,
245 _sysio_incore_inop_getattr,
246 _sysio_incore_inop_setattr,
247 _sysio_incore_filop_getdirentries,
248 _sysio_incore_filop_mkdir,
249 _sysio_incore_filop_rmdir,
250 _sysio_incore_filop_symlink,
251 _sysio_incore_symlinkop_readlink,
252 _sysio_incore_inop_open,
253 _sysio_incore_inop_close,
254 _sysio_incore_filop_link,
255 _sysio_incore_filop_unlink,
256 _sysio_incore_filop_rename,
257 _sysio_incore_filop_read,
258 _sysio_incore_filop_write,
259 _sysio_incore_filop_pos,
260 _sysio_incore_filop_iodone,
261 _sysio_incore_filop_fcntl,
262 _sysio_incore_inop_sync,
263 _sysio_incore_inop_sync,
264 _sysio_incore_filop_ioctl,
265 _sysio_incore_filop_mknod,
267 _sysio_incore_inop_statvfs,
269 _sysio_incore_inop_gone
272 static struct inode_ops _sysio_incore_dev_ops = {
273 _sysio_incore_filop_lookup,
274 _sysio_incore_inop_getattr,
275 _sysio_incore_inop_setattr,
276 _sysio_incore_filop_getdirentries,
277 _sysio_incore_filop_mkdir,
278 _sysio_incore_filop_rmdir,
279 _sysio_incore_filop_symlink,
280 _sysio_incore_symlinkop_readlink,
281 _sysio_nodev_inop_open,
282 _sysio_nodev_inop_close,
283 _sysio_incore_filop_link,
284 _sysio_incore_filop_unlink,
285 _sysio_incore_filop_rename,
286 _sysio_nodev_inop_read,
287 _sysio_nodev_inop_write,
288 _sysio_nodev_inop_pos,
289 _sysio_nodev_inop_iodone,
290 _sysio_incore_filop_fcntl,
291 _sysio_incore_inop_sync,
292 _sysio_nodev_inop_sync,
293 _sysio_nodev_inop_ioctl,
294 _sysio_incore_filop_mknod,
296 _sysio_incore_inop_statvfs,
298 _sysio_incore_inop_gone
301 typedef void *(*probe_ty)(void *data, size_t len, void *arg);
304 * Lookup data argument bundle record.
307 struct qstr *name; /* desired entry name */
308 struct intnl_dirent *de; /* last dirent */
309 size_t minsiz; /* min hole needed */
311 void *p; /* best hole */
312 size_t len; /* best hole len */
317 * Initialize lookup data argument bundle.
319 #define INCORE_LD_INIT(ld, minsz, qs) \
323 (ld)->minsiz = (minsz); \
324 (ld)->hole.p = NULL; \
325 (ld)->hole.len = 0; \
329 * Calculate size of a directory entry given length of the entry name.
331 #define INCORE_D_RECLEN(namlen) \
332 (((size_t )&((struct intnl_dirent *)0)->d_name + \
333 (namlen) + 1 + sizeof(void *)) & \
334 ~(sizeof(void *) - 1))
337 * Given mode bits, return directory entry type code.
339 #define INCORE_D_TYPEOF(m) (((m) & S_IFMT) >> 12)
341 static char incore_dir_template[INCORE_D_RECLEN(1) + INCORE_D_RECLEN(2)];
343 static struct intnl_dirent incore_dir_template[] = {
348 INCORE_D_TYPEOF(S_IFDIR),
353 INCORE_D_RECLEN(1) + INCORE_D_RECLEN(2),
355 INCORE_D_TYPEOF(S_IFDIR),
362 * Initialize this driver.
367 struct intnl_dirent *de;
371 * Fill in the directory template.
373 de = (struct intnl_dirent *)incore_dir_template;
374 #ifdef _DIRENT_HAVE_D_OFF
377 off = de->d_reclen = INCORE_D_RECLEN(1);
378 de->d_type = INCORE_D_TYPEOF(S_IFDIR);
380 #ifdef _DIRENT_HAVE_D_NAMLEN
384 * Move to entry for `..'
386 de = (struct intnl_dirent *)((char *)de + off);
387 de->d_reclen = INCORE_D_RECLEN(2);
388 #ifdef _DIRENT_HAVE_D_NAMLEN
391 #ifdef _DIRENT_HAVE_D_OFF
395 de->d_type = INCORE_D_TYPEOF(S_IFDIR);
396 de->d_name[0] = de->d_name[1] = '.';
399 return _sysio_fssw_register("incore", &incore_fssw_ops);
405 static ino_t nxtnum = 1;
411 static struct incore_inode *
412 incore_i_alloc(struct incore_filesys *icfs, struct intnl_stat *st)
414 struct incore_inode *icino;
417 assert(!st->st_size);
419 icino = malloc(sizeof(struct incore_inode));
422 icino->ici_revalidate = 0;
424 icino->ici_fileid.fid_data = &icino->ici_st.st_ino;
425 icino->ici_fileid.fid_len = sizeof(icino->ici_st.st_ino);
426 icino->ici_data = NULL;
428 LIST_INSERT_HEAD(&icfs->icfs_icinodes, icino, ici_link);
434 incore_trunc(struct incore_inode *icino, _SYSIO_OFF_T size, int clear)
443 if (icino->ici_data) {
444 free(icino->ici_data);
445 icino->ici_data = NULL;
450 p = realloc(icino->ici_data, (size_t )n);
454 if (clear && n > icino->ici_st.st_size)
455 (void )memset((char *)icino->ici_data + icino->ici_st.st_size,
457 (size_t )(n - icino->ici_st.st_size));
459 icino->ici_st.st_size = n;
460 icino->ici_st.st_blocks =
461 (n + icino->ici_st.st_blksize - 1) / icino->ici_st.st_blksize;
462 icino->ici_st.st_mtime = time(NULL);
467 incore_i_destroy(struct incore_inode *icino)
470 LIST_REMOVE(icino, ici_link);
471 (void )incore_trunc(icino, 0, 0);
475 static struct incore_inode *
476 incore_directory_new(struct incore_filesys *icfs,
477 struct incore_inode *parent,
478 struct intnl_stat *st)
480 struct incore_inode *icino;
482 struct intnl_dirent *de;
484 icino = incore_i_alloc(icfs, st);
489 parent = icino; /* root */
492 * Allocate and init directory data.
494 err = incore_trunc(icino, sizeof(incore_dir_template), 1);
496 incore_i_destroy(icino);
499 (void )memcpy(icino->ici_data,
500 &incore_dir_template,
501 sizeof(incore_dir_template));
502 de = icino->ici_data;
503 de->d_ino = st->st_ino;
505 (struct intnl_dirent *)((char *)de +
506 #ifdef _DIRENT_HAVE_D_OFF
512 de->d_ino = parent->ici_st.st_ino;
515 * Set creation time to modify time set by truncate.
517 st->st_ctime = st->st_mtime;
523 _sysio_incore_fsswop_mount(const char *source,
525 const void *data __IS_UNUSED,
526 struct pnode *tocover,
537 struct intnl_stat stat;
538 struct incore_filesys *icfs;
540 struct incore_inode *icino;
543 struct pnode_base *rootpb;
545 static struct qstr noname = { NULL, 0, 0 };
548 * Source is a specification for the root attributes of this
549 * new file system in the format:
551 * <permissions>+<owner>+<group>
553 ul = strtoul(source, &cp, 0);
554 mode = (mode_t )ul & 07777;
556 (ul == ULONG_MAX && errno == ERANGE) ||
557 (unsigned long)mode != ul ||
561 l = strtol(source, &cp, 0);
564 ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
568 l = strtol(source, &cp, 0);
571 ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
577 dev = _sysio_dev_alloc();
589 icfs = malloc(sizeof(struct incore_filesys));
594 (void )memset(icfs, 0, sizeof(struct incore_filesys));
595 LIST_INIT(&icfs->icfs_icinodes);
598 * Create root i-node.
600 (void )memset(&stat, 0, sizeof(stat));
602 inum = incore_inum_alloc();
604 stat.__st_ino = inum;
606 stat.st_mode = S_IFDIR | (mode & 07777);
611 stat.st_blksize = INCORE_BLKSIZE;
613 stat.st_ctime = stat.st_mtime = stat.st_atime = 0;
615 icino = incore_directory_new(icfs, NULL, &stat);
618 icino->ici_st.st_atime = icino->ici_st.st_mtime;
621 _sysio_fs_new(&incore_fs_ops,
622 (flags & MOUNT_F_RO) ? FS_F_RO : 0,
630 * Create root for system.
632 * Persistent across remounts because we ask for immunity.
637 icino->ici_st.st_mode,
640 &_sysio_incore_dir_ops,
646 rootpb = _sysio_pb_new(&noname, NULL, rooti);
653 * Have path-node specified by the given source argument. Let the
654 * system finish the job, now.
671 if (mnt && _sysio_do_unmount(mnt) != 0)
674 _sysio_pb_gone(rootpb);
684 incore_i_destroy(icino);
697 _sysio_incore_fsop_gone(struct filesys *fs)
699 struct incore_filesys *icfs;
700 struct incore_inode *icino, *oicino;
705 * Free up i-node resource associated with this file system.
707 icino = icfs->icfs_icinodes.lh_first;
710 icino = icino->ici_link.le_next;
711 incore_i_destroy(oicino);
715 * Free the FS record.
721 * A directory search engine. Various functions are carried out by
722 * supplying appropriate callback functions.
724 * The two arguments, entry and hole, are called, if not null, for each
725 * directory entry and hole, respectively.
728 incore_directory_probe(void *data,
731 #ifndef _DIRENT_HAVE_D_OFF
739 struct intnl_dirent *de;
745 #ifdef _DIRENT_HAVE_D_OFF
748 assert(de->d_reclen);
750 if (entry && (p = (*entry)(de, de->d_reclen, arg)))
753 #ifdef _DIRENT_HAVE_D_OFF
756 ((void *)de - data) + de->d_reclen;
759 p = (*hole)((void *)de, de->d_reclen, arg);
765 de = (struct intnl_dirent *)((char *)data + n);
771 static struct intnl_dirent *
772 incore_directory_match(struct intnl_dirent *de,
773 size_t reclen __IS_UNUSED,
774 struct lookup_data *ld)
777 #if defined(BSD) || defined(REDSTORM)
778 if (IFTODT(de->d_type) == DT_WHT)
782 #ifdef _DIRENT_HAVE_D_NAMLEN
783 ld->name->len == de->d_namlen &&
785 strncmp(de->d_name, ld->name->name, ld->name->len) == 0)
792 _sysio_incore_dirop_lookup(struct pnode *pno,
794 struct intent *intnt __IS_UNUSED,
795 const char *path __IS_UNUSED)
798 struct intnl_dirent *de;
799 struct incore_inode *icino;
800 struct lookup_data lookup_data;
801 struct file_identifier fileid;
803 struct inode_ops *ops;
812 if (icino->ici_revalidate) {
813 (*inop)->i_mode = icino->ici_st.st_mode;
814 icino->ici_revalidate = 0;
819 ino = pno->p_parent->p_base->pb_ino;
821 INCORE_LD_INIT(&lookup_data,
823 &pno->p_base->pb_name);
825 incore_directory_probe(icino->ici_data,
826 icino->ici_st.st_size,
828 (probe_ty )incore_directory_match,
834 fileid.fid_data = &de->d_ino;
835 fileid.fid_len = sizeof(de->d_ino);
837 _sysio_i_find(ino->i_fs, &fileid);
841 icino->ici_fileid.fid_data = &icino->ici_st.st_ino;
842 icino->ici_fileid.fid_len = sizeof(icino->ici_st.st_ino);
844 switch (icino->ici_st.st_mode & S_IFMT) {
846 ops = &_sysio_incore_dir_ops;
849 ops = &_sysio_incore_file_ops;
857 _sysio_i_new(ino->i_fs,
859 icino->ici_st.st_mode,
876 _sysio_incore_inop_getattr(struct pnode *pno,
878 struct intnl_stat *stbuf)
880 struct incore_inode *icino;
883 ino = pno->p_base->pb_ino;
885 *stbuf = icino->ici_st;
890 _sysio_incore_inop_setattr(struct pnode *pno,
893 struct intnl_stat *stbuf)
895 struct incore_inode *icino;
899 ino = pno->p_base->pb_ino;
905 if (mask & SETATTR_LEN) {
906 err = incore_trunc(icino, stbuf->st_size, 1);
909 mask &= ~SETATTR_LEN;
911 if (mask & SETATTR_MODE) {
912 icino->ici_st.st_mode =
913 (icino->ici_st.st_mode & S_IFMT) | (stbuf->st_mode & 07777);
914 icino->ici_revalidate = 1;
916 if (mask & SETATTR_MTIME)
917 icino->ici_st.st_mtime = stbuf->st_mtime;
918 if (mask & SETATTR_ATIME)
919 icino->ici_st.st_atime = stbuf->st_atime;
920 if (mask & SETATTR_UID)
921 icino->ici_st.st_uid = stbuf->st_uid;
922 if (mask & SETATTR_GID)
923 icino->ici_st.st_gid = stbuf->st_gid;
924 icino->ici_st.st_ctime = time(NULL);
931 incore_directory_position(struct intnl_dirent *de,
932 size_t reclen __IS_UNUSED,
936 return (void *)de >= p ? de : NULL;
945 * Eumeration callback.
948 * On those systems supporting white-out entries, they are returned. On
949 * systems without, they are not.
952 incore_directory_enumerate(struct intnl_dirent *de,
954 struct copy_info *cinfo) {
956 if (reclen > cinfo->nbytes)
958 (void *)memcpy(cinfo->data, de, reclen);
959 cinfo->data = (char *)cinfo->data + reclen;
960 cinfo->nbytes -= reclen;
965 _sysio_incore_dirop_getdirentries(struct inode *ino,
970 struct incore_inode *icino = I2IC(ino);
972 struct intnl_dirent *de;
973 struct copy_info copy_info;
975 if (*basep > icino->ici_st.st_size)
979 incore_directory_probe(icino->ici_data,
980 icino->ici_st.st_size,
982 (probe_ty )incore_directory_position,
984 (char *)icino->ici_data + *basep);
993 copy_info.data = buf;
994 copy_info.nbytes = nbytes;
995 off = (char *)de - (char *)icino->ici_data;
997 incore_directory_probe(de,
998 icino->ici_st.st_size - off,
1000 (probe_ty )incore_directory_enumerate,
1003 nbytes -= copy_info.nbytes;
1004 icino->ici_st.st_atime = time(NULL);
1008 return (ssize_t )nbytes;
1011 static struct intnl_dirent *
1012 incore_directory_best_fit(void *data, size_t len, struct lookup_data *ld)
1015 if (!ld->hole.len || len < ld->hole.len) {
1024 incore_directory_insert(struct incore_inode *parent,
1030 struct lookup_data lookup_data;
1031 struct intnl_dirent *de;
1036 reclen = INCORE_D_RECLEN(name->len);
1037 INCORE_LD_INIT(&lookup_data, reclen, name);
1039 incore_directory_probe(parent->ici_data,
1040 parent->ici_st.st_size,
1042 (probe_ty )incore_directory_match,
1043 (probe_ty )incore_directory_best_fit,
1047 de = lookup_data.de;
1048 xt = (char *)lookup_data.de - (char *)parent->ici_data;
1050 #ifdef _DIRENT_HAVE_D_OFF
1056 #ifdef _DIRENT_HAVE_D_OFF
1059 INCORE_D_RECLEN(de->d_namlen);
1061 if (!parent->ici_st.st_size ||
1062 xt + r + reclen > (size_t )parent->ici_st.st_size) {
1065 err = incore_trunc(parent, xt + r + reclen, 1);
1068 de = (struct intnl_dirent *)((char *)parent->ici_data + xt);
1069 n = parent->ici_st.st_size;
1072 #ifdef _DIRENT_HAVE_D_OFF
1073 de->d_off = xt + r; /* trim */
1077 de = (struct intnl_dirent *)((char *)de + r); /* reposition */
1080 #ifndef _DIRENT_HAVE_D_OFF
1082 * Will we split this hole or use all of it?
1084 if (lookup_data.hole.len - reclen &&
1085 lookup_data.hole.len - reclen <= INCORE_D_RECLEN(1))
1086 reclen = lookup_data.hole.len;
1093 #ifdef _DIRENT_HAVE_D_OFF
1096 de->d_reclen = reclen;
1098 (void )memcpy(de->d_name, name->name, name->len);
1099 #ifdef _DIRENT_HAVE_D_NAMLEN
1100 de->d_namlen = name->len;
1103 #ifndef _DIRENT_HAVE_D_OFF
1107 * White-out remaining part of the hole.
1109 (void *)de += reclen;
1111 de->d_reclen = n - xt;
1112 de->d_type = DT_WHT;
1118 * Update attributes to reflect the new entry.
1120 parent->ici_st.st_nlink++;
1121 assert(parent->ici_st.st_nlink);
1122 parent->ici_st.st_atime = parent->ici_st.st_mtime = time(NULL);
1128 _sysio_incore_dirop_mkdir(struct pnode *pno, mode_t mode)
1130 struct intnl_stat stat;
1131 struct incore_inode *icino, *parent;
1134 struct intnl_dirent *de = NULL;
1137 ino = pno->p_parent->p_base->pb_ino;
1140 if (!S_ISDIR(parent->ici_st.st_mode))
1143 (void )memset(&stat, 0, sizeof(stat));
1144 stat.st_dev = pno->p_parent->p_base->pb_ino->i_fs->fs_dev;
1145 inum = incore_inum_alloc();
1147 stat.__st_ino = inum;
1149 stat.st_mode = S_IFDIR | (mode & 07777);
1151 stat.st_uid = getuid();
1152 stat.st_gid = getgid();
1154 stat.st_blksize = 4096;
1156 stat.st_ctime = stat.st_mtime = stat.st_atime = 0;
1158 icino = incore_directory_new(FS2ICFS(ino->i_fs), parent, &stat);
1163 * Tell the system about the new inode.
1165 * Persistent across remounts because we ask for immunity.
1168 _sysio_i_new(pno->p_parent->p_base->pb_ino->i_fs,
1173 &_sysio_incore_dir_ops,
1176 incore_i_destroy(icino);
1181 * Insert into parent.
1184 incore_directory_insert(parent,
1185 &pno->p_base->pb_name,
1187 INCORE_D_TYPEOF(S_IFDIR));
1190 de->d_ino = 0; /* bad parent */
1196 pno->p_base->pb_ino = ino;
1201 incore_unlink_entry(struct incore_inode *icino,
1204 struct lookup_data lookup_data;
1205 struct intnl_dirent *de;
1207 #ifdef _DIRENT_HAVE_D_OFF
1211 if (!S_ISDIR(icino->ici_st.st_mode))
1214 INCORE_LD_INIT(&lookup_data, 0, name);
1216 incore_directory_probe(icino->ici_data,
1217 icino->ici_st.st_size,
1219 (probe_ty )incore_directory_match,
1224 assert((size_t )((char *)de - (char *)icino->ici_data) >=
1225 sizeof(incore_dir_template));
1226 #ifndef _DIRENT_HAVE_D_OFF
1227 reclen = de->d_reclen;
1230 reclen = off - ((char *)de - (char *)icino->ici_data);
1232 (void )memset(de, 0, reclen);
1233 #ifndef _DIRENT_HAVE_D_OFF
1234 de->d_type = (__uint8_t )DTTOIF(DT_WHT);
1235 de->d_reclen = reclen;
1237 lookup_data.de->d_off = off;
1241 * Adjust link count.
1243 assert(icino->ici_st.st_nlink > 2);
1244 icino->ici_st.st_nlink--;
1250 _sysio_incore_dirop_rmdir(struct pnode *pno)
1252 struct inode *ino = pno->p_base->pb_ino;
1253 struct incore_inode *icino = I2IC(ino);
1256 if (!pno->p_base->pb_name.len ||
1257 (pno->p_base->pb_name.name[0] == '.' &&
1258 (pno->p_base->pb_name.len == 1 ||
1259 (pno->p_base->pb_name.len == 2 &&
1260 pno->p_base->pb_name.name[1] == '.'))))
1263 if (!S_ISDIR(icino->ici_st.st_mode))
1266 if (icino->ici_st.st_nlink > 2)
1269 pno->p_base->pb_ino = NULL;
1271 incore_unlink_entry(I2IC(pno->p_parent->p_base->pb_ino),
1272 &pno->p_base->pb_name);
1277 incore_create(struct pnode *pno, struct intnl_stat *st)
1279 struct inode *dino, *ino;
1280 struct incore_inode *icino;
1283 dino = pno->p_parent->p_base->pb_ino;
1286 icino = incore_i_alloc(FS2ICFS(dino->i_fs), st);
1291 * Tell the system about the new inode.
1294 _sysio_i_new(dino->i_fs,
1299 S_ISREG(st->st_mode)
1300 ? &_sysio_incore_file_ops
1301 : &_sysio_incore_dev_ops,
1304 incore_i_destroy(icino);
1309 * Insert into parent.
1312 incore_directory_insert(I2IC(dino),
1313 &pno->p_base->pb_name,
1315 INCORE_D_TYPEOF(icino->ici_st.st_mode));
1322 pno->p_base->pb_ino = ino;
1327 _sysio_incore_inop_open(struct pnode *pno, int flags __IS_UNUSED, mode_t mode)
1329 struct intnl_stat stat;
1333 * File exists. Nothing to do.
1335 if (pno->p_base->pb_ino)
1339 * Must create a new, regular, file.
1341 (void )memset(&stat, 0, sizeof(stat));
1342 stat.st_dev = pno->p_parent->p_base->pb_ino->i_fs->fs_dev;
1343 inum = incore_inum_alloc();
1345 stat.__st_ino = inum;
1347 stat.st_mode = S_IFREG | (mode & 07777);
1349 stat.st_uid = getuid();
1350 stat.st_gid = getgid();
1353 stat.st_blksize = 4096;
1355 stat.st_ctime = stat.st_mtime = stat.st_atime = 0;
1358 return incore_create(pno, &stat);
1362 _sysio_incore_inop_close(struct inode *ino __IS_UNUSED)
1369 _sysio_incore_dirop_link(struct pnode *old, struct pnode *new)
1371 struct incore_inode *icino = I2IC(old->p_base->pb_ino);
1374 assert(!new->p_base->pb_ino);
1375 assert(!S_ISDIR(old->p_base->pb_ino->i_mode));
1378 * Can bump the link count?
1380 if (!(icino->ici_st.st_nlink + 1))
1383 * Insert into parent.
1386 incore_directory_insert(I2IC(new->p_parent->p_base->pb_ino),
1387 &new->p_base->pb_name,
1388 icino->ici_st.st_ino,
1389 INCORE_D_TYPEOF(icino->ici_st.st_mode));
1393 * Bump the link count.
1395 icino->ici_st.st_nlink++;
1401 _sysio_incore_dirop_rename(struct pnode *old, struct pnode *new)
1404 struct incore_inode *icino = I2IC(old->p_base->pb_ino);
1406 if (new->p_base->pb_ino) {
1408 * Have to kill off the target first.
1410 if (S_ISDIR(I2IC(new->p_base->pb_ino)->ici_st.st_mode) &&
1411 I2IC(new->p_base->pb_ino)->ici_st.st_nlink > 2)
1414 incore_unlink_entry(I2IC(new->p_parent->p_base->pb_ino),
1415 &new->p_base->pb_name);
1421 * Insert into new parent.
1424 incore_directory_insert(I2IC(new->p_parent->p_base->pb_ino),
1425 &new->p_base->pb_name,
1426 icino->ici_st.st_ino,
1427 INCORE_D_TYPEOF(icino->ici_st.st_mode));
1431 * Remove from the old parent.
1434 incore_unlink_entry(I2IC(old->p_parent->p_base->pb_ino),
1435 &old->p_base->pb_name);
1439 if (S_ISDIR(icino->ici_st.st_mode)) {
1440 struct intnl_dirent *de;
1443 * We moved a directory. The entry for `..' must be corrected.
1445 de = icino->ici_data;
1447 assert(strcmp(de->d_name, "..") == 0);
1448 de->d_ino = I2IC(new->p_parent->p_base->pb_ino)->ici_st.st_ino;
1454 _sysio_incore_dirop_unlink(struct pnode *pno)
1456 struct inode *ino = pno->p_base->pb_ino;
1457 struct incore_inode *icino = I2IC(ino);
1460 if (S_ISDIR(icino->ici_st.st_mode))
1464 incore_unlink_entry(I2IC(pno->p_parent->p_base->pb_ino),
1465 &pno->p_base->pb_name);
1470 doio(ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, struct incore_inode *),
1472 struct ioctx *ioctx)
1476 _sysio_doio(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen,
1477 ioctx->ioctx_iov, ioctx->ioctx_iovlen,
1478 (ssize_t (*)(void *, size_t, _SYSIO_OFF_T, void *))f,
1480 if (ioctx->ioctx_cc < 0) {
1481 ioctx->ioctx_errno = -ioctx->ioctx_cc;
1482 ioctx->ioctx_cc = -1;
1484 ioctx->ioctx_done = 1;
1490 incore_read(void *buf, size_t nbytes,
1492 struct incore_inode *icino)
1498 if (!nbytes || off > icino->ici_st.st_size)
1500 n = icino->ici_st.st_size - (size_t )off;
1503 (void )memcpy(buf, (char *)icino->ici_data + off, (size_t )n);
1509 _sysio_incore_filop_read(struct inode *ino, struct ioctx *ioctx)
1513 return doio(incore_read, ino, ioctx);
1517 incore_write(const void *buf, size_t nbytes,
1519 struct incore_inode *icino)
1525 if (!nbytes || off > icino->ici_st.st_size)
1528 if (off && pos <= off) {
1530 * It's all or nothing. We won't write just part of
1535 if (pos > icino->ici_st.st_size) {
1538 err = incore_trunc(icino, (size_t )pos, 0);
1542 (void )memcpy((char *)icino->ici_data + off, buf, nbytes);
1544 return (ssize_t )nbytes;
1548 _sysio_incore_filop_write(struct inode *ino, struct ioctx *ioctx)
1551 return doio((ssize_t (*)(void *, size_t,
1553 struct incore_inode *))incore_write,
1559 _sysio_incore_filop_pos(struct inode *ino __IS_UNUSED, _SYSIO_OFF_T off)
1566 _sysio_incore_filop_iodone(struct ioctx *iocp __IS_UNUSED)
1570 * It's always done in this driver. It completed when posted.
1576 _sysio_incore_filop_fcntl(struct inode *ino __IS_UNUSED,
1577 int cmd __IS_UNUSED,
1578 va_list ap __IS_UNUSED,
1583 * No fcntl's supported.
1590 _sysio_incore_inop_sync(struct inode *ino __IS_UNUSED)
1600 _sysio_incore_filop_ioctl(struct inode *ino __IS_UNUSED,
1601 unsigned long int request __IS_UNUSED,
1602 va_list ap __IS_UNUSED)
1606 * No ioctl's supported.
1612 _sysio_incore_dirop_mknod(struct pnode *pno, mode_t mode, dev_t dev)
1615 struct intnl_stat stat;
1618 assert(!pno->p_base->pb_ino);
1623 else if (S_ISFIFO(m))
1625 else if (S_ISBLK(m))
1633 * Initialize attributes.
1635 (void )memset(&stat, 0, sizeof(stat));
1636 stat.st_dev = pno->p_parent->p_base->pb_ino->i_fs->fs_dev;
1637 inum = incore_inum_alloc();
1639 stat.__st_ino = inum;
1641 stat.st_mode = mode;
1643 stat.st_uid = getuid();
1644 stat.st_gid = getgid();
1647 stat.st_blksize = 4096;
1649 stat.st_ctime = stat.st_mtime = stat.st_atime = 0;
1652 return incore_create(pno, &stat);
1655 #ifdef _HAVE_STATVFS
1657 _sysio_incore_inop_statvfs(struct pnode *pno,
1659 struct intnl_statvfs *buf)
1664 ino = pno->p_base->pb_ino;
1667 fs = pno->p_base->pb_ino->i_fs;
1669 (void )memset(buf, 0, sizeof(struct intnl_statvfs));
1674 buf->f_bsize = fs->fs_bsize;
1675 buf->f_frsize = buf->f_bsize;
1677 buf->f_blocks /= buf->f_bsize;
1678 buf->f_bfree = buf->f_blocks - 1;
1679 buf->f_bavail = buf->f_bfree;
1680 buf->f_files = buf->f_blocks;
1681 buf->f_ffree = buf->f_files - 1;
1682 buf->f_favail = buf->f_ffree;
1683 buf->f_fsid = fs->fs_id;
1685 buf->f_namemax = ULONG_MAX;
1692 _sysio_incore_inop_gone(struct inode *ino)
1694 struct incore_inode *icino = I2IC(ino);
1696 incore_i_destroy(icino);