nfs-ganesha 1.4

nfs4_op_open_downgrade.c

Go to the documentation of this file.
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 }