ReactOS 0.4.15-dev-7924-g5949c20
pnfs_io.c File Reference
#include <stdio.h>
#include <process.h>
#include "nfs41_ops.h"
#include "util.h"
#include "daemon_debug.h"
Include dependency graph for pnfs_io.c:

Go to the source code of this file.

Classes

struct  __pnfs_io_pattern
 
struct  __pnfs_io_thread
 
struct  __pnfs_io_unit
 

Macros

#define IOLVL   2 /* dprintf level for pnfs io logging */
 
#define file_layout_entry(pos)   list_container(pos, pnfs_file_layout, layout.entry)
 

Typedefs

typedef struct __pnfs_io_pattern pnfs_io_pattern
 
typedef struct __pnfs_io_thread pnfs_io_thread
 
typedef struct __pnfs_io_unit pnfs_io_unit
 
typedef uint32_t(WINAPIpnfs_io_thread_fn) (void *)
 

Functions

static enum pnfs_status stripe_next_unit (IN const pnfs_file_layout *layout, IN uint32_t stripeid, IN uint64_t *position, IN uint64_t offset_end, OUT pnfs_io_unit *io)
 
static enum pnfs_status get_sparse_fh (IN pnfs_file_layout *layout, IN nfs41_path_fh *meta_file, IN uint32_t stripeid, OUT nfs41_path_fh **file_out)
 
static enum pnfs_status get_dense_fh (IN pnfs_file_layout *layout, IN uint32_t stripeid, OUT nfs41_path_fh **file_out)
 
static __inline bool_t layout_compatible (IN const pnfs_layout *layout, IN enum pnfs_iomode iomode, IN uint64_t position)
 
static uint32_t thread_count (IN pnfs_layout_state *state, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length)
 
static enum pnfs_status thread_init (IN pnfs_io_pattern *pattern, IN pnfs_io_thread *thread, IN pnfs_file_layout *layout, IN uint32_t stripeid, IN uint64_t offset)
 
static enum pnfs_status pattern_threads_init (IN pnfs_io_pattern *pattern, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length)
 
static enum pnfs_status pattern_init (IN pnfs_io_pattern *pattern, IN nfs41_root *root, IN nfs41_path_fh *meta_file, IN const stateid_arg *stateid, IN pnfs_layout_state *state, IN unsigned char *buffer, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length, IN uint32_t default_lease)
 
static void pattern_free (IN pnfs_io_pattern *pattern)
 
static __inline uint64_t positive_remainder (IN uint64_t dividend, IN uint32_t divisor)
 
static enum pnfs_status thread_next_unit (IN pnfs_io_thread *thread, OUT pnfs_io_unit *io)
 
static enum pnfs_status thread_data_server (IN pnfs_io_thread *thread, OUT pnfs_data_server **server_out)
 
static enum pnfs_status pattern_join (IN HANDLE *threads, IN DWORD count)
 
static enum pnfs_status pattern_fork (IN pnfs_io_pattern *pattern, IN pnfs_io_thread_fn thread_fn)
 
static uint64_t pattern_bytes_transferred (IN pnfs_io_pattern *pattern, OUT OPTIONAL enum stable_how4 *stable)
 
static enum pnfs_status map_ds_error (IN enum nfsstat4 nfsstat, IN pnfs_layout_state *state, IN const pnfs_file_layout *layout)
 
static uint32_t WINAPI file_layout_read_thread (void *args)
 
static uint32_t WINAPI file_layout_write_thread (void *args)
 
enum pnfs_status pnfs_read (IN nfs41_root *root, IN nfs41_open_state *state, IN stateid_arg *stateid, IN pnfs_layout_state *layout, IN uint64_t offset, IN uint64_t length, OUT unsigned char *buffer_out, OUT ULONG *len_out)
 
static enum pnfs_status mds_commit (IN nfs41_open_state *state, IN uint64_t offset, IN uint32_t length, IN const pnfs_io_pattern *pattern, OUT nfs41_file_info *info)
 
static enum pnfs_status layout_commit (IN nfs41_open_state *state, IN pnfs_layout_state *layout, IN uint64_t offset, IN uint64_t length, OUT nfs41_file_info *info)
 
enum pnfs_status pnfs_write (IN nfs41_root *root, IN nfs41_open_state *state, IN stateid_arg *stateid, IN pnfs_layout_state *layout, IN uint64_t offset, IN uint64_t length, IN unsigned char *buffer, OUT ULONG *len_out, OUT nfs41_file_info *info)
 

Macro Definition Documentation

◆ file_layout_entry

#define file_layout_entry (   pos)    list_container(pos, pnfs_file_layout, layout.entry)

Definition at line 32 of file pnfs_io.c.

◆ IOLVL

#define IOLVL   2 /* dprintf level for pnfs io logging */

Definition at line 30 of file pnfs_io.c.

Typedef Documentation

◆ pnfs_io_pattern

◆ pnfs_io_thread

◆ pnfs_io_thread_fn

typedef uint32_t(WINAPI * pnfs_io_thread_fn) (void *)

Definition at line 65 of file pnfs_io.c.

◆ pnfs_io_unit

Function Documentation

◆ file_layout_read_thread()

static uint32_t WINAPI file_layout_read_thread ( void args)
static

Definition at line 487 of file pnfs_io.c.

488{
490 stateid_arg stateid;
492 pnfs_io_pattern *pattern = thread->pattern;
495 uint32_t maxreadsize, bytes_read, total_read;
496 enum pnfs_status status;
497 enum nfsstat4 nfsstat;
498 bool_t eof;
499
500 dprintf(IOLVL, "--> file_layout_read_thread(%u)\n", thread->id);
501
502 /* get the data server for this thread */
504 if (status) {
505 eprintf("thread_data_server() failed with %s\n",
507 goto out;
508 }
509 /* find or establish a client for this data server */
511 server, pattern->default_lease, &client);
512 if (status) {
513 eprintf("pnfs_data_server_client() failed with %s\n",
515 goto out;
516 }
517
518 memcpy(&stateid, pattern->stateid, sizeof(stateid));
519 stateid.stateid.seqid = 0;
520
521 total_read = 0;
522 while (thread_next_unit(thread, &io) == PNFS_PENDING) {
523 maxreadsize = max_read_size(client->session, &thread->file->fh);
524 if (io.length > maxreadsize)
525 io.length = maxreadsize;
526
527 nfsstat = nfs41_read(client->session, thread->file, &stateid,
528 io.offset, (uint32_t)io.length, io.buffer, &bytes_read, &eof);
529 if (nfsstat) {
530 eprintf("nfs41_read() failed with %s\n",
531 nfs_error_string(nfsstat));
532 status = map_ds_error(nfsstat, pattern->state, thread->layout);
533 break;
534 }
535
536 total_read += bytes_read;
537 thread->offset += bytes_read;
538
539 if (eof) {
540 dprintf(IOLVL, "read thread %u reached eof: offset %llu\n",
541 thread->id, thread->offset);
542 status = total_read ? PNFS_SUCCESS : PNFS_READ_EOF;
543 break;
544 }
545 }
546out:
547 dprintf(IOLVL, "<-- file_layout_read_thread(%u) returning %s\n",
549 return status;
550}
uint32_t max_read_size(IN const nfs41_session *session, IN const nfs41_fh *fh)
Definition: util.c:84
static HANDLE thread
Definition: service.c:33
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
const char * pnfs_error_string(enum pnfs_status status)
Definition: pnfs_debug.c:28
int32_t bool_t
Definition: types.h:101
UINT32 uint32_t
Definition: types.h:75
GLubyte * pattern
Definition: glext.h:7787
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK io
Definition: file.c:100
nfsstat4
Definition: nfs41_const.h:86
int nfs41_read(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN uint64_t offset, IN uint32_t count, OUT unsigned char *data_out, OUT uint32_t *data_len_out, OUT bool_t *eof_out)
Definition: nfs41_ops.c:774
pnfs_status
Definition: pnfs.h:58
@ PNFS_PENDING
Definition: pnfs.h:60
@ PNFS_READ_EOF
Definition: pnfs.h:61
@ PNFS_SUCCESS
Definition: pnfs.h:59
enum pnfs_status pnfs_data_server_client(IN struct __nfs41_root *root, IN pnfs_data_server *server, IN uint32_t default_lease, OUT struct __nfs41_client **client_out)
static enum pnfs_status thread_next_unit(IN pnfs_io_thread *thread, OUT pnfs_io_unit *io)
Definition: pnfs_io.c:330
static enum pnfs_status thread_data_server(IN pnfs_io_thread *thread, OUT pnfs_data_server **server_out)
Definition: pnfs_io.c:355
#define IOLVL
Definition: pnfs_io.c:30
static enum pnfs_status map_ds_error(IN enum nfsstat4 nfsstat, IN pnfs_layout_state *state, IN const pnfs_file_layout *layout)
Definition: pnfs_io.c:459
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
_Check_return_ _CRTIMP int __cdecl __cdecl eof(_In_ int _FileHandle)
static FILE * client
Definition: client.c:41
uint32_t seqid
Definition: nfs41_types.h:144
stateid4 stateid
Definition: nfs41_ops.h:284
Definition: match.c:390
Definition: ps.c:97
static rfbScreenInfoPtr server
Definition: vnc.c:74

Referenced by pnfs_read().

◆ file_layout_write_thread()

static uint32_t WINAPI file_layout_write_thread ( void args)
static

Definition at line 552 of file pnfs_io.c.

553{
555 stateid_arg stateid;
557 pnfs_io_pattern *pattern = thread->pattern;
560 const uint64_t offset_start = thread->offset;
561 uint64_t commit_min, commit_max;
562 uint32_t maxwritesize, bytes_written, total_written;
563 enum pnfs_status status;
564 enum nfsstat4 nfsstat;
565
566 dprintf(IOLVL, "--> file_layout_write_thread(%u)\n", thread->id);
567
568 /* get the data server for this thread */
570 if (status) {
571 eprintf("thread_data_server() failed with %s\n",
573 goto out;
574 }
575 /* find or establish a client for this data server */
577 server, pattern->default_lease, &client);
578 if (status) {
579 eprintf("pnfs_data_server_client() failed with %s\n",
581 goto out;
582 }
583
584 memcpy(&stateid, pattern->stateid, sizeof(stateid));
585 stateid.stateid.seqid = 0;
586
587 maxwritesize = max_write_size(client->session, &thread->file->fh);
588
589retry_write:
590 thread->offset = offset_start;
591 thread->stable = FILE_SYNC4;
592 commit_min = NFS4_UINT64_MAX;
593 commit_max = 0;
594 total_written = 0;
595
596 while (thread_next_unit(thread, &io) == PNFS_PENDING) {
597 if (io.length > maxwritesize)
598 io.length = maxwritesize;
599
600 nfsstat = nfs41_write(client->session, thread->file, &stateid,
601 io.buffer, (uint32_t)io.length, io.offset, UNSTABLE4,
602 &bytes_written, &thread->verf, NULL);
603 if (nfsstat) {
604 eprintf("nfs41_write() failed with %s\n",
605 nfs_error_string(nfsstat));
606 status = map_ds_error(nfsstat, pattern->state, thread->layout);
607 break;
608 }
609 if (!verify_write(&thread->verf, &thread->stable))
610 goto retry_write;
611
612 total_written += bytes_written;
613 thread->offset += bytes_written;
614
615 /* track the range for commit */
616 if (commit_min > io.offset)
617 commit_min = io.offset;
618 if (commit_max < io.offset + io.length)
619 commit_max = io.offset + io.length;
620 }
621
622 /* nothing to commit */
623 if (commit_max <= commit_min)
624 goto out;
625 /* layout changed; redo all io against metadata server */
627 goto out;
628 /* the data is already in stable storage */
629 if (thread->stable != UNSTABLE4)
630 goto out;
631 /* the metadata server expects us to commit there instead */
632 if (should_commit_to_mds(thread->layout))
633 goto out;
634
635 dprintf(1, "sending COMMIT to data server for offset=%lld len=%lld\n",
636 commit_min, commit_max - commit_min);
637 nfsstat = nfs41_commit(client->session, thread->file,
638 commit_min, (uint32_t)(commit_max - commit_min), 0, &thread->verf, NULL);
639
640 if (nfsstat)
641 status = map_ds_error(nfsstat, pattern->state, thread->layout);
642 else if (!verify_commit(&thread->verf)) {
643 /* resend the writes unless the layout was recalled */
645 goto retry_write;
647 } else {
648 /* on successful commit, leave pnfs_status unchanged; if the
649 * layout was recalled, we still want to return the error */
650 thread->stable = DATA_SYNC4;
651 }
652out:
653 dprintf(IOLVL, "<-- file_layout_write_thread(%u) returning %s\n",
655 return status;
656}
bool_t verify_write(IN nfs41_write_verf *verf, IN OUT enum stable_how4 *stable)
Definition: util.c:100
bool_t verify_commit(IN nfs41_write_verf *verf)
Definition: util.c:126
uint32_t max_write_size(IN const nfs41_session *session, IN const nfs41_fh *fh)
Definition: util.c:92
#define NULL
Definition: types.h:112
UINT64 uint64_t
Definition: types.h:77
int nfs41_write(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN unsigned char *data, IN uint32_t data_len, IN uint64_t offset, IN enum stable_how4 stable, OUT uint32_t *bytes_written, OUT nfs41_write_verf *verf, OUT nfs41_file_info *cinfo)
Definition: nfs41_ops.c:685
int nfs41_commit(IN nfs41_session *session, IN nfs41_path_fh *file, IN uint64_t offset, IN uint32_t count, IN bool_t do_getattr, OUT nfs41_write_verf *verf, OUT nfs41_file_info *cinfo)
Definition: nfs41_ops.c:833
@ FILE_SYNC4
Definition: nfs41_ops.h:838
@ DATA_SYNC4
Definition: nfs41_ops.h:837
@ UNSTABLE4
Definition: nfs41_ops.h:836
static const uint64_t NFS4_UINT64_MAX
Definition: nfs41_types.h:32
@ PNFSERR_IO
Definition: pnfs.h:64
@ PNFSERR_LAYOUT_CHANGED
Definition: pnfs.h:71
@ PNFSERR_LAYOUT_RECALLED
Definition: pnfs.h:70
__inline int should_commit_to_mds(IN const pnfs_file_layout *layout)
Definition: pnfs.h:306

Referenced by pnfs_write().

◆ get_dense_fh()

static enum pnfs_status get_dense_fh ( IN pnfs_file_layout layout,
IN uint32_t  stripeid,
OUT nfs41_path_fh **  file_out 
)
static

Definition at line 106 of file pnfs_io.c.

110{
111 const uint32_t filehandle_count = layout->filehandles.count;
112 const uint32_t stripe_count = layout->device->stripes.count;
114
115 if (filehandle_count == stripe_count) {
116 *file_out = &layout->filehandles.arr[stripeid];
117 } else {
118 eprintf("invalid dense layout! has %u file handles "
119 "and %u stripes\n", filehandle_count, stripe_count);
121 }
122 return status;
123}
static DWORD layout
Definition: bitmap.c:46
@ PNFSERR_INVALID_FH_LIST
Definition: pnfs.h:67

Referenced by thread_init().

◆ get_sparse_fh()

static enum pnfs_status get_sparse_fh ( IN pnfs_file_layout layout,
IN nfs41_path_fh meta_file,
IN uint32_t  stripeid,
OUT nfs41_path_fh **  file_out 
)
static

Definition at line 78 of file pnfs_io.c.

83{
84 const uint32_t filehandle_count = layout->filehandles.count;
85 const uint32_t server_count = layout->device->servers.count;
87
88 if (filehandle_count == server_count) {
89 const uint32_t serverid = data_server_index(layout->device, stripeid);
90 *file_out = &layout->filehandles.arr[serverid];
91 } else if (filehandle_count == 1) {
92 *file_out = &layout->filehandles.arr[0];
93 } else if (filehandle_count == 0) {
94 *file_out = meta_file;
95 } else {
96 eprintf("invalid sparse layout! has %u file handles "
97 "and %u servers\n", filehandle_count, server_count);
99 }
100 return status;
101}
__inline uint32_t data_server_index(IN const pnfs_file_device *device, IN uint32_t stripeid)
Definition: pnfs.h:358

Referenced by thread_init().

◆ layout_commit()

static enum pnfs_status layout_commit ( IN nfs41_open_state state,
IN pnfs_layout_state layout,
IN uint64_t  offset,
IN uint64_t  length,
OUT nfs41_file_info info 
)
static

Definition at line 762 of file pnfs_io.c.

768{
769 stateid4 layout_stateid;
770 uint64_t last_offset = offset + length - 1;
771 uint64_t *new_last_offset = NULL;
772 enum nfsstat4 nfsstat;
774
776 /* if this is past the current eof, update the open state's
777 * last offset, and pass a pointer to LAYOUTCOMMIT */
778 if (state->pnfs_last_offset < last_offset ||
779 (state->pnfs_last_offset == 0 && last_offset == 0)) {
780 state->pnfs_last_offset = last_offset;
781 new_last_offset = &last_offset;
782 }
784
786 memcpy(&layout_stateid, &layout->stateid, sizeof(layout_stateid));
788
789 dprintf(1, "LAYOUTCOMMIT for offset=%lld len=%lld new_last_offset=%u\n",
790 offset, length, new_last_offset ? 1 : 0);
791 nfsstat = pnfs_rpc_layoutcommit(state->session, &state->file,
792 &layout_stateid, offset, length, new_last_offset, NULL, info);
793 if (nfsstat) {
794 dprintf(IOLVL, "pnfs_rpc_layoutcommit() failed with %s\n",
795 nfs_error_string(nfsstat));
797 }
798 return status;
799}
static int state
Definition: maze.c:121
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLintptr offset
Definition: glext.h:5920
enum nfsstat4 pnfs_rpc_layoutcommit(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid4 *stateid, IN uint64_t offset, IN uint64_t length, IN OPTIONAL uint64_t *new_last_offset, IN OPTIONAL nfstime4 *new_time_modify, OUT nfs41_file_info *info)
Definition: nfs41_ops.c:1999

Referenced by pnfs_write().

◆ layout_compatible()

static __inline bool_t layout_compatible ( IN const pnfs_layout layout,
IN enum pnfs_iomode  iomode,
IN uint64_t  position 
)
static

Definition at line 125 of file pnfs_io.c.

129{
130 return layout->iomode >= iomode
131 && layout->offset <= position
132 && position < layout->offset + layout->length;
133}

Referenced by pattern_threads_init(), and thread_count().

◆ map_ds_error()

static enum pnfs_status map_ds_error ( IN enum nfsstat4  nfsstat,
IN pnfs_layout_state state,
IN const pnfs_file_layout layout 
)
static

Definition at line 459 of file pnfs_io.c.

463{
464 switch (nfsstat) {
465 case NO_ERROR:
466 return PNFS_SUCCESS;
467
468 /* 13.11 Layout Revocation and Fencing
469 * http://tools.ietf.org/html/rfc5661#section-13.11
470 * if we've been fenced, we'll either get ERR_STALE when we PUTFH
471 * something in layout.filehandles, or ERR_PNFS_NO_LAYOUT when
472 * attempting to READ or WRITE */
473 case NFS4ERR_STALE:
475 dprintf(IOLVL, "data server fencing detected!\n");
476
478
479 /* return CHANGED to prevent any further use of the layout */
481
482 default:
483 return PNFSERR_IO;
484 }
485}
#define NO_ERROR
Definition: dderror.h:5
@ NFS4ERR_PNFS_NO_LAYOUT
Definition: nfs41_const.h:189
@ NFS4ERR_STALE
Definition: nfs41_const.h:106
void pnfs_layout_recall_fenced(IN pnfs_layout_state *state, IN const pnfs_layout *layout)
Definition: pnfs_layout.c:1233

Referenced by file_layout_read_thread(), and file_layout_write_thread().

◆ mds_commit()

static enum pnfs_status mds_commit ( IN nfs41_open_state state,
IN uint64_t  offset,
IN uint32_t  length,
IN const pnfs_io_pattern pattern,
OUT nfs41_file_info info 
)
static

Definition at line 714 of file pnfs_io.c.

720{
721 nfs41_write_verf verf;
722 enum nfsstat4 nfsstat;
724 uint32_t i;
725
726 nfsstat = nfs41_commit(state->session,
727 &state->file, offset, length, 1, &verf, info);
728 if (nfsstat) {
729 eprintf("nfs41_commit() to mds failed with %s\n",
730 nfs_error_string(nfsstat));
732 goto out;
733 }
734
735 /* 13.7. COMMIT through Metadata Server:
736 * If nfl_util & NFL4_UFLG_COMMIT_THRU_MDS is TRUE, then in order to
737 * maintain the current NFSv4.1 commit and recovery model, the data
738 * servers MUST return a common writeverf verifier in all WRITE
739 * responses for a given file layout, and the metadata server's
740 * COMMIT implementation must return the same writeverf. */
741 for (i = 0; i < pattern->count; i++) {
742 const pnfs_io_thread *thread = &pattern->threads[i];
743 if (thread->stable != UNSTABLE4) /* already committed */
744 continue;
745
746 if (!should_commit_to_mds(thread->layout)) {
747 /* commit to mds is not allowed on this layout */
748 eprintf("mds commit: failed to commit to data server\n");
750 break;
751 }
752 if (memcmp(verf.verf, thread->verf.verf, NFS4_VERIFIER_SIZE) != 0) {
753 eprintf("mds commit verifier doesn't match ds write verifiers\n");
755 break;
756 }
757 }
758out:
759 return status;
760}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define NFS4_VERIFIER_SIZE
Definition: nfs41_const.h:30
unsigned char verf[NFS4_VERIFIER_SIZE]
Definition: nfs41_types.h:76

Referenced by pnfs_write().

◆ pattern_bytes_transferred()

static uint64_t pattern_bytes_transferred ( IN pnfs_io_pattern pattern,
OUT OPTIONAL enum stable_how4 stable 
)
static

Definition at line 442 of file pnfs_io.c.

445{
446 uint64_t lowest_offset = pattern->offset_end;
447 uint32_t i;
448
449 if (stable) *stable = FILE_SYNC4;
450
451 for (i = 0; i < pattern->count; i++) {
452 lowest_offset = min(lowest_offset, pattern->threads[i].offset);
453 if (stable) *stable = min(*stable, pattern->threads[i].stable);
454 }
455 return lowest_offset - pattern->offset_start;
456}
#define min(a, b)
Definition: monoChain.cc:55

Referenced by pnfs_read(), and pnfs_write().

◆ pattern_fork()

static enum pnfs_status pattern_fork ( IN pnfs_io_pattern pattern,
IN pnfs_io_thread_fn  thread_fn 
)
static

Definition at line 387 of file pnfs_io.c.

390{
392 uint32_t i;
394
395 if (pattern->count == 0)
396 goto out;
397
398 if (pattern->count == 1) {
399 /* no need to fork if there's only 1 thread */
400 status = (enum pnfs_status)thread_fn(pattern->threads);
401 goto out;
402 }
403
404 /* create a thread for each unit that has actual io */
405 threads = calloc(pattern->count, sizeof(HANDLE));
406 if (threads == NULL) {
408 goto out;
409 }
410
411 for (i = 0; i < pattern->count; i++) {
413 thread_fn, &pattern->threads[i], 0, NULL);
414 if (threads[i] == NULL) {
415 eprintf("_beginthreadex() failed with %d\n", GetLastError());
416 pattern->count = i; /* join any threads already started */
417 break;
418 }
419 }
420
421 /* wait on all threads to finish */
423 if (status) {
424 eprintf("pattern_join() failed with %s\n", pnfs_error_string(status));
425 goto out;
426 }
427
428 for (i = 0; i < pattern->count; i++) {
429 /* keep track of the most severe error returned by a thread */
430 DWORD exitcode;
431 if (GetExitCodeThread(threads[i], &exitcode))
432 status = max(status, (enum pnfs_status)exitcode);
433
435 }
436
437 free(threads);
438out:
439 return status;
440}
#define free
Definition: debug_ros.c:5
#define CloseHandle
Definition: compat.h:739
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
unsigned long DWORD
Definition: ntddk_ex.h:95
static HANDLE ULONG_PTR DWORD threads
Definition: process.c:81
@ PNFSERR_RESOURCES
Definition: pnfs.h:69
static enum pnfs_status pattern_join(IN HANDLE *threads, IN DWORD count)
Definition: pnfs_io.c:369
#define calloc
Definition: rosglue.h:14
_CRTIMP uintptr_t __cdecl _beginthreadex(_In_opt_ void *_Security, _In_ unsigned _StackSize, _In_ unsigned(__stdcall *_StartAddress)(void *), _In_opt_ void *_ArgList, _In_ unsigned _InitFlag, _Out_opt_ unsigned *_ThrdAddr)
#define max(a, b)
Definition: svc.c:63
PVOID HANDLE
Definition: typedefs.h:73
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

Referenced by pnfs_read(), and pnfs_write().

◆ pattern_free()

static void pattern_free ( IN pnfs_io_pattern pattern)
static

Definition at line 274 of file pnfs_io.c.

276{
277 /* inform the layout that our io is finished */
279 free(pattern->threads);
280}
void pnfs_layout_io_finished(IN pnfs_layout_state *state)
Definition: pnfs_layout.c:1267

Referenced by pnfs_read(), and pnfs_write().

◆ pattern_init()

static enum pnfs_status pattern_init ( IN pnfs_io_pattern pattern,
IN nfs41_root root,
IN nfs41_path_fh meta_file,
IN const stateid_arg stateid,
IN pnfs_layout_state state,
IN unsigned char buffer,
IN enum pnfs_iomode  iomode,
IN uint64_t  offset,
IN uint64_t  length,
IN uint32_t  default_lease 
)
static

Definition at line 226 of file pnfs_io.c.

237{
238 enum pnfs_status status;
239
240 /* calculate an upper bound on the number of threads to allocate */
241 pattern->count = thread_count(state, iomode, offset, length);
242 pattern->threads = calloc(pattern->count, sizeof(pnfs_io_thread));
243 if (pattern->threads == NULL) {
245 goto out;
246 }
247
248 /* information shared between threads */
249 pattern->root = root;
250 pattern->meta_file = meta_file;
251 pattern->stateid = stateid;
252 pattern->state = state;
253 pattern->buffer = buffer;
254 pattern->offset_start = offset;
255 pattern->offset_end = offset + length;
256 pattern->default_lease = default_lease;
257
258 /* initialize a thread for every stripe necessary to cover the range */
260 if (status)
261 goto out_err_free;
262
263 /* take a reference on the layout so we don't return it during io */
265out:
266 return status;
267
268out_err_free:
269 free(pattern->threads);
270 pattern->threads = NULL;
271 goto out;
272}
struct _root root
GLuint buffer
Definition: glext.h:5915
void pnfs_layout_io_start(IN pnfs_layout_state *state)
Definition: pnfs_layout.c:1257
static enum pnfs_status pattern_threads_init(IN pnfs_io_pattern *pattern, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length)
Definition: pnfs_io.c:176
static uint32_t thread_count(IN pnfs_layout_state *state, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length)
Definition: pnfs_io.c:137

Referenced by pnfs_read(), and pnfs_write().

◆ pattern_join()

static enum pnfs_status pattern_join ( IN HANDLE threads,
IN DWORD  count 
)
static

Definition at line 369 of file pnfs_io.c.

372{
374 /* WaitForMultipleObjects() supports a maximum of 64 objects */
375 while (count) {
378 if (status != WAIT_OBJECT_0)
379 return PNFSERR_RESOURCES;
380
381 count -= n;
382 threads += n;
383 }
384 return PNFS_SUCCESS;
385}
#define TRUE
Definition: types.h:120
#define INFINITE
Definition: serial.h:102
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble n
Definition: glext.h:7729
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
#define MAXIMUM_WAIT_OBJECTS
Definition: winbase.h:404
#define WAIT_OBJECT_0
Definition: winbase.h:406

Referenced by pattern_fork().

◆ pattern_threads_init()

static enum pnfs_status pattern_threads_init ( IN pnfs_io_pattern pattern,
IN enum pnfs_iomode  iomode,
IN uint64_t  offset,
IN uint64_t  length 
)
static

Definition at line 176 of file pnfs_io.c.

181{
183 uint64_t position = offset;
184 struct list_entry *entry;
185 uint32_t s, t = 0;
187
188 list_for_each(entry, &pattern->state->layouts) {
190
191 if (!layout_compatible(&layout->layout, iomode, position))
192 continue;
193
194 for (s = 0; s < layout->device->stripes.count; s++) {
195 uint64_t off = position;
196
197 /* does the range contain this stripe? */
199 if (status != PNFS_PENDING)
200 continue;
201
202 if (t >= pattern->count) { /* miscounted threads needed? */
204 goto out;
205 }
206
207 status = thread_init(pattern, &pattern->threads[t++], layout, s, off);
208 if (status)
209 goto out;
210 }
211 position = layout->layout.offset + layout->layout.length;
212 }
213
214 if (position < offset + length) {
215 /* unable to satisfy the entire range */
217 goto out;
218 }
219
220 /* update the pattern with the actual number of threads used */
221 pattern->count = t;
222out:
223 return status;
224}
#define list_for_each(entry, head)
Definition: list.h:36
GLdouble s
Definition: gl.h:2039
GLdouble GLdouble t
Definition: gl.h:2047
uint32_t entry
Definition: isohybrid.c:63
@ PNFSERR_NO_LAYOUT
Definition: pnfs.h:66
static enum pnfs_status thread_init(IN pnfs_io_pattern *pattern, IN pnfs_io_thread *thread, IN pnfs_file_layout *layout, IN uint32_t stripeid, IN uint64_t offset)
Definition: pnfs_io.c:159
static __inline bool_t layout_compatible(IN const pnfs_layout *layout, IN enum pnfs_iomode iomode, IN uint64_t position)
Definition: pnfs_io.c:125
#define file_layout_entry(pos)
Definition: pnfs_io.c:32
static enum pnfs_status stripe_next_unit(IN const pnfs_file_layout *layout, IN uint32_t stripeid, IN uint64_t *position, IN uint64_t offset_end, OUT pnfs_io_unit *io)
Definition: pnfs_io.c:291
Definition: list.h:27

Referenced by pattern_init().

◆ pnfs_read()

enum pnfs_status pnfs_read ( IN nfs41_root root,
IN nfs41_open_state state,
IN stateid_arg stateid,
IN pnfs_layout_state layout,
IN uint64_t  offset,
IN uint64_t  length,
OUT unsigned char buffer_out,
OUT ULONG len_out 
)

Definition at line 659 of file pnfs_io.c.

668{
670 enum pnfs_status status;
671
672 dprintf(IOLVL, "--> pnfs_read(%llu, %llu)\n", offset, length);
673
674 *len_out = 0;
675
677
678 /* get layouts/devices for the entire range; PNFS_PENDING means we
679 * dropped the lock to send an rpc, so repeat until it succeeds */
680 do {
682 &state->file, stateid, PNFS_IOMODE_READ, offset, length);
683 } while (status == PNFS_PENDING);
684
685 if (status == PNFS_SUCCESS) {
686 /* interpret the layout and set up threads for io */
687 status = pattern_init(&pattern, root, &state->file, stateid,
688 layout, buffer_out, PNFS_IOMODE_READ, offset, length,
689 state->session->lease_time);
690 if (status)
691 eprintf("pattern_init() failed with %s\n",
693 }
694
696
697 if (status)
698 goto out;
699
702 goto out_free_pattern;
703
705
706out_free_pattern:
708out:
709 dprintf(IOLVL, "<-- pnfs_read() returning %s\n",
711 return status;
712}
@ PNFS_IOMODE_READ
Definition: pnfs.h:81
enum pnfs_status pnfs_layout_state_prepare(IN pnfs_layout_state *state, IN struct __nfs41_session *session, IN nfs41_path_fh *meta_file, IN struct __stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length)
static enum pnfs_status pattern_init(IN pnfs_io_pattern *pattern, IN nfs41_root *root, IN nfs41_path_fh *meta_file, IN const stateid_arg *stateid, IN pnfs_layout_state *state, IN unsigned char *buffer, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length, IN uint32_t default_lease)
Definition: pnfs_io.c:226
static uint64_t pattern_bytes_transferred(IN pnfs_io_pattern *pattern, OUT OPTIONAL enum stable_how4 *stable)
Definition: pnfs_io.c:442
static void pattern_free(IN pnfs_io_pattern *pattern)
Definition: pnfs_io.c:274
static enum pnfs_status pattern_fork(IN pnfs_io_pattern *pattern, IN pnfs_io_thread_fn thread_fn)
Definition: pnfs_io.c:387
static uint32_t WINAPI file_layout_read_thread(void *args)
Definition: pnfs_io.c:487
uint32_t ULONG
Definition: typedefs.h:59

◆ pnfs_write()

enum pnfs_status pnfs_write ( IN nfs41_root root,
IN nfs41_open_state state,
IN stateid_arg stateid,
IN pnfs_layout_state layout,
IN uint64_t  offset,
IN uint64_t  length,
IN unsigned char buffer,
OUT ULONG len_out,
OUT nfs41_file_info info 
)

Definition at line 801 of file pnfs_io.c.

811{
813 enum stable_how4 stable;
814 enum pnfs_status status;
815
816 dprintf(IOLVL, "--> pnfs_write(%llu, %llu)\n", offset, length);
817
818 *len_out = 0;
819
821
822 /* get layouts/devices for the entire range; PNFS_PENDING means we
823 * dropped the lock to send an rpc, so repeat until it succeeds */
824 do {
826 &state->file, stateid, PNFS_IOMODE_RW, offset, length);
827 } while (status == PNFS_PENDING);
828
829 if (status == PNFS_SUCCESS) {
830 /* interpret the layout and set up threads for io */
831 status = pattern_init(&pattern, root, &state->file, stateid,
833 state->session->lease_time);
834 if (status)
835 eprintf("pattern_init() failed with %s\n",
837 }
838
840
841 if (status)
842 goto out;
843
845 /* on layout recall, we still attempt to commit what we wrote */
847 goto out_free_pattern;
848
849 *len_out = (ULONG)pattern_bytes_transferred(&pattern, &stable);
850 if (*len_out == 0)
851 goto out_free_pattern;
852
853 if (stable == UNSTABLE4) {
854 /* send COMMIT to the mds and verify against all ds writes */
855 status = mds_commit(state, offset, *len_out, &pattern, info);
856 } else if (stable == DATA_SYNC4) {
857 /* send LAYOUTCOMMIT to sync the metadata */
858 status = layout_commit(state, layout, offset, *len_out, info);
859 } else {
860 /* send a GETATTR to update the cached size */
861 bitmap4 attr_request;
862 nfs41_superblock_getattr_mask(state->file.fh.superblock, &attr_request);
863 nfs41_getattr(state->session, &state->file, &attr_request, info);
864 }
865out_free_pattern:
867out:
868 dprintf(IOLVL, "<-- pnfs_write() returning %s\n",
870 return status;
871}
static __inline void nfs41_superblock_getattr_mask(IN const nfs41_superblock *superblock, OUT bitmap4 *attrs)
Definition: nfs41.h:448
int nfs41_getattr(IN nfs41_session *session, IN OPTIONAL nfs41_path_fh *file, IN bitmap4 *attr_request, OUT nfs41_file_info *info)
Definition: nfs41_ops.c:1063
stable_how4
Definition: nfs41_ops.h:835
@ PNFS_IOMODE_RW
Definition: pnfs.h:82
static enum pnfs_status layout_commit(IN nfs41_open_state *state, IN pnfs_layout_state *layout, IN uint64_t offset, IN uint64_t length, OUT nfs41_file_info *info)
Definition: pnfs_io.c:762
static enum pnfs_status mds_commit(IN nfs41_open_state *state, IN uint64_t offset, IN uint32_t length, IN const pnfs_io_pattern *pattern, OUT nfs41_file_info *info)
Definition: pnfs_io.c:714
static uint32_t WINAPI file_layout_write_thread(void *args)
Definition: pnfs_io.c:552

◆ positive_remainder()

static __inline uint64_t positive_remainder ( IN uint64_t  dividend,
IN uint32_t  divisor 
)
static

Definition at line 282 of file pnfs_io.c.

285{
286 const uint64_t remainder = dividend % divisor;
288}
GLuint divisor
Definition: glext.h:6313
double __cdecl remainder(double, double)
Definition: remainder.c:75

Referenced by stripe_next_unit().

◆ stripe_next_unit()

static enum pnfs_status stripe_next_unit ( IN const pnfs_file_layout layout,
IN uint32_t  stripeid,
IN uint64_t position,
IN uint64_t  offset_end,
OUT pnfs_io_unit io 
)
static

Definition at line 291 of file pnfs_io.c.

297{
298 const uint32_t unit_size = layout_unit_size(layout);
299 const uint32_t stripe_count = layout->device->stripes.count;
300 uint64_t sui = stripe_unit_number(layout, *position, unit_size);
301
302 /* advance to the desired stripeid */
303 sui += abs(stripeid - stripe_index(layout, sui, stripe_count));
304
305 io->offset = stripe_unit_offset(layout, sui, unit_size);
306 if (io->offset < *position) /* don't start before position */
307 io->offset = *position;
308 else
309 *position = io->offset;
310
311 io->length = stripe_unit_offset(layout, sui + 1, unit_size);
312 if (io->length > offset_end) /* don't end past offset_end */
313 io->length = offset_end;
314
315 if (io->offset >= io->length) /* nothing to do, return success */
316 return PNFS_SUCCESS;
317
318 io->length -= io->offset;
319
320 if (is_dense(layout)) {
321 const uint64_t rel_offset = io->offset - layout->pattern_offset;
322 const uint64_t remainder = positive_remainder(rel_offset, unit_size);
323 const uint32_t stride = unit_size * stripe_count;
324
325 io->offset = (rel_offset / stride) * unit_size + remainder;
326 }
327 return PNFS_PENDING;
328}
#define abs(i)
Definition: fconv.c:206
GLsizei stride
Definition: glext.h:5848
__inline uint32_t stripe_index(IN const pnfs_file_layout *layout, IN uint64_t sui, IN uint32_t stripe_count)
Definition: pnfs.h:347
__inline uint32_t layout_unit_size(IN const pnfs_file_layout *layout)
Definition: pnfs.h:315
__inline int is_dense(IN const pnfs_file_layout *layout)
Definition: pnfs.h:297
__inline uint64_t stripe_unit_offset(IN const pnfs_file_layout *layout, IN uint64_t sui, IN uint32_t unit_size)
Definition: pnfs.h:336
__inline uint64_t stripe_unit_number(IN const pnfs_file_layout *layout, IN uint64_t offset, IN uint32_t unit_size)
Definition: pnfs.h:324
static __inline uint64_t positive_remainder(IN uint64_t dividend, IN uint32_t divisor)
Definition: pnfs_io.c:282

Referenced by pattern_threads_init(), and thread_next_unit().

◆ thread_count()

static uint32_t thread_count ( IN pnfs_layout_state state,
IN enum pnfs_iomode  iomode,
IN uint64_t  offset,
IN uint64_t  length 
)
static

Definition at line 137 of file pnfs_io.c.

142{
143 uint64_t position = offset;
144 struct list_entry *entry;
145 uint32_t count = 0;
146
147 list_for_each(entry, &state->layouts) {
149
150 if (!layout_compatible(&layout->layout, iomode, position))
151 continue;
152
153 position = layout->layout.offset + layout->layout.length;
154 count += layout->device->stripes.count;
155 }
156 return count;
157}

Referenced by pattern_init(), and test_GetPerformanceInfo().

◆ thread_data_server()

static enum pnfs_status thread_data_server ( IN pnfs_io_thread thread,
OUT pnfs_data_server **  server_out 
)
static

Definition at line 355 of file pnfs_io.c.

358{
359 pnfs_file_device *device = thread->layout->device;
360 const uint32_t serverid = data_server_index(device, thread->id);
361
362 if (serverid >= device->servers.count)
364
365 *server_out = &device->servers.arr[serverid];
366 return PNFS_SUCCESS;
367}
@ PNFSERR_INVALID_DS_INDEX
Definition: pnfs.h:68
Definition: devices.h:37

Referenced by file_layout_read_thread(), and file_layout_write_thread().

◆ thread_init()

static enum pnfs_status thread_init ( IN pnfs_io_pattern pattern,
IN pnfs_io_thread thread,
IN pnfs_file_layout layout,
IN uint32_t  stripeid,
IN uint64_t  offset 
)
static

Definition at line 159 of file pnfs_io.c.

165{
166 thread->pattern = pattern;
167 thread->layout = layout;
168 thread->stable = FILE_SYNC4;
169 thread->offset = offset;
170 thread->id = stripeid;
171
172 return is_dense(layout) ? get_dense_fh(layout, stripeid, &thread->file)
173 : get_sparse_fh(layout, pattern->meta_file, stripeid, &thread->file);
174}
static enum pnfs_status get_sparse_fh(IN pnfs_file_layout *layout, IN nfs41_path_fh *meta_file, IN uint32_t stripeid, OUT nfs41_path_fh **file_out)
Definition: pnfs_io.c:78
static enum pnfs_status get_dense_fh(IN pnfs_file_layout *layout, IN uint32_t stripeid, OUT nfs41_path_fh **file_out)
Definition: pnfs_io.c:106
Definition: fci.c:127

Referenced by pattern_threads_init().

◆ thread_next_unit()

static enum pnfs_status thread_next_unit ( IN pnfs_io_thread thread,
OUT pnfs_io_unit io 
)
static

Definition at line 330 of file pnfs_io.c.

333{
334 pnfs_io_pattern *pattern = thread->pattern;
336 enum pnfs_status status;
337
339
340 /* stop io if the layout is recalled */
341 status = pnfs_layout_recall_status(state, &thread->layout->layout);
342 if (status)
343 goto out_unlock;
344
345 status = stripe_next_unit(thread->layout, thread->id,
346 &thread->offset, pattern->offset_end, io);
347 if (status == PNFS_PENDING)
348 io->buffer = pattern->buffer + thread->offset - pattern->offset_start;
349
350out_unlock:
352 return status;
353}
enum pnfs_status pnfs_layout_recall_status(IN const pnfs_layout_state *state, IN const pnfs_layout *layout)
Definition: pnfs_layout.c:1211

Referenced by file_layout_read_thread(), and file_layout_write_thread().