* cached by IO_CLOSE. To make sure a file descriptor is really closed call
* IH_REALLYCLOSE.
*
+ * Note that IH_REALLYCLOSE does not guarantee that all file descriptors are
+ * closed (or are marked as needing close) by the time it returns, in the case
+ * of an IH_OPEN being executed in parallel. If a separate thread is running
+ * an IH_OPEN on the same IHandle_t at around the same time, it is possible for
+ * it to open the file, then IH_REALLYCLOSE runs, and then IH_OPEN associates
+ * the file handle with the IHandle_t. For this reason, it is probably an
+ * error if it is ever possible to have an IH_OPEN call run at the same time as
+ * an IH_REALLYCLOSE call on the same IHandle_t. If such functionality is
+ * required, ihandle must be changed to accomodate this.
+ *
* The IHandle_t also provides a place to do other optimizations. In the
* NT user space file system, we keep a separate special file for the
* link counts and using the IHandle_t allows keeping the details of
*
* Replacements for C runtime file operations
* FDH_READ/FDH_WRITE - read/write using the file descriptor.
- * FDH_READV/FDH_WRITEV - readv/writev (Unix only)
* FDH_SEEK - set file handle's read/write position
* FDH_CLOSE - return a file descriptor to the cache
* FDH_REALLYCLOSE - Close a file descriptor, do not return to the cache
#define FD_HANDLE_MALLOCSIZE ((size_t)((4096/sizeof(FdHandle_t))))
#define STREAM_HANDLE_MALLOCSIZE 1
+/* Possible values for the vol_io_params.sync_behavior option.
+ * These dictate what actually happens when you call FDH_SYNC or IH_CONDSYNC. */
+#define IH_SYNC_ALWAYS (1) /* This makes FDH_SYNCs do what you'd probably
+ * expect: a synchronous fsync() */
+#define IH_SYNC_ONCLOSE (2) /* This makes FDH_SYNCs just flag the ih as "I
+ * need to sync", and does not perform the actual
+ * fsync() until we IH_REALLYCLOSE. This provides a
+ * little assurance over IH_SYNC_NEVER when a volume
+ * has gone offline, and a few other situations. */
+#define IH_SYNC_NEVER (3) /* This makes FDH_SYNCs do nothing. Faster, but
+ * obviously less durable. The OS may ensure that
+ * our data hits the disk eventually, depending on
+ * the platform and various OS-specific tuning
+ * parameters. */
+
/* READ THIS.
*
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;
+ int sync_behavior; /* one of the IH_SYNC_* constants */
+} ih_init_params;
/* Number of file descriptors needed for non-cached I/O */
#define FD_HANDLE_SETASIDE 128 /* Match to MAX_FILESERVER_THREAD */
extern void ih_PkgDefaults(void);
extern void ih_Initialize(void);
extern void ih_UseLargeCache(void);
+extern int ih_SetSyncBehavior(const char *behavior);
extern IHandle_t *ih_init(int /*@alt Device@ */ dev, int /*@alt VolId@ */ vid,
Inode ino);
extern IHandle_t *ih_copy(IHandle_t * ihP);
extern int ih_reallyclose(IHandle_t * ihP);
extern int ih_release(IHandle_t * ihP);
extern int ih_condsync(IHandle_t * ihP);
+extern FdHandle_t *ih_attachfd(IHandle_t * ihP, FD_t fd);
/* Macros common to user space and inode API's. */
#define IH_INIT(H, D, V, I) ((H) = ih_init((D), (V), (I)))
#define IH_OPEN(H) ih_open(H)
-#define FDH_CLOSE(H) (fd_close(H), (H)=NULL, 0)
+#define FDH_CLOSE(H) (fd_close(H), (H)=NULL)
-#define FDH_REALLYCLOSE(H) (fd_reallyclose(H), (H)=NULL, 0)
+#define FDH_REALLYCLOSE(H) (fd_reallyclose(H), (H)=NULL)
#define FDH_FDOPEN(H, A) stream_fdopen((H)->fd_fd)
#define STREAM_REALLYCLOSE(H) stream_close(H, 1)
-#define IH_RELEASE(H) (ih_release(H), (H)=NULL, 0)
+#define IH_RELEASE(H) (ih_release(H), (H)=NULL)
#define IH_REALLYCLOSE(H) ih_reallyclose(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 */
+# define AFS_IHANDLE_PIO_ENV 1
+# 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 */
+#elif defined(AFS_NT40_ENV)
+# define AFS_IHANDLE_PIO_ENV 1
+# 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
extern ssize_t ih_pread(FD_t fd, void * buf, size_t count, afs_foff_t offset);
extern ssize_t ih_pwrite(FD_t 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 */
+#endif
#ifdef AFS_NT40_ENV
# define OS_LOCKFILE(FD, O) (!LockFile(FD, (DWORD)((O) & 0xFFFFFFFF), (DWORD)((O) >> 32), 2, 0))
# define OS_DIRSEPC '/'
#endif
+#if defined(AFS_NT40_ENV) || !defined(AFS_NAMEI_ENV)
+# define IH_CREATE_INIT(H, D, P, N, P1, P2, P3, P4) \
+ ih_icreate_init(H, D, P, N, P1, P2, P3, P4)
+#endif
+
#ifdef AFS_NAMEI_ENV
# ifdef AFS_NT40_ENV
# endif /* !O_LARGEFILE */
# define OS_SYNC(FD) fsync(FD)
+# define IH_CREATE_INIT(H, D, P, N, P1, P2, P3, P4) \
+ namei_icreate_init(H, D, P, P1, P2, P3, P4)
/*@=fcnmacros =macrofcndecl@*/
# endif /* AFS_NT40_ENV */
#define OS_SIZE(FD) ih_size(FD)
extern afs_sfsize_t ih_size(FD_t);
-#ifndef AFS_NT40_ENV
-# define FDH_READV(H, I, N) readv((H)->fd_fd, I, N)
-# define FDH_WRITEV(H, I, N) writev((H)->fd_fd, I, N)
-#endif
-
#ifdef HAVE_PIOV
# ifdef O_LARGEFILE
# define FDH_PREADV(H, I, N, O) preadv64((H)->fd_fd, I, N, O)
#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) ((H->fd_ih!=NULL) ? ( H->fd_ih->ih_synced = 1) - 1 : 1)
+#define FDH_SYNC(H) ih_fdsync(H)
#define FDH_TRUNC(H, L) OS_TRUNC((H)->fd_fd, L)
#define FDH_SIZE(H) OS_SIZE((H)->fd_fd)
#define FDH_LOCKFILE(H, O) OS_LOCKFILE((H)->fd_fd, O)
#define FDH_UNLOCKFILE(H, O) OS_UNLOCKFILE((H)->fd_fd, O)
#define FDH_ISUNLINKED(H) OS_ISUNLINKED((H)->fd_fd)
+extern int ih_fdsync(FdHandle_t *fdP);
+
#ifdef AFS_NT40_ENV
# define afs_stat_st __stat64
# define afs_stat _stat64