nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=4:tabstop=4: 00003 */ 00004 00014 #ifdef HAVE_CONFIG_H 00015 #include "config.h" 00016 #endif 00017 00018 #include "fsal.h" 00019 #include "fsal_internal.h" 00020 #include "fsal_convert.h" 00021 00022 #include <unistd.h> 00023 #include <sys/types.h> 00024 00025 #ifdef _SHOOK 00026 #include "shook_svr.h" 00027 #endif 00028 00052 fsal_status_t LUSTREFSAL_truncate(fsal_handle_t * p_filehandle, /* IN */ 00053 fsal_op_context_t * p_context, /* IN */ 00054 fsal_size_t length, /* IN */ 00055 fsal_file_t * file_descriptor, /* Unused in this FSAL */ 00056 fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ 00057 ) 00058 { 00059 00060 int rc, errsv; 00061 fsal_path_t fsalpath; 00062 fsal_status_t st; 00063 int no_trunc = 0; 00064 00065 /* sanity checks. 00066 * note : object_attributes is optional. 00067 */ 00068 if(!p_filehandle || !p_context) 00069 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate); 00070 00071 /* get the path of the file and its handle */ 00072 st = fsal_internal_Handle2FidPath(p_context, p_filehandle, &fsalpath); 00073 if(FSAL_IS_ERROR(st)) 00074 ReturnStatus(st, INDEX_FSAL_truncate); 00075 00076 #ifdef _SHOOK 00077 /* If the file is not online: 00078 * - if truncate(0) => call tuncate(0), then "shook restore_trunc" 00079 * - if truncate(>0) => call "shook restore", then truncate 00080 */ 00081 shook_state state; 00082 rc = shook_get_status(fsalpath.path, &state, FALSE); 00083 if (rc) 00084 { 00085 LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s", 00086 fsalpath.path, strerror(-rc)); 00087 if (rc) 00088 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate); 00089 } 00090 else if (state != SS_ONLINE) 00091 { 00092 if (length == 0) 00093 { 00094 LogInfo(COMPONENT_FSAL, "File is offline: calling shook restore_trunc"); 00095 00096 /* first truncate the file, them call the shook_svr to clear 00097 * the 'released' flag */ 00098 00099 TakeTokenFSCall(); 00100 rc = truncate(fsalpath.path, 0); 00101 errsv = errno; 00102 ReleaseTokenFSCall(); 00103 00104 if (rc == 0) 00105 { 00106 /* use a short timeout of 2s */ 00107 rc = shook_server_call(SA_RESTORE_TRUNC, ((lustrefsal_op_context_t *)p_context)->export_context->fsname, 00108 &((lustrefsal_handle_t *)p_filehandle)->data.fid, 2); 00109 if (rc) 00110 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate); 00111 else { 00112 /* check that file is online, else operation is still 00113 * in progress: return err jukebox */ 00114 rc = shook_get_status(fsalpath.path, &state, FALSE); 00115 if (rc) 00116 { 00117 LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s", 00118 fsalpath.path, strerror(-rc)); 00119 if (rc) 00120 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate); 00121 } 00122 else if (state != SS_ONLINE) 00123 Return(ERR_FSAL_DELAY, -rc, INDEX_FSAL_truncate); 00124 /* OK */ 00125 } 00126 /* file is already truncated, no need to truncate again */ 00127 no_trunc = 1; 00128 } 00129 else 00130 { 00131 if(errsv == ENOENT) 00132 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_truncate); 00133 else 00134 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_truncate); 00135 } 00136 } 00137 else /* length > 0 */ 00138 { 00139 /* trigger restore. Give it a chance to retrieve the file in less than a second. 00140 * Else, it returns ETIME that is converted in ERR_DELAY */ 00141 rc = shook_server_call(SA_RESTORE, ((lustrefsal_op_context_t *)p_context)->export_context->fsname, 00142 &((lustrefsal_handle_t *)p_filehandle)->data.fid, 1); 00143 if (rc) 00144 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate); 00145 else { 00146 /* check that file is online, else operation is still 00147 * in progress: return err jukebox */ 00148 rc = shook_get_status(fsalpath.path, &state, FALSE); 00149 if (rc) 00150 { 00151 LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s", 00152 fsalpath.path, strerror(-rc)); 00153 if (rc) 00154 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate); 00155 } 00156 else if (state != SS_ONLINE) 00157 Return(ERR_FSAL_DELAY, -rc, INDEX_FSAL_truncate); 00158 /* OK */ 00159 } 00160 00161 /* if rc = 0, file can be opened */ 00162 } 00163 } 00164 /* else file is on line */ 00165 #endif 00166 00167 /* Executes the POSIX truncate operation */ 00168 00169 if (!no_trunc) 00170 { 00171 TakeTokenFSCall(); 00172 rc = truncate(fsalpath.path, length); 00173 errsv = errno; 00174 ReleaseTokenFSCall(); 00175 } 00176 00177 /* convert return code */ 00178 if(rc) 00179 { 00180 if(errsv == ENOENT) 00181 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_truncate); 00182 else 00183 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_truncate); 00184 } 00185 00186 /* Optionally retrieve attributes */ 00187 if(p_object_attributes) 00188 { 00189 00190 fsal_status_t st; 00191 00192 st = LUSTREFSAL_getattrs(p_filehandle, p_context, p_object_attributes); 00193 00194 if(FSAL_IS_ERROR(st)) 00195 { 00196 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00197 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00198 } 00199 00200 } 00201 00202 /* No error occurred */ 00203 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate); 00204 00205 }