/* Miscellaneous definitions, global vars, etc.
   Copyright (C) 1991, 1992 Free Software Foundation

This file is part of the GNU Hurd.

The GNU Hurd is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

The GNU Hurd is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with the GNU Hurd; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by Michael I. Bushnell.  */

#ifndef UFS_H_INCLUDED
#define UFS_H_INCLUDED

#include <mach.h>
#include <sys/types.h>
#include <hurd/hurd_types.h>
#include <setjmp.h>
#include <machine/ufs_machdep.h>

/* There should be a param.h with these in it: */
/* begin kludge XXX */
#define DEV_BSIZE 512
#define MAXSYMLINKS 32

#define NBBY 8

#define btodb(n) ((n) / DEV_BSIZE)
#define howmany(x,y) (((x)+((y)-1))/(y))
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
#define isclr(a, i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
#define isset(a, i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<(i)%NBBY))
/* end kludge XXX */

/* Types because MiG is stupid */
typedef struct protid *protid_t;

/* Global variables */

/* These come from our parent */
mach_port_t ufs_control_port;	/* Port implementing fsys protocol */
mach_port_t ufs_realnode;	/* Node mounted on */
file_t dotdot_file;		/* .. from root */

/* Port to the authentication server */
mach_port_t auth_server_port;

/* Port to execution server */
mach_port_t exec_server_port;

/* ports to devices */
mach_port_t master_device_port;
mach_port_t ufs_device;		/* physical device holding file system */

memory_object_t default_pager;	/* default pager for shared mem */

int readonly;			/* Set if filesystem is readonly */

/* Portsets communicated between files */
mach_port_t ufs_portset;	/* Global set of request ports we listen to */

time_value_t *time;		/* system mapped time */

struct fs *sblock;		/* Local copy of superblock */

int nextgennumber;		/* next generation for inode creation */

void *cgs;			/* mapped image of cylinder groups */
void *dinodes;			/* mapped image of inodes */

int long_dir_consistency_checking;

struct mutex bootlock;
struct condition bootsync;


enum lookup_type
{
  LOOKUP,
  CREATE,
  REMOVE,
  RENAME,
};

#define SPEC_DOTDOT 0x10000000	/* special flag for lookup */

enum slot_status
{
  LOOKING,
  TAKE,
  SHRINK,
  COMPRESS,
  EXTEND,
  HERE_TIS,
};

struct dirstat
{
  enum lookup_type type;
  enum slot_status stat;
  off_t blkoff;
  int prevoffinblk;
  int offinblk;
};

/* This is the data structure hung off each cthread with cthread_set_data */
struct thread_stuff
{
  jmp_buf buf;
  struct thread_stuff *link;
};

/* This macro is a short form for the jump buffer for a thread */
#define JMPBUF ((thread_stuff *)(cthread_data (cthread_self ()))->onerror)

/* Each port as a type in the first longword of its data structure,
   used to determine the type of port.  */
#define PT_NONE		0
#define PT_PROTID	1
#define PT_PAGER	2
#define PT_CTL		3
#define PT_DEVIO	4

/* Indirection data structures */

struct protid
{
  int porttype;			/* always PT_PROTID */
  int refcnt;			/* one per running request and 
				   one from ufs_portset.  */
  
  struct idlist *uids, *gids;
  int nuids, ngids;

  struct peropen *po;
  memory_object_t shared_object;
  struct shared_io *mapped;

  struct protid *nfree;
};

/* Each protid points to one of these */
/* The inode pointer in these structures can be referenced without */
 /* locking the peropen, because it never changes and the peropen */
 /* can't be deleted if a locked protid is pointing at it and holding */
 /* a ref.  This speeds up lots of routines that don't need this */
 /* structure for anything but the ip field. */
struct peropen
{
  int filepointer;
  int flock_status;		/* LOCK_EX, _SH, or _UN */
  int refcnt;
  int openstat;
  int state;
  struct inode *ip;

  struct peropen *nfree;
};

/* State includes the following bits: */
#define PO_NONBLOCK	1
#define PO_APPEND	2



/* Structure used for I/O */
struct ioreq
{
  int porttype;			/* always PT_DEVIO */
  int diskaddr;			/* in physical blocks */
  vm_address_t buffer;		/* where to buffer it */
  int amt;			/* amount to transfer in physical blocks */
  int error;			/* set if an error happens */
  void (*callback)();		/* Call when done */
};


/* Prototypes.  Ain't ANSI C fun?  */

/* From ufs_alloc.c: */
error_t alloc (struct inode *, daddr_t, daddr_t, int, daddr_t *, 
	       struct protid *);
error_t realloccg (struct inode *, daddr_t, daddr_t, int, int, daddr_t *,
		   struct protid *);
error_t ialloc (ino_t, mode_t, struct inode **);
ino_t dirpref ();
daddr_t blkpref (struct inode *, daddr_t, int, daddr_t *);
void blkfree (daddr_t, int);
void ifree (ino_t, mode_t);

/* From ufs_devio.c: */
void dev_read (struct ioreq *);
void dev_write (struct ioreq *);
error_t dev_write_sync (daddr_t, void *, long);
error_t dev_read_sync (daddr_t, void **, long);
void devio_thread (void);

/* From ufs_exception.c: */
void register_memory_fault_area (void *, long);
void unregister_memory_fault_area (void *, long);
void init_exceptions ();

/* From ufs_fsops.c: */
error_t do_stat (struct inode *, io_statbuf_t *);

/* From ufs_fsysops.c: */
fsys_t verify_fsys_port (fsys_t);

/* From ufs_inode.c: */
void inode_init (void);
error_t iget (ino_t, struct inode **);
struct inode *ifind (ino_t);
void iput (struct inode *);
void irele (struct inode *);
struct protid *convert_port_to_protid (mach_port_t);
mach_port_t convert_protid_to_port (struct protid *);
void release_protidport (struct protid *);
void release_peropen (struct peropen *);
void protid_nosenders (struct protid *);
struct protid *make_protid (struct inode *, int, struct protid *);

/* From ufs_ioops.c: */
error_t fs_rdwr (struct inode *, char *, off_t, int, int, struct protid *);
error_t file_extend (struct inode *, int, int, struct protid *);
off_t get_inode_vsize (struct inode *);
error_t fs_get_it (struct inode *);

/* From ufs_lookup.c: */
error_t lookup (struct inode *, char *, enum lookup_type, 
		struct inode **, struct dirstat *, struct protid *);
error_t ufs_access (struct inode *, mode_t, struct protid *);
int groupmember (gid_t, struct protid *);
int isuid (uid_t, struct protid *);
error_t isowner (struct inode *, struct protid *);
int dirempty (struct inode *, struct protid *);
error_t dirremove (struct inode *, struct dirstat *);
error_t direnter (struct inode *, char *, struct inode *,
		  struct dirstat *, struct protid *);
error_t dirrewrite (struct inode *, struct inode *, struct dirstat *);
error_t checkpath (struct inode *, struct inode *, struct protid *);
void dirbad (struct inode *, off_t, char *);
error_t pathnamecheck (char *);
void dsrelease (struct dirstat *);
error_t ufs_checkdirmod (struct inode *, mode_t,
			 struct inode *, struct protid *);

/* From ufs_machdep.c: */
void report_memory_fault (thread_t, int);
int thread_pc (thread_t);

/* From ufs_main.c: */
volatile void panic (char *);
volatile void panic_with_error (char *, error_t);

/* From ufs_pager.c: */
void pager_init (void);
void pager_shutdown (void);
void inode_update (struct inode *, int);
void din_map (struct inode *);
void sin_map (struct inode *);
void sin_remap (struct inode *, int);
mach_port_t get_filemap (struct inode *);
void file_update (struct inode *, int);
void inode_truncate (struct inode *, off_t);
void pager_nosenders (mach_port_t, int);
void sync_everything (int);

/* From ufs_subr.c: */
void fragacct (int, long *, int);
int isblock (u_char *, daddr_t);
void setblock (u_char *, daddr_t);
void clrblock (u_char *, daddr_t);

/* From ufs_trans.c: */
void destroy_translator (struct inode *, int);

#endif /* UFS_H_INCLUDED */
