Whamcloud - gitweb
import libsysio for b_newsysio
[fs/lustre-release.git] / libsysio / include / inode.h
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 #if defined(AUTOMOUNT_FILE_NAME) && !defined(MAX_MOUNT_DEPTH)
45 /*
46  * Maximum number of automounts to attempt in path traversal.
47  */
48 #define MAX_MOUNT_DEPTH         64
49 #endif
50
51 /*
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.
55  */
56 struct file_identifier {
57     void    *fid_data;
58     size_t  fid_len;
59 };
60
61 struct pnode;
62 struct inode;
63 struct intent;
64 struct intnl_dirent;
65 struct intnl_stat;
66 #ifdef _HAVE_STATVFS
67 struct intnl_statvfs;
68 #endif
69 struct io_arguments;
70 struct ioctx;
71
72 /*
73  * Operations on i-nodes.
74  *
75  * Should this be split up into file and name space operations?
76  */
77 struct inode_ops {
78     int (*inop_lookup)(struct pnode *pno,
79                        struct inode **inop,
80                        struct intent *intnt,
81                        const char *path);
82     int (*inop_getattr)(struct pnode *pno,
83                         struct inode *ino,
84                         struct intnl_stat *stbuf);
85     int (*inop_setattr)(struct pnode *pno,
86                         struct inode *ino,
87                         unsigned mask,
88                         struct intnl_stat *stbuf);
89     ssize_t (*inop_getdirentries)(struct inode *ino,
90                                   char *buf,
91                                   size_t nbytes,
92                                   _SYSIO_OFF_T *basep);
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);
111 #ifdef _HAVE_STATVFS
112     int (*inop_statvfs)(struct pnode *pno,
113                         struct inode *ino,
114                         struct intnl_statvfs *buf);
115 #endif
116     void    (*inop_gone)(struct inode *ino);
117 };
118
119 /*
120  * Values for the mask to inop_setattr.
121  */
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
128
129 /*
130  * An i-node record is maintained for each file object in the system.
131  */
132 struct inode {
133     LIST_ENTRY(inode) i_link;                           /* FS i-nodes link */
134     unsigned
135         i_immune                        : 1,            /* immune from GC */
136         i_zombie                        : 1;            /* stale inode */
137     unsigned i_ref;                                     /* soft ref counter */
138     mode_t  i_mode;                                     /* mode (see stat.h) */
139     dev_t   i_rdev;                                     /* dev (if device) */
140     struct inode_ops i_ops;                             /* operations */
141     struct filesys *i_fs;                               /* file system ptr */
142     struct file_identifier *i_fid;                      /* file ident */
143     void    *i_private;                                 /* driver data */
144     TAILQ_ENTRY(inode) i_nodes;                         /* all i-nodes link */
145 };
146
147 /*
148  * Init an i-node record.
149  */
150 #define I_INIT(ino, fs, mode, rdev, ops, fid, immunity, private) \
151     do { \
152         (ino)->i_immune = (immunity) ? 1 : 0; \
153         (ino)->i_zombie = 0; \
154         (ino)->i_ref = 0; \
155         (ino)->i_mode = (mode); \
156         (ino)->i_rdev = (rdev); \
157         (ino)->i_ops = *(ops); \
158         (ino)->i_fs = (fs); \
159         (ino)->i_fid = (fid); \
160         (ino)->i_private = (private); \
161     } while (0)
162
163 /*
164  * Take soft reference to i-node.
165  */
166 #define I_REF(ino) \
167     do { \
168         TAILQ_REMOVE(&_sysio_inodes, (ino), i_nodes); \
169         TAILQ_INSERT_TAIL(&_sysio_inodes, (ino), i_nodes); \
170         (ino)->i_ref++; \
171         assert((ino)->i_ref); \
172     } while (0)
173
174 /*
175  * Release soft reference to i-node.
176  */
177 #define I_RELE(ino) \
178     do { \
179         assert((ino)->i_ref); \
180         if (!--(ino)->i_ref && (ino)->i_zombie) \
181                 _sysio_i_gone(ino); \
182     } while (0)
183
184 /*
185  * Attempt to kill an inode.
186  */
187 #define I_GONE(ino) \
188     do { \
189         _sysio_i_undead(ino); \
190         I_RELE(ino); \
191     } while (0)
192
193 /*
194  * The "quick string" record (inspired by the structure of the same name
195  * from Linux) is used to pass a string without delimiters as well as useful
196  * information about the string.
197  */
198 struct qstr {
199     const char *name;
200     size_t  len;
201     unsigned hashval;
202 };
203
204 /*
205  * A path node is an entry in a directory. It may have many aliases, one
206  * for each name space in which it occurs. This record holds the
207  * common information.
208  */
209 struct pnode_base {
210     struct qstr pb_name;                                /* entry name */
211     struct inode *pb_ino;                               /* inode */
212     LIST_HEAD(, pnode_base) pb_children;                /* children if a dir */
213     LIST_ENTRY(pnode_base) pb_sibs;                     /* links to siblings */
214     LIST_ENTRY(pnode_base) pb_names;                    /* near names links */
215     LIST_HEAD(, pnode) pb_aliases;                      /* aliases */
216     struct pnode_base *pb_parent;                       /* parent */
217 };
218
219 /*
220  * Since a file system may be multiply mounted, in different parts of the local
221  * tree, a file system object may appear in different places. We handle that
222  * with aliases. There is one pnode for every alias the system is tracking.
223  *
224  * Name space traversal depends heavily on the interpretation of many
225  * of the fields in this structure. For that reason a detailed discussion
226  * of the various fields is given.
227  *
228  * The reference field records soft references to the record. For instance,
229  * it tracks file and directory opens. It does not track sibling references,
230  * though, as those are hard references and can be found by examining the
231  * aliases list in the base part of the node.
232  *
233  * The parent value points to the parent directory for this entry, in the
234  * *system* name space -- Not the mounted volumes. If you want to examine
235  * the moutned volume name space, use the base record.
236  *
237  * The base value points to the base path node information. It is info common
238  * to all of the aliases.
239  *
240  * The mount value points to the mount record for the rooted name space in
241  * which the alias is found. Notably, if a node is the root of a sub-tree then
242  * the mount record, among other things, indicates another node
243  * (in another sub-tree) that is covered by this one.
244  *
245  * Another sub-tree, mounted on this node, is indicated by a non-null cover.
246  * The pnode pointed to, then, is the root of the mounted sub-tree.
247  *
248  * The links list entry holds pointers to other aliases for the base path
249  * node entry.
250  *
251  * The nodes link is bookkeeping.
252  */
253 struct pnode {
254     unsigned p_ref;                                     /* soft ref count */
255     struct pnode *p_parent;                             /* parent */
256     struct pnode_base *p_base;                          /* base part */
257     struct mount *p_mount;                              /* mount info */
258     struct pnode *p_cover;                              /* covering pnode */
259     LIST_ENTRY(pnode) p_links;                          /* other aliases */
260     TAILQ_ENTRY(pnode) p_nodes;                         /* all nodes links */
261 };
262
263 /*
264  * Reference path-tree node.
265  */
266 #define P_REF(pno) \
267     do { \
268         TAILQ_REMOVE(&_sysio_pnodes, (pno), p_nodes); \
269         TAILQ_INSERT_TAIL(&_sysio_pnodes, (pno), p_nodes); \
270         (pno)->p_ref++; \
271         assert((pno)->p_ref); \
272     } while (0)
273
274 /*
275  * Release reference to path-tree node.
276  */
277 #define P_RELE(pno) \
278     do { \
279         assert((pno)->p_ref); \
280         --(pno)->p_ref; \
281     } while (0)
282
283 /*
284  * An intent record allows callers of namei and lookup to pass some information
285  * about what they want to accomplish in the end.
286  */
287 struct intent {
288     unsigned int_opmask;                
289     void    *int_arg1;
290     void    *int_arg2;
291 };
292
293 /*
294  * Intent operations.
295  */
296 #define INT_GETATTR         0x01                        /* get attrs */
297 #define INT_SETATTR         0x02                        /* set attrs */
298 #define INT_UPDPARENT       0x04                        /* insert/delete */
299 #define INT_OPEN            0x08                        /* open */
300 #define INT_CREAT           (INT_UPDPARENT|0x10)        /* insert */
301 #define INT_READLINK        0x12                        /* readlink */
302
303 #define INTENT_INIT(intnt, mask, arg1, arg2) \
304     do { \
305         (intnt)->int_opmask = (mask); \
306         (intnt)->int_arg1 = (arg1); \
307         (intnt)->int_arg2 = (arg2); \
308     } while (0)
309
310 /*
311  * Bundled up arguments to _sysio_path_walk.
312  */
313 struct nameidata {
314     unsigned nd_flags;                                  /* flags (see below) */
315     const char *nd_path;                                /* path arg */
316     struct pnode *nd_pno;                               /* returned pnode */
317     struct pnode *nd_root;                              /* system/user root */
318     struct intent *nd_intent;                           /* intent (NULL ok) */
319     unsigned nd_slicnt;                                 /* symlink indirects */
320 #ifdef AUTOMOUNT_FILE_NAME
321     unsigned nd_amcnt;                                  /* automounts */
322 #endif
323 };
324
325 /*
326  * Values for nameidata flags field.
327  */
328 #define ND_NOFOLLOW     0x01                            /* no follow symlinks */
329 #define ND_NEGOK        0x02                            /* last missing is ok */
330
331 #ifdef AUTOMOUNT_FILE_NAME
332 #define _ND_INIT_AUTOMOUNT(nd)  ((nd)->nd_amcnt = 0)
333 #else
334 #define _ND_INIT_AUTOMOUNT(nd)
335 #endif
336
337 #define _ND_INIT_OTHERS(nd) \
338     _ND_INIT_AUTOMOUNT(nd)
339
340 /*
341  * Init nameidata record.
342  */
343 #define ND_INIT(nd, flags, path, root, intnt) \
344     do { \
345         (nd)->nd_flags = (flags); \
346         (nd)->nd_path = (path); \
347         (nd)->nd_pno = NULL; \
348         (nd)->nd_root = (root); \
349         (nd)->nd_intent = (intnt); \
350         (nd)->nd_slicnt = 0; \
351         _ND_INIT_OTHERS(nd); \
352     } while (0)
353
354 /*
355  * IO completion callback record.
356  */
357 struct ioctx_callback {
358     TAILQ_ENTRY(ioctx_callback) iocb_next;             /* list link */
359     void    (*iocb_f)(struct ioctx *, void *);         /* cb func */
360     void    *iocb_data;                                /* cb data */
361 };
362
363 /*
364  * All IO internally is done with an asynchronous mechanism. This record
365  * holds the completion information. It's too big :-(
366  */
367 struct ioctx {
368     LIST_ENTRY(ioctx) ioctx_link;                       /* AIO list link */
369     unsigned
370         ioctx_fast                      : 1,            /* from stack space */
371         ioctx_done                      : 1,            /* transfer complete */
372         ioctx_write                     : 1;            /* op is a write */
373     struct inode *ioctx_ino;                            /* i-node */
374     const struct iovec *ioctx_iov;                      /* scatter/gather vec */
375     size_t  ioctx_iovlen;                               /* iovec length */
376     const struct intnl_xtvec *ioctx_xtv;                /* extents */
377     size_t  ioctx_xtvlen;                               /* xtv length */
378     ssize_t ioctx_cc;                                   /* rtn char count */
379     int ioctx_errno;                                    /* error number */
380     TAILQ_HEAD(, ioctx_callback) ioctx_cbq;             /* callback queue */
381     void *ioctx_private;                                /* driver data */
382 };
383
384 /*
385  * Init IO context record.
386  */
387 #define IOCTX_INIT(ioctx, fast, wr, ino, iov, iovlen, xtv, xtvlen) \
388     do { \
389         (ioctx)->ioctx_fast = (fast); \
390         (ioctx)->ioctx_done = 0; \
391         (ioctx)->ioctx_write = (wr) ? 1 : 0; \
392         (ioctx)->ioctx_ino = (ino); \
393         (ioctx)->ioctx_iov = (iov); \
394         (ioctx)->ioctx_iovlen = (iovlen); \
395         (ioctx)->ioctx_xtv = (xtv); \
396         (ioctx)->ioctx_xtvlen = (xtvlen); \
397         (ioctx)->ioctx_cc = 0; \
398         (ioctx)->ioctx_errno = 0; \
399         TAILQ_INIT(&(ioctx)->ioctx_cbq); \
400         (ioctx)->ioctx_private = NULL; \
401     } while (0)
402
403 /*
404  * Return whether a pnode/inode is on a read-only mount or file system.
405  */
406 #define IS_RDONLY(pno, ino) \
407         ((((struct pnode *)(pno)) && \
408           ((((struct pnode *)(pno))->p_mount->mnt_flags & MOUNT_F_RO) || \
409            (((struct pnode *)(pno))->p_base->pb_ino && \
410             (((struct pnode *)(pno))->p_base->pb_ino->i_fs->fs_flags & \
411              FS_F_RO)))) || \
412          (((struct inode *)(ino)) && \
413           (((struct inode *)(ino))->i_fs->fs_flags & FS_F_RO)))
414
415 extern struct pnode *_sysio_root;
416
417 extern TAILQ_HEAD(inodes_head, inode) _sysio_inodes;
418 extern TAILQ_HEAD(pnodes_head, pnode) _sysio_pnodes;
419
420 extern int _sysio_i_init(void);
421 #if ZERO_SUM_MEMORY
422 extern void _sysio_i_shutdown(void);
423 #endif
424 extern struct inode *_sysio_i_new(struct filesys *fs,
425                                   struct file_identifier *fid,
426                                   mode_t type,
427                                   dev_t rdev,
428                                   unsigned immunity,
429                                   struct inode_ops *ops,
430                                   void *private);
431 extern struct inode *_sysio_i_find(struct filesys *fs,
432                                    struct file_identifier *fid);
433 extern void _sysio_i_gone(struct inode *ino);
434 extern void _sysio_i_undead(struct inode *ino);
435 extern int _sysio_p_find_alias(struct pnode *parent,
436                                struct qstr *name,
437                                struct pnode **pnop);
438 extern int _sysio_p_validate(struct pnode *pno,
439                              struct intent *intnt,
440                              const char *path);
441 extern struct pnode_base *_sysio_pb_new(struct qstr *name,
442                                         struct pnode_base *parent,
443                                         struct inode *ino);
444 extern void _sysio_pb_gone(struct pnode_base *pb);
445 extern struct pnode *_sysio_p_new_alias(struct pnode *parent,
446                                         struct pnode_base *pb,
447                                         struct mount *mnt);
448 extern void _sysio_p_gone(struct pnode *pno);
449 extern size_t _sysio_p_prune(struct pnode *root);
450 extern int _sysio_p_kill_all(struct pnode *root);
451 extern char *_sysio_pb_path(struct pnode_base *pb, char separator);
452 extern int _sysio_setattr(struct pnode *pno,
453                           struct inode *ino,
454                           unsigned mask,
455                           struct intnl_stat *stbuf);
456 extern void _sysio_do_noop(void);
457 extern void _sysio_do_illop(void);
458 extern int _sysio_do_ebadf(void);
459 extern int _sysio_do_einval(void);
460 extern int _sysio_do_enoent(void);
461 extern int _sysio_do_enodev(void);
462 extern int _sysio_do_espipe(void);
463 extern int _sysio_do_eisdir(void);
464 extern int _sysio_do_enosys(void);
465 extern int _sysio_path_walk(struct pnode *parent, struct nameidata *nd);
466 #ifdef AUTOMOUNT_FILE_NAME
467 extern void _sysio_next_component(const char *path, struct qstr *name);
468 #endif
469 extern int _sysio_namei(struct pnode *pno,
470                         const char *path,
471                         unsigned flags,
472                         struct intent *intnt,
473                         struct pnode **pnop);
474 extern int _sysio_p_chdir(struct pnode *pno);
475 extern int _sysio_ioctx_init(void);
476 extern void _sysio_ioctx_enter(struct ioctx *ioctx);
477 extern struct ioctx *_sysio_ioctx_new(struct inode *ino,
478                                       int wr,
479                                       const struct iovec *iov,
480                                       size_t iovlen,
481                                       const struct intnl_xtvec *xtv,
482                                       size_t xtvlen);
483 extern int _sysio_ioctx_cb(struct ioctx *ioctx,
484                            void (*f)(struct ioctx *, void *),
485                            void *data);
486 extern void _sysio_ioctx_cb_free(struct ioctx_callback *cb);
487 extern struct ioctx *_sysio_ioctx_find(void *id);
488 extern ssize_t _sysio_ioctx_wait(struct ioctx *ioctx);
489 extern void _sysio_ioctx_complete(struct ioctx *ioctx);
490 extern ssize_t _sysio_validx(const struct intnl_xtvec *xtv, size_t xtvlen,
491                              const struct iovec *iov, size_t iovlen,
492                              _SYSIO_OFF_T limit);
493 extern ssize_t _sysio_enumerate_extents(const struct intnl_xtvec *xtv,
494                                         size_t xtvlen,
495                                         const struct iovec *iov,
496                                         size_t iovlen,
497                                         ssize_t (*f)(const struct iovec *,
498                                                      int,
499                                                      _SYSIO_OFF_T,
500                                                      ssize_t,
501                                                      void *),
502                                         void *arg);
503 extern ssize_t _sysio_enumerate_iovec(const struct iovec *iov,
504                                       size_t count,
505                                       _SYSIO_OFF_T off,
506                                       ssize_t limit,
507                                       ssize_t (*f)(void *,
508                                                    size_t,
509                                                    _SYSIO_OFF_T,
510                                                    void *),
511                                       void *arg);
512 extern ssize_t _sysio_doio(const struct intnl_xtvec *xtv, size_t xtvlen,
513                            const struct iovec *iov, size_t iovlen,
514                            ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, void *),
515                            void *arg);
516 extern int _sysio_open(struct pnode *pno, int flags, mode_t mode);