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-2006 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
44 #if defined(AUTOMOUNT_FILE_NAME) && !defined(MAX_MOUNT_DEPTH)
46 * Maximum number of automounts to attempt in path traversal.
48 #define MAX_MOUNT_DEPTH 64
52 * Each i-node is uniquely identified by a file identifier, supplied by
53 * the relevant file system driver. The i-node number returned in the getattrs
54 * call is not always enough.
56 struct file_identifier {
73 * Operations on i-nodes.
75 * Should this be split up into file and name space operations?
78 int (*inop_lookup)(struct pnode *pno,
82 int (*inop_getattr)(struct pnode *pno,
84 struct intnl_stat *stbuf);
85 int (*inop_setattr)(struct pnode *pno,
88 struct intnl_stat *stbuf);
89 ssize_t (*inop_filldirentries)(struct inode *ino,
93 int (*inop_mkdir)(struct pnode *pno, mode_t mode);
94 int (*inop_rmdir)(struct pnode *pno);
95 int (*inop_symlink)(struct pnode *pno, const char *data);
96 int (*inop_readlink)(struct pnode *pno, char *buf, size_t bufsiz);
97 int (*inop_open)(struct pnode *pno, int flags, mode_t mode);
98 int (*inop_close)(struct inode *ino);
99 int (*inop_link)(struct pnode *old, struct pnode *new);
100 int (*inop_unlink)(struct pnode *pno);
101 int (*inop_rename)(struct pnode *old, struct pnode *new);
102 int (*inop_read)(struct inode *ino, struct ioctx *ioctx);
103 int (*inop_write)(struct inode *ino, struct ioctx *ioctx);
104 _SYSIO_OFF_T (*inop_pos)(struct inode *ino, _SYSIO_OFF_T off);
105 int (*inop_iodone)(struct ioctx *iocp);
106 int (*inop_fcntl)(struct inode *ino, int cmd, va_list ap, int *rtn);
107 int (*inop_sync)(struct inode *ino);
108 int (*inop_datasync)(struct inode *ino);
109 int (*inop_ioctl)(struct inode *ino, unsigned long int request, va_list ap);
110 int (*inop_mknod)(struct pnode *pno, mode_t mode, dev_t dev);
112 int (*inop_statvfs)(struct pnode *pno,
114 struct intnl_statvfs *buf);
116 void (*inop_gone)(struct inode *ino);
120 * Values for the mask to inop_setattr.
122 #define SETATTR_MODE 0x01
123 #define SETATTR_MTIME 0x02
124 #define SETATTR_ATIME 0x04
125 #define SETATTR_UID 0x08
126 #define SETATTR_GID 0x10
127 #define SETATTR_LEN 0x20
130 * An i-node record is maintained for each file object in the system.
133 LIST_ENTRY(inode) i_link; /* FS i-nodes link */
135 i_immune : 1, /* immune from GC */
136 i_zombie : 1; /* stale inode */
137 unsigned i_ref; /* soft ref counter */
138 struct inode_ops i_ops; /* operations */
139 struct intnl_stat i_stbuf; /* attrs */
140 struct filesys *i_fs; /* file system ptr */
141 struct file_identifier *i_fid; /* file ident */
142 void *i_private; /* driver data */
143 TAILQ_ENTRY(inode) i_nodes; /* all i-nodes link */
147 * Init an i-node record.
149 #define I_INIT(ino, fs, stat, ops, fid, immunity, private) \
151 (ino)->i_immune = (immunity) ? 1 : 0; \
152 (ino)->i_zombie = 0; \
154 (ino)->i_ops = *(ops); \
155 (ino)->i_stbuf = *(stat); \
156 (ino)->i_fs = (fs); \
157 (ino)->i_fid = (fid); \
158 (ino)->i_private = (private); \
162 * Take soft reference to i-node.
166 TAILQ_REMOVE(&_sysio_inodes, (ino), i_nodes); \
167 TAILQ_INSERT_TAIL(&_sysio_inodes, (ino), i_nodes); \
169 assert((ino)->i_ref); \
173 * Release soft reference to i-node.
175 #define I_RELE(ino) \
177 assert((ino)->i_ref); \
178 if (!--(ino)->i_ref && (ino)->i_zombie) \
179 _sysio_i_gone(ino); \
183 * Attempt to kill an inode.
185 #define I_GONE(ino) \
187 _sysio_i_undead(ino); \
192 * The "quick string" record (inspired by the structure of the same name
193 * from Linux) is used to pass a string without delimiters as well as useful
194 * information about the string.
203 * A path node is an entry in a directory. It may have many aliases, one
204 * for each name space in which it occurs. This record holds the
205 * common information.
208 struct qstr pb_name; /* entry name */
209 struct inode *pb_ino; /* inode */
210 LIST_HEAD(, pnode_base) pb_children; /* children if a dir */
211 LIST_ENTRY(pnode_base) pb_sibs; /* links to siblings */
212 LIST_ENTRY(pnode_base) pb_names; /* near names links */
213 LIST_HEAD(, pnode) pb_aliases; /* aliases */
214 struct pnode_base *pb_parent; /* parent */
218 * Since a file system may be multiply mounted, in different parts of the local
219 * tree, a file system object may appear in different places. We handle that
220 * with aliases. There is one pnode for every alias the system is tracking.
222 * Name space traversal depends heavily on the interpretation of many
223 * of the fields in this structure. For that reason a detailed discussion
224 * of the various fields is given.
226 * The reference field records soft references to the record. For instance,
227 * it tracks file and directory opens. It does not track sibling references,
228 * though, as those are hard references and can be found by examining the
229 * aliases list in the base part of the node.
231 * The parent value points to the parent directory for this entry, in the
232 * *system* name space -- Not the mounted volumes. If you want to examine
233 * the moutned volume name space, use the base record.
235 * The base value points to the base path node information. It is info common
236 * to all of the aliases.
238 * The mount value points to the mount record for the rooted name space in
239 * which the alias is found. Notably, if a node is the root of a sub-tree then
240 * the mount record, among other things, indicates another node
241 * (in another sub-tree) that is covered by this one.
243 * Another sub-tree, mounted on this node, is indicated by a non-null cover.
244 * The pnode pointed to, then, is the root of the mounted sub-tree.
246 * The links list entry holds pointers to other aliases for the base path
249 * The nodes link is bookkeeping.
252 unsigned p_ref; /* soft ref count */
253 struct pnode *p_parent; /* parent */
254 struct pnode_base *p_base; /* base part */
255 struct mount *p_mount; /* mount info */
256 struct pnode *p_cover; /* covering pnode */
257 LIST_ENTRY(pnode) p_links; /* other aliases */
258 TAILQ_ENTRY(pnode) p_nodes; /* all nodes links */
262 * Reference path-tree node.
266 TAILQ_REMOVE(&_sysio_pnodes, (pno), p_nodes); \
267 TAILQ_INSERT_TAIL(&_sysio_pnodes, (pno), p_nodes); \
269 assert((pno)->p_ref); \
273 * Release reference to path-tree node.
275 #define P_RELE(pno) \
277 assert((pno)->p_ref); \
282 * An intent record allows callers of namei and lookup to pass some information
283 * about what they want to accomplish in the end.
294 #define INT_GETATTR 0x01 /* get attrs */
295 #define INT_SETATTR 0x02 /* set attrs */
296 #define INT_UPDPARENT 0x04 /* insert/delete */
297 #define INT_OPEN 0x08 /* open */
298 #define INT_CREAT (INT_UPDPARENT|0x10) /* insert */
299 #define INT_READLINK 0x12 /* readlink */
301 #define INTENT_INIT(intnt, mask, arg1, arg2) \
303 (intnt)->int_opmask = (mask); \
304 (intnt)->int_arg1 = (arg1); \
305 (intnt)->int_arg2 = (arg2); \
309 * Bundled up arguments to _sysio_path_walk.
312 unsigned nd_flags; /* flags (see below) */
313 const char *nd_path; /* path arg */
314 struct pnode *nd_pno; /* returned pnode */
315 struct pnode *nd_root; /* system/user root */
316 struct intent *nd_intent; /* intent (NULL ok) */
317 unsigned nd_slicnt; /* symlink indirects */
318 #ifdef AUTOMOUNT_FILE_NAME
319 unsigned nd_amcnt; /* automounts */
324 * Values for nameidata flags field.
326 #define ND_NOFOLLOW 0x01 /* no follow symlinks */
327 #define ND_NEGOK 0x02 /* last missing is ok */
328 #define ND_NOPERMCHECK 0x04 /* don't check perms */
330 #ifdef AUTOMOUNT_FILE_NAME
331 #define _ND_INIT_AUTOMOUNT(nd) ((nd)->nd_amcnt = 0)
333 #define _ND_INIT_AUTOMOUNT(nd)
336 #define _ND_INIT_OTHERS(nd) \
337 _ND_INIT_AUTOMOUNT(nd)
340 * Init nameidata record.
342 #define ND_INIT(nd, flags, path, root, intnt) \
344 (nd)->nd_flags = (flags); \
345 (nd)->nd_path = (path); \
346 (nd)->nd_pno = NULL; \
347 (nd)->nd_root = (root); \
348 (nd)->nd_intent = (intnt); \
349 (nd)->nd_slicnt = 0; \
350 _ND_INIT_OTHERS(nd); \
354 * IO completion callback record.
356 struct ioctx_callback {
357 TAILQ_ENTRY(ioctx_callback) iocb_next; /* list link */
358 void (*iocb_f)(struct ioctx *, void *); /* cb func */
359 void *iocb_data; /* cb data */
363 * All IO internally is done with an asynchronous mechanism. This record
364 * holds the completion information. It's too big :-(
367 LIST_ENTRY(ioctx) ioctx_link; /* AIO list link */
369 ioctx_fast : 1, /* from stack space */
370 ioctx_done : 1, /* transfer complete */
371 ioctx_write : 1; /* op is a write */
372 struct inode *ioctx_ino; /* i-node */
373 const struct iovec *ioctx_iov; /* scatter/gather vec */
374 size_t ioctx_iovlen; /* iovec length */
375 const struct intnl_xtvec *ioctx_xtv; /* extents */
376 size_t ioctx_xtvlen; /* xtv length */
377 ssize_t ioctx_cc; /* rtn char count */
378 int ioctx_errno; /* error number */
379 TAILQ_HEAD(, ioctx_callback) ioctx_cbq; /* callback queue */
380 void *ioctx_private; /* driver data */
384 * Init IO context record.
386 #define IOCTX_INIT(ioctx, fast, wr, ino, iov, iovlen, xtv, xtvlen) \
388 (ioctx)->ioctx_fast = (fast); \
389 (ioctx)->ioctx_done = 0; \
390 (ioctx)->ioctx_write = (wr) ? 1 : 0; \
391 (ioctx)->ioctx_ino = (ino); \
392 (ioctx)->ioctx_iov = (iov); \
393 (ioctx)->ioctx_iovlen = (iovlen); \
394 (ioctx)->ioctx_xtv = (xtv); \
395 (ioctx)->ioctx_xtvlen = (xtvlen); \
396 (ioctx)->ioctx_cc = 0; \
397 (ioctx)->ioctx_errno = 0; \
398 TAILQ_INIT(&(ioctx)->ioctx_cbq); \
399 (ioctx)->ioctx_private = NULL; \
403 * Return whether access to a pnode is read-only.
405 #define IS_RDONLY(pno) \
406 ((pno)->p_mount->mnt_flags & MOUNT_F_RO)
408 extern struct pnode *_sysio_root;
410 extern TAILQ_HEAD(inodes_head, inode) _sysio_inodes;
411 extern TAILQ_HEAD(pnodes_head, pnode) _sysio_pnodes;
413 extern int _sysio_i_init(void);
414 #ifdef ZERO_SUM_MEMORY
415 extern void _sysio_i_shutdown(void);
417 extern struct inode *_sysio_i_new(struct filesys *fs,
418 struct file_identifier *fid,
419 struct intnl_stat *stat,
421 struct inode_ops *ops,
423 extern struct inode *_sysio_i_find(struct filesys *fs,
424 struct file_identifier *fid);
425 extern void _sysio_i_gone(struct inode *ino);
426 extern void _sysio_i_undead(struct inode *ino);
427 extern int _sysio_p_find_alias(struct pnode *parent,
429 struct pnode **pnop);
430 extern int _sysio_p_validate(struct pnode *pno,
431 struct intent *intnt,
433 extern struct pnode_base *_sysio_pb_new(struct qstr *name,
434 struct pnode_base *parent,
436 extern void _sysio_pb_gone(struct pnode_base *pb);
437 extern struct pnode *_sysio_p_new_alias(struct pnode *parent,
438 struct pnode_base *pb,
440 extern void _sysio_p_gone(struct pnode *pno);
441 extern size_t _sysio_p_prune(struct pnode *root);
442 extern int _sysio_p_kill_all(struct pnode *root);
443 extern char *_sysio_pb_path(struct pnode_base *pb, char separator);
444 extern int _sysio_setattr(struct pnode *pno,
447 struct intnl_stat *stbuf);
448 extern void _sysio_do_noop(void);
449 extern void _sysio_do_illop(void);
450 extern int _sysio_do_ebadf(void);
451 extern int _sysio_do_einval(void);
452 extern int _sysio_do_enoent(void);
453 extern int _sysio_do_enodev(void);
454 extern int _sysio_do_espipe(void);
455 extern int _sysio_do_eisdir(void);
456 extern int _sysio_do_enosys(void);
457 extern int _sysio_path_walk(struct pnode *parent, struct nameidata *nd);
458 #ifdef AUTOMOUNT_FILE_NAME
459 extern void _sysio_next_component(const char *path, struct qstr *name);
461 extern int _sysio_permitted(struct pnode *pno, int amode);
462 extern int _sysio_namei(struct pnode *pno,
465 struct intent *intnt,
466 struct pnode **pnop);
467 extern int _sysio_p_chdir(struct pnode *pno);
468 extern int _sysio_ioctx_init(void);
469 extern void _sysio_ioctx_enter(struct ioctx *ioctx);
470 extern struct ioctx *_sysio_ioctx_new(struct inode *ino,
472 const struct iovec *iov,
474 const struct intnl_xtvec *xtv,
476 extern int _sysio_ioctx_cb(struct ioctx *ioctx,
477 void (*f)(struct ioctx *, void *),
479 extern void _sysio_ioctx_cb_free(struct ioctx_callback *cb);
480 extern struct ioctx *_sysio_ioctx_find(void *id);
481 extern int _sysio_ioctx_done(struct ioctx *ioctx);
482 extern ssize_t _sysio_ioctx_wait(struct ioctx *ioctx);
483 extern void _sysio_ioctx_complete(struct ioctx *ioctx);
484 extern int _sysio_open(struct pnode *pno, int flags, mode_t mode);
485 extern int _sysio_mkdir(struct pnode *where, mode_t mode);
486 extern int _sysio_mknod(struct pnode *where, mode_t mode, dev_t dev);