nfs-ganesha 1.4
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 #ifdef _SOLARIS 00006 #include "solaris_port.h" 00007 #endif 00008 00009 #include "posixdb_internal.h" 00010 #include "posixdb_consistency.h" 00011 #include <string.h> 00012 00013 fsal_posixdb_status_t fsal_posixdb_add(fsal_posixdb_conn * p_conn, /* IN */ 00014 fsal_posixdb_fileinfo_t * p_object_info, /* IN */ 00015 posixfsal_handle_t * p_parent_directory_handle, /* IN */ 00016 fsal_name_t * p_filename, /* IN */ 00017 posixfsal_handle_t * p_object_handle /* OUT */ ) 00018 { 00019 PGresult *p_res; 00020 char handleid_str[MAX_HANDLEIDSTR_SIZE]; 00021 char handlets_str[MAX_HANDLETSSTR_SIZE]; 00022 char handleidparent_str[MAX_HANDLEIDSTR_SIZE]; 00023 char handletsparent_str[MAX_HANDLETSSTR_SIZE]; 00024 char devid_str[MAX_DEVICEIDSTR_SIZE]; 00025 char inode_str[MAX_INODESTR_SIZE]; 00026 int found; 00027 const char *paramValues[6]; 00028 fsal_posixdb_status_t st; 00029 00030 /******************* 00031 * 1/ sanity check * 00032 *******************/ 00033 00034 /* parent_directory and filename are NULL only if it is the root directory */ 00035 if(!p_conn || !p_object_info || !p_object_handle 00036 || (p_filename && !p_parent_directory_handle) || (!p_filename 00037 && p_parent_directory_handle)) 00038 ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); 00039 00040 CheckConn(p_conn); 00041 00042 LogFullDebug(COMPONENT_FSAL, "adding entry with parentid=%llu, id=%"PRIu64", name=%s\n", 00043 p_parent_directory_handle ? p_parent_directory_handle->data.id : 0, 00044 p_object_info ? p_object_info->inode : 0, 00045 p_filename ? p_filename->name : "NULL"); 00046 00047 BeginTransaction(p_conn, p_res); 00048 00049 /********************************* 00050 * 2/ we check the parent handle * 00051 *********************************/ 00052 00053 if(p_parent_directory_handle) 00054 { /* the root has no parent */ 00055 snprintf(handleidparent_str, MAX_HANDLEIDSTR_SIZE, "%llu", 00056 p_parent_directory_handle->data.id); 00057 snprintf(handletsparent_str, MAX_HANDLETSSTR_SIZE, "%i", 00058 p_parent_directory_handle->data.ts); 00059 paramValues[0] = handleidparent_str; 00060 paramValues[1] = handletsparent_str; 00061 p_res = PQexecPrepared(p_conn, "lookupHandle", 2, paramValues, NULL, NULL, 0); 00062 CheckResult(p_res); 00063 00064 if(PQntuples(p_res) != 1) 00065 { 00066 /* parent entry not found */ 00067 RollbackTransaction(p_conn, p_res); 00068 ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0); 00069 } 00070 PQclear(p_res); 00071 } 00072 /********************************************************** 00073 * 3/ Check if there is an existing Handle for the object * 00074 **********************************************************/ 00075 snprintf(devid_str, MAX_DEVICEIDSTR_SIZE, "%llu", 00076 (unsigned long long int)p_object_info->devid); 00077 snprintf(inode_str, MAX_INODESTR_SIZE, "%llu", 00078 (unsigned long long int)p_object_info->inode); 00079 paramValues[0] = devid_str; 00080 paramValues[1] = inode_str; 00081 p_res = PQexecPrepared(p_conn, "lookupHandleByInodeFU", 2, paramValues, NULL, NULL, 0); 00082 CheckResult(p_res); 00083 found = (PQntuples(p_res) == 1); 00084 00085 if(found) 00086 { /* a Handle (that matches devid & inode) already exists */ 00087 /* fill 'info' with information about the handle in the database */ 00088 posixdb_internal_fillFileinfoFromStrValues(&(p_object_handle->data.info), NULL, NULL, PQgetvalue(p_res, 0, 2), /* nlink */ 00089 PQgetvalue(p_res, 0, 3), /* ctime */ 00090 PQgetvalue(p_res, 0, 4) /* ftype */ 00091 ); 00092 p_object_handle->data.info.inode = p_object_info->inode; 00093 p_object_handle->data.info.devid = p_object_info->devid; 00094 strncpy(handleid_str, PQgetvalue(p_res, 0, 0), MAX_HANDLEIDSTR_SIZE); 00095 strncpy(handlets_str, PQgetvalue(p_res, 0, 1), MAX_HANDLETSSTR_SIZE); 00096 PQclear(p_res); 00097 00098 p_object_handle->data.id = atoll(handleid_str); 00099 p_object_handle->data.ts = atoi(handlets_str); 00100 00101 /* check the consistency of the handle */ 00102 if(fsal_posixdb_consistency_check(&(p_object_handle->data.info), p_object_info)) 00103 { 00104 /* consistency check failed */ 00105 /* p_object_handle has been filled in order to be able to fix the consistency later */ 00106 RollbackTransaction(p_conn, p_res); 00107 ReturnCodeDB(ERR_FSAL_POSIXDB_CONSISTENCY, 0); 00108 } 00109 00110 /* update nlink & ctime if needed */ 00111 if(p_object_info->nlink != p_object_handle->data.info.nlink 00112 || p_object_info->ctime != p_object_handle->data.info.ctime) 00113 { 00114 char nlink_str[MAX_NLINKSTR_SIZE]; 00115 char ctime_str[MAX_CTIMESTR_SIZE]; 00116 00117 snprintf(nlink_str, MAX_NLINKSTR_SIZE, "%i", p_object_info->nlink); 00118 snprintf(ctime_str, MAX_CTIMESTR_SIZE, "%i", (int)p_object_info->ctime); 00119 paramValues[0] = handleid_str; 00120 paramValues[1] = handlets_str; 00121 paramValues[2] = nlink_str; 00122 paramValues[3] = ctime_str; 00123 00124 p_object_handle->data.info = *p_object_info; 00125 00126 p_res = PQexecPrepared(p_conn, "updateHandle", 4, paramValues, NULL, NULL, 0); 00127 CheckCommand(p_res); 00128 } 00129 00130 fsal_posixdb_UpdateInodeCache(p_object_handle); 00131 00132 } 00133 else 00134 { /* no handle found */ 00135 /* Handle does not exist, add a new Handle entry */ 00136 char nlink_str[MAX_NLINKSTR_SIZE]; 00137 char ctime_str[MAX_CTIMESTR_SIZE]; 00138 char ftype_str[MAX_FTYPESTR_SIZE]; 00139 PQclear(p_res); 00140 00141 p_object_handle->data.ts = (int)time(NULL); 00142 p_object_handle->data.info = *p_object_info; 00143 snprintf(handlets_str, MAX_HANDLETSSTR_SIZE, "%i", p_object_handle->data.ts); 00144 snprintf(nlink_str, MAX_NLINKSTR_SIZE, "%i", p_object_info->nlink); 00145 snprintf(ctime_str, MAX_CTIMESTR_SIZE, "%i", (int)p_object_info->ctime); 00146 snprintf(ftype_str, MAX_CTIMESTR_SIZE, "%i", (int)p_object_info->ftype); 00147 00148 paramValues[0] = devid_str; 00149 paramValues[1] = inode_str; 00150 paramValues[2] = handlets_str; 00151 paramValues[3] = nlink_str; 00152 paramValues[4] = ctime_str; 00153 paramValues[5] = ftype_str; 00154 00155 p_res = PQexecPrepared(p_conn, "insertHandle", 6, paramValues, NULL, NULL, 0); 00156 CheckCommand(p_res); 00157 00158 PQclear(p_res); 00159 00160 p_res = 00161 PQexecPrepared(p_conn, "lookupHandleByInodeFU", 2, paramValues, NULL, NULL, 0); 00162 CheckResult(p_res); 00163 00164 strncpy(handleid_str, PQgetvalue(p_res, 0, 0), MAX_HANDLEIDSTR_SIZE); 00165 strncpy(handlets_str, PQgetvalue(p_res, 0, 1), MAX_HANDLETSSTR_SIZE); 00166 p_object_handle->data.id = atoll(PQgetvalue(p_res, 0, 0)); 00167 PQclear(p_res); 00168 00169 /* now, we have the handle id */ 00170 fsal_posixdb_UpdateInodeCache(p_object_handle); 00171 00172 } 00173 00174 /************************************************ 00175 * add (or update) an entry in the Parent table * 00176 ************************************************/ 00177 paramValues[0] = p_parent_directory_handle ? handleidparent_str : handleid_str; 00178 paramValues[1] = p_parent_directory_handle ? handletsparent_str : handlets_str; 00179 paramValues[2] = p_filename ? p_filename->name : ""; 00180 p_res = PQexecPrepared(p_conn, "lookupParent", 3, paramValues, NULL, NULL, 0); 00181 CheckResult(p_res); 00182 /* p-res contains handleid & handlets */ 00183 found = (PQntuples(p_res) == 1); 00184 paramValues[3] = handleid_str; 00185 paramValues[4] = handlets_str; 00186 if(found) 00187 { 00188 /* update the Parent entry if necessary (there entry exists with another handle) */ 00189 if((fsal_u64_t) atoll(PQgetvalue(p_res, 0, 0)) != p_object_handle->data.id 00190 || atoi(PQgetvalue(p_res, 0, 1)) != p_object_handle->data.ts) 00191 { 00192 /* steps : 00193 - check the nlink value of the Parent entry to be overwritten 00194 - if nlink = 1, then we can delete the handle. 00195 else we have to update it (nlink--) : that is done by fsal_posixdb_deleteParent 00196 - update the handle of the entry 00197 */ 00198 char bad_handleid_str[MAX_HANDLEIDSTR_SIZE]; 00199 char bad_handlets_str[MAX_HANDLETSSTR_SIZE]; 00200 int nlink; 00201 00202 strncpy(bad_handleid_str, PQgetvalue(p_res, 0, 0), MAX_HANDLEIDSTR_SIZE); 00203 strncpy(bad_handlets_str, PQgetvalue(p_res, 0, 1), MAX_HANDLETSSTR_SIZE); 00204 PQclear(p_res); /* clear old res before a new query */ 00205 00206 /* check the nlink value of the entry to be updated */ 00207 paramValues[0] = handleidparent_str; 00208 paramValues[1] = handletsparent_str; 00209 p_res = PQexecPrepared(p_conn, "lookupHandleFU", 2, paramValues, NULL, NULL, 0); 00210 CheckResult(p_res); 00211 00212 found = (PQntuples(p_res) == 1); 00213 00214 if(found) 00215 { /* we have retrieved the handle information of the bad entry */ 00216 nlink = atoi(PQgetvalue(p_res, 0, 4)); 00217 PQclear(p_res); /* clear old res before a new query */ 00218 00219 /* a Parent entry already exists, we delete it */ 00220 00221 st = fsal_posixdb_deleteParent(p_conn, bad_handleid_str, bad_handlets_str, 00222 p_parent_directory_handle ? 00223 handleidparent_str : handleid_str, 00224 p_parent_directory_handle ? 00225 handletsparent_str : handlets_str, 00226 p_filename ? p_filename->name : "", nlink); 00227 if(FSAL_POSIXDB_IS_ERROR(st)) 00228 { 00229 RollbackTransaction(p_conn, p_res); 00230 return st; 00231 } 00232 } 00233 else 00234 { /* the Handle line has been deleted */ 00235 PQclear(p_res); /* clear old res before a new query */ 00236 } 00237 00238 /* the bad entry has been deleted. Now we had a new Parent entry */ 00239 goto add_new_parent_entry; 00240 00241 } 00242 else 00243 { 00244 /* a Parent entry exists with our handle, nothing to do */ 00245 PQclear(p_res); 00246 } 00247 } 00248 else 00249 { 00250 /* add a Parent entry */ 00251 PQclear(p_res); 00252 add_new_parent_entry: 00253 paramValues[0] = p_parent_directory_handle ? handleidparent_str : handleid_str; 00254 paramValues[1] = p_parent_directory_handle ? handletsparent_str : handlets_str; 00255 paramValues[2] = p_filename ? p_filename->name : ""; 00256 paramValues[3] = handleid_str; 00257 paramValues[4] = handlets_str; 00258 00259 p_res = PQexecPrepared(p_conn, "insertParent", 5, paramValues, NULL, NULL, 0); 00260 CheckCommand(p_res); 00261 PQclear(p_res); 00262 /* XXX : is it possible to have unique key violation ? */ 00263 } 00264 00265 EndTransaction(p_conn, p_res); 00266 00267 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00268 }