nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 * 00004 * Copyright CEA/DAM/DIF (2008) 00005 * contributeur : Philippe DENIEL philippe.deniel@cea.fr 00006 * Thomas LEIBOVICI thomas.leibovici@cea.fr 00007 * 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 3 of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 * --------------------------------------- 00024 */ 00025 00037 #ifdef HAVE_CONFIG_H 00038 #include "config.h" 00039 #endif 00040 00041 #ifdef _SOLARIS 00042 #include "solaris_port.h" 00043 #endif 00044 00045 #include <stdio.h> 00046 #include <string.h> 00047 #include <pthread.h> 00048 #include "HashData.h" 00049 #include "HashTable.h" 00050 #include "log.h" 00051 #include "ganesha_rpc.h" 00052 #include "nfs4.h" 00053 #include "nfs_core.h" 00054 #include "sal_functions.h" 00055 #include "nfs_proto_functions.h" 00056 #include "nfs_proto_tools.h" 00057 00070 #define arg_OPEN_DOWNGRADE4 op->nfs_argop4_u.opopen_downgrade 00071 #define res_OPEN_DOWNGRADE4 resp->nfs_resop4_u.opopen_downgrade 00072 00073 static nfsstat4 nfs4_do_open_downgrade(struct nfs_argop4 * op, 00074 compound_data_t * data, 00075 cache_entry_t * pentry_file, 00076 state_owner_t * powner, 00077 state_t ** statep, 00078 char ** cause); 00079 00080 int nfs4_op_open_downgrade(struct nfs_argop4 *op, 00081 compound_data_t * data, struct nfs_resop4 *resp) 00082 { 00083 state_t * pstate_found = NULL; 00084 state_owner_t * popen_owner; 00085 int rc; 00086 const char * tag = "OPEN_DOWNGRADE"; 00087 00088 resp->resop = NFS4_OP_OPEN_DOWNGRADE; 00089 res_OPEN_DOWNGRADE4.status = NFS4_OK; 00090 00091 /* 00092 * Do basic checks on a filehandle 00093 * Commit is done only on a file 00094 */ 00095 res_OPEN_DOWNGRADE4.status = nfs4_sanity_check_FH(data, 0LL); 00096 if(res_OPEN_DOWNGRADE4.status != NFS4_OK) 00097 return res_OPEN_DOWNGRADE4.status; 00098 00099 /* Commit is done only on a file */ 00100 if(data->current_filetype != REGULAR_FILE) 00101 { 00102 res_OPEN_DOWNGRADE4.status = NFS4ERR_INVAL; 00103 return res_OPEN_DOWNGRADE4.status; 00104 } 00105 00106 /* Check stateid correctness and get pointer to state */ 00107 if((rc = nfs4_Check_Stateid(&arg_OPEN_DOWNGRADE4.open_stateid, 00108 data->current_entry, 00109 &pstate_found, 00110 data, 00111 STATEID_SPECIAL_FOR_LOCK, 00112 tag)) != NFS4_OK) 00113 { 00114 res_OPEN_DOWNGRADE4.status = rc; 00115 LogDebug(COMPONENT_STATE, 00116 "OPEN_DOWNGRADE failed nfs4_Check_Stateid"); 00117 return res_OPEN_DOWNGRADE4.status; 00118 } 00119 00120 popen_owner = pstate_found->state_powner; 00121 00122 P(popen_owner->so_mutex); 00123 00124 /* Check seqid */ 00125 if(!Check_nfs4_seqid(popen_owner, arg_OPEN_DOWNGRADE4.seqid, op, data, resp, tag)) 00126 { 00127 /* Response is all setup for us and LogDebug told what was wrong */ 00128 V(popen_owner->so_mutex); 00129 return res_OPEN_DOWNGRADE4.status; 00130 } 00131 V(popen_owner->so_mutex); 00132 00133 00134 /* What kind of open is it ? */ 00135 LogFullDebug(COMPONENT_STATE, 00136 "OPEN_DOWNGRADE: Share Deny = %d Share Access = %d ", 00137 arg_OPEN_DOWNGRADE4.share_deny, 00138 arg_OPEN_DOWNGRADE4.share_access); 00139 00140 if(data->minorversion == 1) /* NFSv4.1 */ 00141 { 00142 if((pstate_found->state_data.share.share_access & arg_OPEN_DOWNGRADE4.share_access) != 00143 (arg_OPEN_DOWNGRADE4.share_access)) 00144 { 00145 /* Open share access is not a superset of downgrade share access */ 00146 res_OPEN_DOWNGRADE4.status = NFS4ERR_INVAL; 00147 return res_OPEN_DOWNGRADE4.status; 00148 } 00149 00150 if((pstate_found->state_data.share.share_deny & arg_OPEN_DOWNGRADE4.share_deny) != 00151 (arg_OPEN_DOWNGRADE4.share_deny)) 00152 { 00153 /* Open share deny is not a superset of downgrade share deny */ 00154 res_OPEN_DOWNGRADE4.status = NFS4ERR_INVAL; 00155 return res_OPEN_DOWNGRADE4.status; 00156 } 00157 00158 pstate_found->state_data.share.share_access = arg_OPEN_DOWNGRADE4.share_access; 00159 pstate_found->state_data.share.share_deny = arg_OPEN_DOWNGRADE4.share_deny; 00160 } 00161 else /* NFSv4.0 */ 00162 { 00163 nfsstat4 status4; 00164 char * cause = ""; 00165 status4 = nfs4_do_open_downgrade(op, data, pstate_found->state_pentry, 00166 pstate_found->state_powner, &pstate_found, 00167 &cause); 00168 if(status4 != NFS4_OK) 00169 { 00170 LogEvent(COMPONENT_STATE, "Failed to open downgrade: %s", cause); 00171 res_OPEN_DOWNGRADE4.status = status4; 00172 return res_OPEN_DOWNGRADE4.status; 00173 } 00174 } 00175 00176 /* Successful exit */ 00177 res_OPEN_DOWNGRADE4.status = NFS4_OK; 00178 00179 /* Handle stateid/seqid for success */ 00180 update_stateid(pstate_found, 00181 &res_OPEN_DOWNGRADE4.OPEN_DOWNGRADE4res_u.resok4.open_stateid, 00182 data, 00183 tag); 00184 00185 /* Save the response in the open owner */ 00186 Copy_nfs4_state_req(pstate_found->state_powner, arg_OPEN_DOWNGRADE4.seqid, op, data, resp, tag); 00187 00188 return res_OPEN_DOWNGRADE4.status; 00189 } /* nfs4_op_opendowngrade */ 00190 00201 void nfs4_op_open_downgrade_Free(OPEN_DOWNGRADE4res * resp) 00202 { 00203 /* Nothing to be done */ 00204 return; 00205 } /* nfs4_op_open_downgrade_Free */ 00206 00207 void nfs4_op_open_downgrade_CopyRes(OPEN_DOWNGRADE4res * resp_dst, OPEN_DOWNGRADE4res * resp_src) 00208 { 00209 /* Nothing to be done */ 00210 return; 00211 } 00212 00213 static nfsstat4 nfs4_do_open_downgrade(struct nfs_argop4 * op, 00214 compound_data_t * data, 00215 cache_entry_t * pentry_file, 00216 state_owner_t * powner, 00217 state_t ** statep, 00218 char ** cause) 00219 { 00220 state_data_t candidate_data; 00221 state_status_t state_status; 00222 OPEN_DOWNGRADE4args *args = &op->nfs_argop4_u.opopen_downgrade; 00223 00224 candidate_data.share.share_access = args->share_access; 00225 candidate_data.share.share_deny = args->share_deny; 00226 00227 pthread_rwlock_wrlock(&data->current_entry->state_lock); 00228 /* Check if given share access is subset of current share access */ 00229 if(((*statep)->state_data.share.share_access & args->share_access) != 00230 (args->share_access)) 00231 { 00232 /* Open share access is not a superset of downgrade share access */ 00233 *cause = " (invalid share access for downgrade)"; 00234 pthread_rwlock_unlock(&data->current_entry->state_lock); 00235 return NFS4ERR_INVAL; 00236 } 00237 00238 /* Check if given share deny is subset of current share deny */ 00239 if(((*statep)->state_data.share.share_deny & args->share_deny) != 00240 (args->share_deny)) 00241 { 00242 /* Open share deny is not a superset of downgrade share deny */ 00243 *cause = " (invalid share deny for downgrade)"; 00244 pthread_rwlock_unlock(&data->current_entry->state_lock); 00245 return NFS4ERR_INVAL; 00246 } 00247 00248 /* Check if given share access is previously seen */ 00249 if(state_share_check_prev(*statep, &candidate_data) != STATE_SUCCESS) 00250 { 00251 *cause = " (share access or deny never seen before)"; 00252 pthread_rwlock_unlock(&data->current_entry->state_lock); 00253 return NFS4ERR_INVAL; 00254 } 00255 00256 if(state_share_downgrade(pentry_file, data->pcontext, &candidate_data, 00257 powner, *statep, 00258 &state_status) != STATE_SUCCESS) 00259 { 00260 *cause = " (state_share_downgrade failed)"; 00261 pthread_rwlock_unlock(&data->current_entry->state_lock); 00262 return NFS4ERR_SERVERFAULT; 00263 } 00264 00265 pthread_rwlock_unlock(&data->current_entry->state_lock); 00266 return NFS4_OK; 00267 }