/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
* pass the elements required to identify a file to the underlying file
* systen. For the usual Vice inode operations, this is no more than the
* usual device and inode numbers. For the user space file system used on NT
- * we also need the volume id to identify the file.
+ * we also need the volume id to identify the file.
*
* An FdHandle_t is an abstraction used to associate file descroptors
* with Inode handles. IH_OPEN is used to get a file descriptor that
#define _IHANDLE_H_
#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
#include <pthread.h>
extern pthread_once_t ih_glock_once;
extern pthread_mutex_t ih_glock_mutex;
extern void ih_glock_init(void);
#define IH_LOCK \
- assert(pthread_once(&ih_glock_once, ih_glock_init) == 0 && \
- pthread_mutex_lock(&ih_glock_mutex) == 0)
-#define IH_UNLOCK \
- assert(pthread_mutex_unlock(&ih_glock_mutex) == 0)
+ do { osi_Assert(pthread_once(&ih_glock_once, ih_glock_init) == 0); \
+ MUTEX_ENTER(&ih_glock_mutex); \
+ } while (0)
+#define IH_UNLOCK MUTEX_EXIT(&ih_glock_mutex)
#else /* AFS_PTHREAD_ENV */
#define IH_LOCK
#define IH_UNLOCK
else \
(head) = (ptr)->next; \
(ptr)->next = (ptr)->prev = NULL; \
- assert(!(head) || !((head)->prev)); \
+ osi_Assert(!(head) || !((head)->prev)); \
} while(0)
/*
(ptr)->prev->next = (ptr); \
else \
(head) = (ptr); \
- assert((head) && ((head)->prev == NULL)); \
+ osi_Assert((head) && ((head)->prev == NULL)); \
} while(0)
#endif /* DLL_INIT_LIST */
struct IHandle_s;
/* File descriptors are HANDLE's on NT. The following typedef helps catch
- * type errors.
+ * type errors. duplicated in libadmin/vos/afs_vosAdmin.c
*/
#ifdef AFS_NT40_ENV
typedef HANDLE FD_t;
/* file descriptor handle */
typedef struct FdHandle_s {
int fd_status; /* status flags */
+ int fd_refcnt; /* refcnt */
FD_t fd_fd; /* file descriptor */
struct IHandle_s *fd_ih; /* Pointer to Inode handle */
struct FdHandle_s *fd_next; /* LRU/Avail list pointers */
int str_direction; /* current read/write direction */
afs_sfsize_t str_buflen; /* bytes remaining in buffer */
afs_foff_t str_bufoff; /* current offset into buffer */
+ afs_foff_t str_fdoff; /* current offset into file */
int str_error; /* error code */
int str_eof; /* end of file flag */
struct StreamHandle_s *str_next; /* Avail list pointers */
#define FD_HANDLE_MALLOCSIZE ((size_t)((4096/sizeof(FdHandle_t))))
#define STREAM_HANDLE_MALLOCSIZE 1
+
+/* READ THIS.
+ *
+ * On modern platforms tuned for I/O intensive workloads, there may be
+ * thousands of file descriptors available (64K on 32-bit Solaris 7,
+ * for example), and threading in Solaris 9 and Linux 2.6 (NPTL) are
+ * tuned for (many) thousands of concurrent threads at peak.
+ *
+ * On these platforms, it makes sense to allow administrators to set
+ * appropriate limits for their hardware. Clients may now set desired
+ * values in the exported vol_io_params, of type ih_init_params.
+ */
+
+typedef struct ih_init_params
+{
+ afs_uint32 fd_handle_setaside; /* for non-cached i/o, trad. was 128 */
+ afs_uint32 fd_initial_cachesize; /* what was 'default' */
+ afs_uint32 fd_max_cachesize; /* max open files if large-cache activated */
+} ih_init_params;
+
+
/* Number of file descriptors needed for non-cached I/O */
-#define FD_HANDLE_SETASIDE 64
+#define FD_HANDLE_SETASIDE 128 /* Match to MAX_FILESERVER_THREAD */
+
+/* Which systems have 8-bit fileno? On GNU/Linux systems, the
+ * fileno member of FILE is an int. On NetBSD 5, it's a short.
+ * Ditto for OpenBSD 4.5. Through Solaris 10 8/07 it's unsigned char.
+ */
/* Don't try to have more than 256 files open at once if you are planning
* to use fopen or fdopen. The FILE structure has an eight bit field for
*/
#define FD_MAX_CACHESIZE (2000 - FD_HANDLE_SETASIDE)
+/* On modern platforms, this is sized higher than the note implies.
+ * For HP, see http://forums11.itrc.hp.com/service/forums/questionanswer.do?admit=109447626+1242508538748+28353475&threadId=302950
+ * On AIX, it's said to be self-tuning (sar -v)
+ * On Solaris, http://www.princeton.edu/~unix/Solaris/troubleshoot/kerntune.html
+ * says stdio limit (FILE) may exist, but then backtracks and says the 64bit
+ * solaris and POLL (rather than select) io avoid the issue. Solaris Internals
+ * states that Solaris 7 and above deal with up to 64K on 32bit.
+ * However, extended FILE must be enabled to use this. See
+ * enable_extended_FILE_stdio(3C)
+ */
+
/* Inode handle */
typedef struct IHandle_s {
- int ih_vid; /* Parent volume id. */
+ afs_uint32 ih_vid; /* Parent volume id. */
int ih_dev; /* device id. */
int ih_flags; /* Flags */
+ int ih_synced; /* should be synced next time */
Inode ih_ino; /* Inode number */
int ih_refcnt; /* reference count */
struct FdHandle_s *ih_fdhead; /* List of open file desciptors */
#define IH_REALLY_CLOSED 1
/* Hash function for inode handles */
-#define I_HANDLE_HASH_SIZE 1024 /* power of 2 */
+#define I_HANDLE_HASH_SIZE 2048 /* power of 2 */
+
/* The casts to int's ensure NT gets the xor operation correct. */
#define IH_HASH(D, V, I) ((int)(((D)^(V)^((int)(I)))&(I_HANDLE_HASH_SIZE-1)))
/*
* Prototypes for file descriptor cache routines
*/
+extern void ih_PkgDefaults(void);
extern void ih_Initialize(void);
extern void ih_UseLargeCache(void);
extern IHandle_t *ih_init(int /*@alt Device@ */ dev, int /*@alt VolId@ */ vid,
extern afs_sfsize_t stream_write(void *ptr, afs_fsize_t size,
afs_fsize_t nitems,
StreamHandle_t * streamP);
-extern int stream_seek(StreamHandle_t * streamP, afs_foff_t offset,
- int whence);
+extern int stream_aseek(StreamHandle_t * streamP, afs_foff_t offset);
extern int stream_flush(StreamHandle_t * streamP);
extern int stream_close(StreamHandle_t * streamP, int reallyClose);
extern int ih_reallyclose(IHandle_t * ihP);
#define STREAM_WRITE(A, B, C, H) stream_write(A, B, C, H)
-#define STREAM_SEEK(H, A, B) stream_seek(H, A, B)
+#define STREAM_ASEEK(H, A) stream_aseek(H, A)
#define STREAM_FLUSH(H) stream_flush(H)
#define IH_CONDSYNC(H) ih_condsync(H)
+#ifdef HAVE_PIO
+#ifdef AFS_NT40_ENV
+#define OS_PREAD(FD, B, S, O) nt_pread(FD, B, S, O)
+#define OS_PWRITE(FD, B, S, O) nt_pwrite(FD, B, S, O)
+#else
+#ifdef O_LARGEFILE
+#define OS_PREAD(FD, B, S, O) pread64(FD, B, S, O)
+#define OS_PWRITE(FD, B, S, O) pwrite64(FD, B, S, O)
+#else /* !O_LARGEFILE */
+#define OS_PREAD(FD, B, S, O) pread(FD, B, S, O)
+#define OS_PWRITE(FD, B, S, O) pwrite(FD, B, S, O)
+#endif /* !O_LARGEFILE */
+#endif /* AFS_NT40_ENV */
+#else /* !HAVE_PIO */
+extern ssize_t ih_pread(int fd, void * buf, size_t count, afs_foff_t offset);
+extern ssize_t ih_pwrite(int fd, const void * buf, size_t count, afs_foff_t offset);
+#define OS_PREAD(FD, B, S, O) ih_pread(FD, B, S, O)
+#define OS_PWRITE(FD, B, S, O) ih_pwrite(FD, B, S, O)
+#endif /* !HAVE_PIO */
+
#ifdef AFS_NAMEI_ENV
#ifdef AFS_NT40_ENV
extern int OS_CLOSE(int FD);
extern ssize_t OS_READ(int FD, void *B, size_t S);
extern ssize_t OS_WRITE(int FD, void *B, size_t S);
+extern ssize_t OS_PREAD(int FD, void *B, size_t S, afs_foff_t O);
+extern ssize_t OS_PWRITE(int FD, void *B, size_t S, afs_foff_t O);
extern int OS_SYNC(int FD);
extern afs_sfsize_t OS_SIZE(int FD);
extern int IH_INC(IHandle_t * H, Inode I, int /*@alt VolId, VolumeId @ */ P);
#define OS_OPEN(F, M, P) open(F, M, P)
#define OS_CLOSE(FD) close(FD)
-#define OS_READ(FD, B, S) read(FD, B, S)
-#define OS_WRITE(FD, B, S) write(FD, B, S)
#ifdef O_LARGEFILE
#define OS_SEEK(FD, O, F) lseek64(FD, (off64_t) (O), F)
#else /* !O_LARGEFILE */
#define FDH_WRITEV(H, I, N) writev((H)->fd_fd, I, N)
#endif
+#ifdef HAVE_PIOV
+#define FDH_PREADV(H, I, N, O) preadv((H)->fd_fd, I, N, O)
+#define FDH_PWRITEV(H, I, N, O) pwritev((H)->fd_fd, I, N, O)
+#endif
+
+#define FDH_PREAD(H, B, S, O) OS_PREAD((H)->fd_fd, B, S, O)
+#define FDH_PWRITE(H, B, S, O) OS_PWRITE((H)->fd_fd, B, S, O)
#define FDH_READ(H, B, S) OS_READ((H)->fd_fd, B, S)
#define FDH_WRITE(H, B, S) OS_WRITE((H)->fd_fd, B, S)
#define FDH_SEEK(H, O, F) OS_SEEK((H)->fd_fd, O, F)
-#define FDH_SYNC(H) OS_SYNC((H)->fd_fd)
+#define FDH_SYNC(H) ((H->fd_ih!=NULL) ? ( H->fd_ih->ih_synced = 1) - 1 : 1)
#define FDH_TRUNC(H, L) OS_TRUNC((H)->fd_fd, L)
#define FDH_SIZE(H) OS_SIZE((H)->fd_fd)