Whamcloud - gitweb
b=17604
[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-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
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_filldirentries)(struct inode *ino,
90                                    _SYSIO_OFF_T *posp,
91                                    char *buf,
92                                    size_t nbytes);
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     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 */
144 };
145
146 /*
147  * Init an i-node record.
148  */
149 #define I_INIT(ino, fs, stat, ops, fid, immunity, private) \
150     do { \
151         (ino)->i_immune = (immunity) ? 1 : 0; \
152         (ino)->i_zombie = 0; \
153         (ino)->i_ref = 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); \
159     } while (0)
160
161 /*
162  * Take soft reference to i-node.
163  */
164 #define I_REF(ino) \
165     do { \
166         TAILQ_REMOVE(&_sysio_inodes, (ino), i_nodes); \
167         TAILQ_INSERT_TAIL(&_sysio_inodes, (ino), i_nodes); \
168         (ino)->i_ref++; \
169         assert((ino)->i_ref); \
170     } while (0)
171
172 /*
173  * Release soft reference to i-node.
174  */
175 #define I_RELE(ino) \
176     do { \
177         assert((ino)->i_ref); \
178         if (!--(ino)->i_ref && (ino)->i_zombie) \
179                 _sysio_i_gone(ino); \
180     } while (0)
181
182 /*
183  * Attempt to kill an inode.
184  */
185 #define I_GONE(ino) \
186     do { \
187         _sysio_i_undead(ino); \
188         I_RELE(ino); \
189     } while (0)
190
191 /*
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.
195  */
196 struct qstr {
197     const char *name;
198     size_t  len;
199     unsigned hashval;
200 };
201
202 /*
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.
206  */
207 struct pnode_base {
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 */
215 };
216
217 /*
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.
221  *
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.
225  *
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.
230  *
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.
234  *
235  * The base value points to the base path node information. It is info common
236  * to all of the aliases.
237  *
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.
242  *
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.
245  *
246  * The links list entry holds pointers to other aliases for the base path
247  * node entry.
248  *
249  * The nodes link is bookkeeping.
250  */
251 struct pnode {
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 */
259 };
260
261 /*
262  * Reference path-tree node.
263  */
264 #define P_REF(pno) \
265     do { \
266         TAILQ_REMOVE(&_sysio_pnodes, (pno), p_nodes); \
267         TAILQ_INSERT_TAIL(&_sysio_pnodes, (pno), p_nodes); \
268         (pno)->p_ref++; \
269         assert((pno)->p_ref); \
270     } while (0)
271
272 /*
273  * Release reference to path-tree node.
274  */
275 #define P_RELE(pno) \
276     do { \
277         assert((pno)->p_ref); \
278         --(pno)->p_ref; \
279     } while (0)
280
281 /*
282  * An intent record allows callers of namei and lookup to pass some information
283  * about what they want to accomplish in the end.
284  */
285 struct intent {
286     unsigned int_opmask;                
287     void    *int_arg1;
288     void    *int_arg2;
289 };
290
291 /*
292  * Intent operations.
293  */
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 */
300
301 #define INTENT_INIT(intnt, mask, arg1, arg2) \
302     do { \
303         (intnt)->int_opmask = (mask); \
304         (intnt)->int_arg1 = (arg1); \
305         (intnt)->int_arg2 = (arg2); \
306     } while (0)
307
308 /*
309  * Bundled up arguments to _sysio_path_walk.
310  */
311 struct nameidata {
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 */
320 #endif
321 };
322
323 /*
324  * Values for nameidata flags field.
325  */
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 */
329
330 #ifdef AUTOMOUNT_FILE_NAME
331 #define _ND_INIT_AUTOMOUNT(nd)  ((nd)->nd_amcnt = 0)
332 #else
333 #define _ND_INIT_AUTOMOUNT(nd)
334 #endif
335
336 #define _ND_INIT_OTHERS(nd) \
337     _ND_INIT_AUTOMOUNT(nd)
338
339 /*
340  * Init nameidata record.
341  */
342 #define ND_INIT(nd, flags, path, root, intnt) \
343     do { \
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); \
351     } while (0)
352
353 /*
354  * IO completion callback record.
355  */
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 */
360 };
361
362 /*
363  * All IO internally is done with an asynchronous mechanism. This record
364  * holds the completion information. It's too big :-(
365  */
366 struct ioctx {
367     LIST_ENTRY(ioctx) ioctx_link;                       /* AIO list link */
368     unsigned
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 */
381 };
382
383 /*
384  * Init IO context record.
385  */
386 #define IOCTX_INIT(ioctx, fast, wr, ino, iov, iovlen, xtv, xtvlen) \
387     do { \
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; \
400     } while (0)
401
402 /*
403  * Return whether access to a pnode is read-only.
404  */
405 #define IS_RDONLY(pno) \
406         ((pno)->p_mount->mnt_flags & MOUNT_F_RO)
407
408 extern struct pnode *_sysio_root;
409
410 extern TAILQ_HEAD(inodes_head, inode) _sysio_inodes;
411 extern TAILQ_HEAD(pnodes_head, pnode) _sysio_pnodes;
412
413 extern int _sysio_i_init(void);
414 #ifdef ZERO_SUM_MEMORY
415 extern void _sysio_i_shutdown(void);
416 #endif
417 extern struct inode *_sysio_i_new(struct filesys *fs,
418                                   struct file_identifier *fid,
419                                   struct intnl_stat *stat,
420                                   unsigned immunity,
421                                   struct inode_ops *ops,
422                                   void *private);
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,
428                                struct qstr *name,
429                                struct pnode **pnop);
430 extern int _sysio_p_validate(struct pnode *pno,
431                              struct intent *intnt,
432                              const char *path);
433 extern struct pnode_base *_sysio_pb_new(struct qstr *name,
434                                         struct pnode_base *parent,
435                                         struct inode *ino);
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,
439                                         struct mount *mnt);
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,
445                           struct inode *ino,
446                           unsigned mask,
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);
460 #endif
461 extern int _sysio_permitted(struct pnode *pno, int amode);
462 extern int _sysio_namei(struct pnode *pno,
463                         const char *path,
464                         unsigned flags,
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,
471                                       int wr,
472                                       const struct iovec *iov,
473                                       size_t iovlen,
474                                       const struct intnl_xtvec *xtv,
475                                       size_t xtvlen);
476 extern int _sysio_ioctx_cb(struct ioctx *ioctx,
477                            void (*f)(struct ioctx *, void *),
478                            void *data);
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);