1 /*
2 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2006 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * Copyright (c) 2013 University of Houston. All rights reserved.
13 * Copyright (c) 2018 Research Organization for Information Science
14 * and Technology (RIST). All rights reserved.
15 * $COPYRIGHT$
16 *
17 * Additional copyrights may follow
18 *
19 * $HEADER$
20 *
21 * These symbols are in a file by themselves to provide nice linker
22 * semantics. Since linkers generally pull in symbols by object fules,
23 * keeping these symbols as the only symbols in this file prevents
24 * utility programs such as "ompi_info" from having to import entire
25 * modules just to query their version and parameters
26 */
27
28 #include "ompi_config.h"
29 #include "mpi.h"
30 #include "ompi/mca/sharedfp/sharedfp.h"
31 #include "ompi/mca/sharedfp/base/base.h"
32 #include "ompi/mca/sharedfp/lockedfile/sharedfp_lockedfile.h"
33
34 /* included so that we can test file locking availability */
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <unistd.h>
38
39 /*
40 * *******************************************************************
41 * ************************ actions structure ************************
42 * *******************************************************************
43 */
44 /* IMPORTANT: Update here when adding sharedfp component interface functions*/
45 static mca_sharedfp_base_module_1_0_0_t lockedfile = {
46 mca_sharedfp_lockedfile_module_init, /* initalise after being selected */
47 mca_sharedfp_lockedfile_module_finalize, /* close a module on a communicator */
48 mca_sharedfp_lockedfile_seek,
49 mca_sharedfp_lockedfile_get_position,
50 mca_sharedfp_lockedfile_read,
51 mca_sharedfp_lockedfile_read_ordered,
52 mca_sharedfp_lockedfile_read_ordered_begin,
53 mca_sharedfp_lockedfile_read_ordered_end,
54 mca_sharedfp_lockedfile_iread,
55 mca_sharedfp_lockedfile_write,
56 mca_sharedfp_lockedfile_write_ordered,
57 mca_sharedfp_lockedfile_write_ordered_begin,
58 mca_sharedfp_lockedfile_write_ordered_end,
59 mca_sharedfp_lockedfile_iwrite,
60 mca_sharedfp_lockedfile_file_open,
61 mca_sharedfp_lockedfile_file_close
62 };
63 /*
64 * *******************************************************************
65 * ************************* structure ends **************************
66 * *******************************************************************
67 */
68
69 int mca_sharedfp_lockedfile_component_init_query(bool enable_progress_threads,
70 bool enable_mpi_threads)
71 {
72 /* Nothing to do */
73
74 return OMPI_SUCCESS;
75 }
76
77 struct mca_sharedfp_base_module_1_0_0_t * mca_sharedfp_lockedfile_component_file_query(ompio_file_t *fh, int *priority) {
78 struct flock lock;
79 int fd, err;
80 /*char *filename;*/
81 char filename[256];
82 int rank;
83 bool has_file_lock_support=false;
84
85 *priority = mca_sharedfp_lockedfile_priority;
86
87 /*get the rank of this process*/
88 rank = ompi_comm_rank ( fh->f_comm);
89
90 /*test, and update priority*/
91 /*
92 * This test tests to see if fcntl returns success when asked to
93 * establish a file lock. This test is intended for use on file systems
94 * such as NFS that may not implement file locks. The locked file algorithm makes use
95 * of file locks to implement the shared file pointer operations, and will not work
96 * properly if file locks are not available.
97 *
98 * This is a simple test and has at least two limitations:
99 *
100 * 1. Some implementations of NFS are known to return success for
101 * setting a file lock when in fact no lock has been set. This
102 * test will not detect such erroneous implementations of NFS
103 *
104 * 2. Some implementations will hang (enter and wait indefinitately)
105 * within the fcntl call. This test will also hang in that case.
106 * Under normal conditions, this test should only take a few seconds to
107 * run.
108 *
109 * The test prints a message showing the success or failure of
110 * setting the file lock if PRINT_TAG is set to true in sharedfp.h.
111 * It also sets the priority to a non-zero value on success and
112 * returns NULL on failure. If there is a failure, the system routine
113 * strerror is interogated in order to print the reason.
114 */
115
116 /* Set the filename. */
117 /*data filename created by appending .locktest.$rank to the original filename*/
118 sprintf(filename,"%s%s%d",fh->f_filename,".locktest.",rank);
119
120 lock.l_type = F_WRLCK;
121 lock.l_start = 0;
122 lock.l_whence = SEEK_SET;
123 lock.l_len = 100;
124 lock.l_pid = getpid();
125
126 fd = open(filename, O_RDWR | O_CREAT, 0644);
127
128 if ( -1 == fd ){
129 opal_output(ompi_sharedfp_base_framework.framework_output,
130 "mca_sharedfp_lockedfile_component_file_query: error opening file %s %s", filename, strerror(errno));
131 has_file_lock_support=false;
132 }
133 else{
134 err = fcntl(fd, F_SETLKW, &lock);
135 opal_output(ompi_sharedfp_base_framework.framework_output,
136 "mca_sharedfp_lockedfile_component_file_query: returned err=%d, for fd=%d\n",err,fd);
137
138 if (err) {
139 opal_output(ompi_sharedfp_base_framework.framework_output,
140 "mca_sharedfp_lockedfile_component_file_query: Failed to set a file lock on %s %s\n", filename, strerror(errno) );
141 opal_output(ompi_sharedfp_base_framework.framework_output,
142 "err=%d, errno=%d, EOPNOTSUPP=%d, EINVAL=%d, ENOSYS=%d, EACCES=%d, EAGAIN=%d, EBADF=%d\n",
143 err, errno, EOPNOTSUPP, EINVAL, ENOSYS, EACCES, EAGAIN, EBADF);
144
145 if (errno == EACCES || errno == EAGAIN) {
146 opal_output(ompi_sharedfp_base_framework.framework_output,
147 "errno=EACCES || EAGAIN, Already locked by another process\n");
148 }
149
150 }
151 else {
152 opal_output(ompi_sharedfp_base_framework.framework_output,
153 "mca_sharedfp_lockedfile_component_file_query: fcntl claims success in setting a file lock on %s\n", filename );
154
155 has_file_lock_support=true;
156 }
157 /* printf("err = %d, errno = %d\n", err, errno); */
158 close(fd);
159 unlink( filename );
160 }
161 /**priority=100;*/
162 if(has_file_lock_support){
163 return &lockedfile;
164 }
165
166 *priority = 0;
167 /*module can not run!, return NULL to indicate that we are unable to run*/
168
169 opal_output(ompi_sharedfp_base_framework.framework_output,
170 "mca_sharedfp_lockedfile_component_file_query: Can not run!, file locking not supported\n");
171 return NULL;
172 }
173
174 int mca_sharedfp_lockedfile_component_file_unquery (ompio_file_t *file)
175 {
176 /* This function might be needed for some purposes later. for now it
177 * does not have anything to do since there are no steps which need
178 * to be undone if this module is not selected */
179
180 return OMPI_SUCCESS;
181 }
182
183 int mca_sharedfp_lockedfile_module_init (ompio_file_t *file)
184 {
185 return OMPI_SUCCESS;
186 }
187
188
189 int mca_sharedfp_lockedfile_module_finalize (ompio_file_t *file)
190 {
191 return OMPI_SUCCESS;
192 }