nfs-ganesha 1.4

nfs4_op_open.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 
00058 static nfsstat4 nfs4_chk_shrdny(struct nfs_argop4 *, compound_data_t *,
00059     cache_entry_t *, fsal_accessflags_t, fsal_accessflags_t, fsal_openflags_t *,
00060     bool_t , fsal_attrib_list_t *, struct nfs_resop4 *);
00061 
00062 static nfsstat4 nfs4_do_open(struct nfs_argop4  * op,
00063                              compound_data_t    * data,
00064                              cache_entry_t      * pentry_newfile,
00065                              cache_entry_t      * pentry_parent,
00066                              state_owner_t      * powner,
00067                              state_t           ** statep,
00068                              fsal_name_t        * filename,
00069                              fsal_openflags_t     openflags,
00070                              char              ** cause2);
00071 
00072 static nfsstat4 nfs4_create_fh(compound_data_t *, cache_entry_t *, char **);
00086 #define STATE_ADD " (state_add failed)"
00087 #define STATE_SHARE_ADD  " (state_share_add failed)"
00088 #define STATE_SHARE_UP   " (state_share_upgrade failed)"
00089 #define CACHE_INODE_OPEN " cache_inode_open"
00090 #define arg_OPEN4 op->nfs_argop4_u.opopen
00091 #define res_OPEN4 resp->nfs_resop4_u.opopen
00092 
00093 int nfs4_op_open(struct nfs_argop4 *op, compound_data_t *data,
00094     struct nfs_resop4 *resp)
00095 {
00096   char __attribute__ ((__unused__)) funcname[] = "nfs4_op_open";
00097 
00098   cache_entry_t           * pentry_parent = NULL;
00099   cache_entry_t           * pentry_lookup = NULL;
00100   cache_entry_t           * pentry_newfile = NULL;
00101   fsal_attrib_list_t        attr_parent;
00102   fsal_attrib_list_t        attr;
00103   fsal_attrib_list_t        attr_newfile;
00104   fsal_attrib_list_t        sattr;
00105   fsal_openflags_t          openflags = 0;
00106   cache_inode_status_t      cache_status = CACHE_INODE_SUCCESS;
00107   state_status_t            state_status;
00108   int                       retval;
00109   fsal_name_t               filename;
00110   bool_t                    AttrProvided = FALSE;
00111   bool_t                    ReuseState = FALSE;
00112   fsal_accessmode_t         mode = 0600;
00113   nfs_client_id_t         * pclientid;
00114   state_t                 * pfile_state = NULL;
00115   state_t                 * pstate_iterate;
00116   state_nfs4_owner_name_t   owner_name;
00117   state_owner_t           * powner = NULL;
00118   const char              * tag = "OPEN";
00119   const char              * cause = "OOPS";
00120   const char              * cause2 = "";
00121   struct glist_head       * glist;
00122   open_claim_type4          claim = arg_OPEN4.claim.claim;
00123   nfsstat4                  status4;
00124   uint32_t                  tmp_attr[2];
00125 #ifdef _USE_QUOTA
00126   fsal_status_t            fsal_status;
00127 #endif
00128   char                    * text = "";
00129 
00130   LogDebug(COMPONENT_STATE,
00131            "Entering NFS v4 OPEN handler -----------------------------------------------------");
00132 
00133   /* What kind of open is it ? */
00134   LogFullDebug(COMPONENT_STATE,
00135                "OPEN: Claim type = %d   Open Type = %d  Share Deny = %d   Share Access = %d ",
00136                arg_OPEN4.claim.claim,
00137                arg_OPEN4.openhow.opentype,
00138                arg_OPEN4.share_deny,
00139                arg_OPEN4.share_access);
00140 
00141   fsal_accessflags_t write_access = FSAL_WRITE_ACCESS;
00142   fsal_accessflags_t read_access = FSAL_READ_ACCESS;
00143 
00144   resp->resop = NFS4_OP_OPEN;
00145   res_OPEN4.status = NFS4_OK;
00146   res_OPEN4.OPEN4res_u.resok4.rflags = 0 ;
00147 
00148   /* Do basic checks on a filehandle */
00149   res_OPEN4.status = nfs4_sanity_check_FH(data, 0LL);
00150   if(res_OPEN4.status != NFS4_OK)
00151     return res_OPEN4.status;
00152 
00153   /* This can't be done on the pseudofs */
00154   if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
00155     {
00156       res_OPEN4.status = NFS4ERR_ROFS;
00157       LogDebug(COMPONENT_STATE,
00158                "NFS4 OPEN returning NFS4ERR_ROFS");
00159       return res_OPEN4.status;
00160     }
00161 
00162   if (nfs_export_check_security(data->reqp, data->pexport) == FALSE)
00163     {
00164       res_OPEN4.status = NFS4ERR_PERM;
00165       return res_OPEN4.status;
00166     }
00167 
00168   /*
00169    * If Filehandle points to a xattr object, manage it via the xattrs
00170    * specific functions
00171    */
00172   if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
00173     return nfs4_op_open_xattr(op, data, resp);
00174 
00175   /* If data->current_entry is empty, repopulate it */
00176   if(data->current_entry == NULL)
00177     {
00178       /* refcount +1 */
00179       if((data->current_entry = nfs_FhandleToCache(NFS_V4,
00180                                                    NULL,
00181                                                    NULL,
00182                                                    &(data->currentFH),
00183                                                    NULL,
00184                                                    NULL,
00185                                                    &(res_OPEN4.status),
00186                                                    &attr,
00187                                                    data->pcontext,
00188                                                    &retval)) == NULL)
00189         {
00190           res_OPEN4.status = NFS4ERR_RESOURCE;
00191           LogDebug(COMPONENT_STATE,
00192                    "NFS4 OPEN returning NFS4ERR_RESOURCE after "
00193                    "trying to repopulate cache");
00194           return res_OPEN4.status;
00195         }
00196     }
00197 
00198   if (claim == CLAIM_PREVIOUS)
00199       cause = "CLAIM_PREVIOUS";
00200   else
00201       cause = "CLAIM_NULL";
00202 
00203   /* Set parent */
00204   /* for CLAIM_PREVIOUS, currentFH is the file being reclaimed, not a dir */
00205   pentry_parent = data->current_entry;
00206 
00207   /* It this a known client id ? */
00208   LogDebug(COMPONENT_STATE,
00209            "OPEN Client id = %llx",
00210            (unsigned long long)arg_OPEN4.owner.clientid);
00211 
00212   if(nfs_client_id_get_confirmed(arg_OPEN4.owner.clientid, &pclientid) !=
00213       CLIENT_ID_SUCCESS)
00214     {
00215       res_OPEN4.status = NFS4ERR_STALE_CLIENTID;
00216       cause2 = " (failed to find confirmed clientid)";
00217       goto out3;
00218     }
00219 
00220   /* Check if lease is expired and reserve it */
00221   P(pclientid->cid_mutex);
00222 
00223   if(!reserve_lease(pclientid))
00224     {
00225       V(pclientid->cid_mutex);
00226 
00227       dec_client_id_ref(pclientid);
00228 
00229       res_OPEN4.status = NFS4ERR_EXPIRED;
00230       cause2 = " (clientid expired)";
00231       goto out3;
00232     }
00233 
00234   V(pclientid->cid_mutex);
00235 
00236   if (arg_OPEN4.openhow.opentype == OPEN4_CREATE && claim != CLAIM_NULL) {
00237       res_OPEN4.status = NFS4ERR_INVAL;
00238       cause2 = " (create without claim type null)";
00239       goto out2;
00240   }
00241 
00242   /* Is this open_owner known? If so, get it so we can use replay cache */
00243   convert_nfs4_open_owner(&arg_OPEN4.owner, &owner_name, 0LL);
00244 
00245   if(!nfs4_owner_Get_Pointer(&owner_name, &powner))
00246     {
00247       LogFullDebug(COMPONENT_STATE, "OPEN new owner");
00248     }
00249   else
00250     {
00251       if(isFullDebug(COMPONENT_STATE))
00252         {
00253           char str[HASHTABLE_DISPLAY_STRLEN];
00254 
00255           display_nfs4_owner(powner, str);
00256 
00257           LogFullDebug(COMPONENT_STATE,
00258                        "A previously known open_owner is used:%p %s arg_OPEN4.seqid=%u",
00259                        powner, str, arg_OPEN4.seqid);
00260         }
00261 
00262       if(arg_OPEN4.seqid == 0)
00263         {
00264           LogDebug(COMPONENT_STATE,
00265                    "Previously known open_owner is used with seqid=0, ask the client to confirm it again");
00266           powner->so_owner.so_nfs4_owner.so_confirmed = FALSE;
00267         }
00268       else
00269         {
00270           /* Check for replay */
00271           if(!Check_nfs4_seqid(powner, arg_OPEN4.seqid, op, data, resp, tag))
00272             {
00273               /* Response is setup for us and LogDebug told what was wrong */
00274               goto out2;
00275             }
00276         }
00277     }
00278   /* Is this open_owner known ? */
00279   if(powner == NULL)
00280     {
00281       /* This open owner is not known yet, allocated and set up a new one */
00282       powner = create_nfs4_owner(&owner_name,
00283                                  pclientid,
00284                                  STATE_OPEN_OWNER_NFSV4,
00285                                  NULL,
00286                                  0);
00287 
00288       if(powner == NULL)
00289         {
00290           res_OPEN4.status = NFS4ERR_RESOURCE;
00291           LogDebug(COMPONENT_STATE,
00292                    "NFS4 OPEN returning NFS4ERR_RESOURCE for CLAIM_NULL (could not create NFS4 Owner");
00293           dec_client_id_ref(pclientid);
00294           return res_OPEN4.status;
00295         }
00296     }
00297 
00298   if (nfs_in_grace() && claim != CLAIM_PREVIOUS)
00299     {
00300        cause2 = " (in grace period)";
00301        res_OPEN4.status = NFS4ERR_GRACE;
00302        goto out;
00303     }
00304   if (nfs_in_grace() && claim == CLAIM_PREVIOUS &&
00305      pclientid->cid_allow_reclaim != 1)
00306     {
00307        cause2 = " (client cannot reclaim)";
00308        res_OPEN4.status = NFS4ERR_NO_GRACE;
00309        goto out;
00310     }
00311   if (!nfs_in_grace() && claim == CLAIM_PREVIOUS)
00312     {
00313        cause2 = " (not in grace period)";
00314        res_OPEN4.status = NFS4ERR_NO_GRACE;
00315        goto out;
00316     }
00317 
00318   /*
00319    * check if share_access does not have any access set, or has invalid bits
00320    * that are set.  check that share_deny doesn't have any invalid bits set.
00321    */
00322   if (!(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_BOTH) ||
00323       (arg_OPEN4.share_access & ~OPEN4_SHARE_ACCESS_BOTH) ||
00324       (arg_OPEN4.share_deny & ~OPEN4_SHARE_DENY_BOTH))
00325    {
00326        res_OPEN4.status = NFS4ERR_INVAL;
00327        cause2 = " (invalid share_access or share_deny)";
00328        goto out;
00329    }
00330 
00331   /* Set openflags. */
00332   if(arg_OPEN4.share_access == OPEN4_SHARE_ACCESS_BOTH)
00333     openflags = FSAL_O_RDWR;
00334   else if(arg_OPEN4.share_access == OPEN4_SHARE_ACCESS_READ)
00335     openflags = FSAL_O_RDONLY;
00336   else if(arg_OPEN4.share_access == OPEN4_SHARE_ACCESS_WRITE)
00337     openflags = FSAL_O_WRONLY;
00338 
00339   /* First switch is based upon claim type */
00340   switch (claim)
00341     {
00342     case CLAIM_NULL:
00343       /* Check for name length */
00344       if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN)
00345         {
00346           res_OPEN4.status = NFS4ERR_NAMETOOLONG;
00347           goto out;
00348         }
00349 
00350       /* get the filename from the argument, it should not be empty */
00351       if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0)
00352         {
00353           res_OPEN4.status = NFS4ERR_INVAL;
00354           cause2 = " (empty filename)";
00355           goto out;
00356         }
00357 
00358       /* Check if asked attributes are correct */
00359       if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 ||
00360          arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4)
00361         {
00362           if(!nfs4_Fattr_Supported
00363              (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs))
00364             {
00365               res_OPEN4.status = NFS4ERR_ATTRNOTSUPP;
00366               goto out;
00367             }
00368 
00369           /* Do not use READ attr, use WRITE attr */
00370           if(!nfs4_Fattr_Check_Access
00371              (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs,
00372               FATTR4_ATTR_WRITE))
00373             {
00374               res_OPEN4.status = NFS4ERR_INVAL;
00375               cause2 = " (bad attr)";
00376               goto out;
00377             }
00378         }
00379 
00380       /* Check if filename is correct */
00381       if((cache_status =
00382           cache_inode_error_convert(FSAL_buffdesc2name
00383                                     ((fsal_buffdesc_t *) & arg_OPEN4.claim.open_claim4_u.
00384                                      file, &filename))) != CACHE_INODE_SUCCESS)
00385         {
00386           res_OPEN4.status = nfs4_Errno(cache_status);
00387           cause2 = " FSAL_buffdesc2name";
00388           goto out;
00389         }
00390 
00391       /* Check parent */
00392       pentry_parent = data->current_entry;
00393 
00394       /* Parent must be a directory */
00395       if((pentry_parent->type != DIRECTORY))
00396         {
00397           /* Parent object is not a directory... */
00398           if(pentry_parent->type == SYMBOLIC_LINK)
00399             res_OPEN4.status = NFS4ERR_SYMLINK;
00400           else
00401             res_OPEN4.status = NFS4ERR_NOTDIR;
00402 
00403           cause2 = " (parent not directory)";
00404           goto out;
00405         }
00406 
00407       /* Status of parent directory before the operation */
00408       if(cache_inode_getattr(pentry_parent,
00409                              &attr_parent,
00410                              data->pcontext,
00411                              &cache_status) != CACHE_INODE_SUCCESS)
00412         {
00413           res_OPEN4.status = nfs4_Errno(cache_status);
00414           cause2 = " cache_inode_getattr";
00415           goto out;
00416         }
00417 
00418       res_OPEN4.OPEN4res_u.resok4.cinfo.before
00419            = cache_inode_get_changeid4(pentry_parent);
00420 
00421       /* CLient may have provided fattr4 to set attributes at creation time */
00422       if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 ||
00423          arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4)
00424         {
00425           if(arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs.attrmask.
00426              bitmap4_len != 0)
00427             {
00428               /* Convert fattr4 so nfs4_sattr */
00429               res_OPEN4.status =
00430                   nfs4_Fattr_To_FSAL_attr(&sattr,
00431                                           &(arg_OPEN4.openhow.openflag4_u.how.
00432                                             createhow4_u.createattrs));
00433 
00434               if(res_OPEN4.status != NFS4_OK)
00435                 {
00436                   cause2 = " (nfs4_Fattr_To_FSAL_attr failed)";
00437                   goto out;
00438                 }
00439 
00440               AttrProvided = TRUE;
00441             }
00442         }
00443 
00444       /* Second switch is based upon "openhow" */
00445       switch (arg_OPEN4.openhow.opentype)
00446         {
00447         case OPEN4_CREATE:
00448           /* a new file is to be created */
00449 #ifdef _USE_QUOTA
00450           /* if quota support is active, then we should check is the FSAL allows inode creation or not */
00451           fsal_status = FSAL_check_quota( data->pexport->fullpath, 
00452                                           FSAL_QUOTA_INODES,
00453                                           FSAL_OP_CONTEXT_TO_UID( data->pcontext ) ) ;
00454           if( FSAL_IS_ERROR( fsal_status ) )
00455             {
00456               res_OPEN4.status = NFS4ERR_DQUOT ;
00457               dec_client_id_ref(pclientid);
00458               return res_OPEN4.status;
00459             }
00460 #endif /* _USE_QUOTA */
00461 
00462           if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4)
00463             cause = "OPEN4_CREATE EXCLUSIVE";
00464           else
00465             cause = "OPEN4_CREATE";
00466 
00467           /* Does a file with this name already exist ? */
00468           pentry_lookup = cache_inode_lookup(pentry_parent,
00469                                              &filename,
00470                                              &attr_newfile,
00471                                              data->pcontext,
00472                                              &cache_status);
00473           if(cache_status != CACHE_INODE_NOT_FOUND)
00474             {
00475               /* if open is UNCHECKED, return NFS4_OK (RFC3530 page 172) */
00476               if(arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4
00477                  && (cache_status == CACHE_INODE_SUCCESS))
00478                 {
00479 
00480                   /*
00481                    * we are not creating the file, attributes on recreate
00482                    * should be ignored except for size = 0.
00483                    */
00484                   if (AttrProvided && (sattr.asked_attributes & FSAL_ATTR_SIZE)
00485                      && (sattr.filesize == 0))
00486                     {
00487                       sattr.asked_attributes = FSAL_ATTR_SIZE;
00488                     }
00489                   else
00490                     {
00491                       AttrProvided = FALSE;
00492                     }
00493                   pthread_rwlock_wrlock(&pentry_lookup->state_lock);
00494                   status4 = nfs4_chk_shrdny(op, data, pentry_lookup,
00495                       read_access, write_access, &openflags, AttrProvided,
00496                       &sattr, resp);
00497                   if (status4 != NFS4_OK)
00498                     {
00499                       pthread_rwlock_unlock(&pentry_lookup->state_lock);
00500                       cause2 = " cache_inode_access";
00501                       res_OPEN4.status = status4;
00502                       cache_inode_put(pentry_lookup);
00503                       goto out;
00504                     }
00505 
00506                   status4 = nfs4_do_open(op, data, pentry_lookup, pentry_parent,
00507                       powner, &pfile_state, &filename, openflags, &text);
00508                   pthread_rwlock_unlock(&pentry_lookup->state_lock);
00509                   if (status4 != NFS4_OK)
00510                     {
00511                       cause2 = (const char *)text;
00512                       res_OPEN4.status = status4;
00513                       cache_inode_put(pentry_lookup);
00514                       goto out;
00515                     }
00516 
00517                   res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 3;
00518                   if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val =
00519                       gsh_calloc(res_OPEN4.OPEN4res_u.resok4.attrset.
00520                                  bitmap4_len, sizeof(uint32_t))) == NULL)
00521                     {
00522                       res_OPEN4.status = NFS4ERR_RESOURCE;
00523                       res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 0;
00524                       cause2 = " (allocation of bitmap failed)";
00525                       cache_inode_put(pentry_lookup);
00526                       goto out;
00527                     }
00528 
00529                   res_OPEN4.OPEN4res_u.resok4.cinfo.after
00530                        = cache_inode_get_changeid4(pentry_parent);
00531                   res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = FALSE;
00532 
00533                   /* No delegation */
00534                   res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type =
00535                       OPEN_DELEGATE_NONE;
00536 
00537                   /* If server use OPEN_CONFIRM4, set the correct flag */
00538                   P(powner->so_mutex);
00539                   if(powner->so_owner.so_nfs4_owner.so_confirmed == FALSE)
00540                     {
00541                         res_OPEN4.OPEN4res_u.resok4.rflags |=
00542                             OPEN4_RESULT_CONFIRM | OPEN4_RESULT_LOCKTYPE_POSIX;
00543                     }
00544                   else
00545                     {
00546                         res_OPEN4.OPEN4res_u.resok4.rflags |= OPEN4_RESULT_LOCKTYPE_POSIX ;
00547                     }
00548                   V(powner->so_mutex);
00549 
00550                   if (data->current_entry) {
00551                     cache_inode_put(data->current_entry);
00552                     data->current_entry = NULL;
00553                   }
00554 
00555                   status4 = nfs4_create_fh(data, pentry_lookup, &text);
00556                   if(status4 != NFS4_OK)
00557                     {
00558                       cause2 = text;
00559                       res_OPEN4.status = status4;
00560                       goto out;
00561                     }
00562 
00563                   data->current_entry = pentry_lookup;
00564                   data->current_filetype = REGULAR_FILE;
00565 
00566                   /* regular exit */
00567                   goto out_success;
00568                 }
00569 
00570               /* if open is EXCLUSIVE, but verifier is the same,
00571                  return NFS4_OK (RFC3530 page 173) */
00572               if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4)
00573                 {
00574                   if((pentry_lookup != NULL)
00575                      && (pentry_lookup->type == REGULAR_FILE))
00576                     {
00577                       /* Acquire lock to enter critical section on
00578                          this entry */
00579                       pthread_rwlock_rdlock(&pentry_lookup->state_lock);
00580                       glist_for_each(glist,
00581                                      &pentry_lookup->state_list)
00582                         {
00583                           pstate_iterate = glist_entry(glist, state_t,
00584                                                        state_list);
00585 
00586                           /* Check if open_owner is the same */
00587                           if((pstate_iterate->state_type == STATE_TYPE_SHARE)
00588                              && !memcmp(arg_OPEN4.owner.owner.owner_val,
00589                                         pstate_iterate->state_powner
00590                                         ->so_owner_val,
00591                                         pstate_iterate->state_powner
00592                                         ->so_owner_len)
00593                              && !memcmp(pstate_iterate->state_data.share.
00594                                         share_oexcl_verifier,
00595                                         arg_OPEN4.openhow.openflag4_u.how.
00596                                         createhow4_u.createverf,
00597                                         NFS4_VERIFIER_SIZE))
00598                             {
00599 
00600                               /* A former open EXCLUSIVE with same
00601                                  owner and verifier was found, resend
00602                                  it */
00603 
00604                               memset(&(res_OPEN4.OPEN4res_u.resok4
00605                                        .cinfo.after), 0, sizeof(changeid4));
00606                               res_OPEN4.OPEN4res_u.resok4.cinfo.after =
00607                                    cache_inode_get_changeid4(pentry_parent);
00608                               res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = FALSE;
00609 
00610                               /* No delegation */
00611                               res_OPEN4.OPEN4res_u.resok4.delegation
00612                                    .delegation_type = OPEN_DELEGATE_NONE;
00613 
00614                               /* If server use OPEN_CONFIRM4, set the
00615                                  correct flag */
00616                               P(powner->so_mutex);
00617                               if(powner->so_owner.so_nfs4_owner.so_confirmed
00618                                  == FALSE)
00619                                 {
00620                                   res_OPEN4.OPEN4res_u.resok4.rflags |=
00621                                     OPEN4_RESULT_CONFIRM |
00622                                     OPEN4_RESULT_LOCKTYPE_POSIX;
00623                                 }
00624                               else
00625                                 {
00626                                   res_OPEN4.OPEN4res_u.resok4.rflags |=
00627                                     OPEN4_RESULT_LOCKTYPE_POSIX;
00628                                 }
00629                               V(powner->so_mutex);
00630 
00631                               if (data->current_entry) {
00632                                   cache_inode_put(data->current_entry);
00633                                   data->current_entry = NULL;
00634                               }
00635 
00636                               status4 = nfs4_create_fh(data,
00637                                                        pentry_lookup,
00638                                                        &text);
00639                               if(status4 != NFS4_OK)
00640                                 {
00641                                   cause2 = text;
00642                                   res_OPEN4.status = status4;
00643                                   pthread_rwlock_unlock(&pentry_lookup
00644                                                         ->state_lock);
00645                                   goto out;
00646                                 }
00647 
00648                               data->current_entry = pentry_lookup;
00649                               data->current_filetype = REGULAR_FILE;
00650 
00651                               /* Avoid segfault during test OPEN4
00652                                  (pstate would be NULL) */
00653                               pfile_state = pstate_iterate;
00654 
00655                               /* regular exit */
00656                               pthread_rwlock_unlock(&pentry_lookup
00657                                                     ->state_lock);
00658                               goto out_success;
00659                             }
00660                         }
00661                       pthread_rwlock_unlock(&pentry_lookup->state_lock);
00662                     }
00663                 }
00664 
00665               /* Managing GUARDED4 mode */
00666               if(cache_status != CACHE_INODE_SUCCESS)
00667                 res_OPEN4.status = nfs4_Errno(cache_status);
00668               else
00669                 res_OPEN4.status = NFS4ERR_EXIST; /* File already exists */
00670 
00671               cause2 = "GUARDED4";
00672               cache_inode_put(pentry_lookup);
00673               goto out;
00674             }
00675 
00676           LogFullDebug(COMPONENT_STATE,
00677                        "    OPEN open.how = %d",
00678                        arg_OPEN4.openhow.openflag4_u.how.mode);
00679 
00680           /* Create the file, if we reach this point, it does not
00681              exist, we can create it */
00682           if((pentry_newfile
00683               = cache_inode_create(pentry_parent,
00684                                    &filename,
00685                                    REGULAR_FILE,
00686                                    mode,
00687                                    NULL,
00688                                    &attr_newfile,
00689                                    data->pcontext,
00690                                    &cache_status)) == NULL)
00691             {
00692               /* If the file already exists, this is not an error if
00693                  open mode is UNCHECKED */
00694               if(cache_status != CACHE_INODE_ENTRY_EXISTS)
00695                 {
00696                   res_OPEN4.status = nfs4_Errno(cache_status);
00697                   cause2 = " UNCHECKED cache_inode_create";
00698                   goto out;
00699                 }
00700               else
00701                 {
00702                   /* If this point is reached, then something has
00703                      gone wrong.  The only way cache_inode_create()
00704                      returns NULL with CACHE_INODE_ENTRY_EXISTS
00705                      is if the entry->type != REGULAR_FILE. */
00706                   res_OPEN4.status = NFS4ERR_EXIST;
00707                   cause2 = " not a REGULAR file";
00708                   goto out;
00709                 }
00710             }
00711           cache_status = CACHE_INODE_SUCCESS;
00712 
00713           if(AttrProvided == TRUE)      /* Set the attribute if provided */
00714             {
00715               if((cache_status
00716                   = cache_inode_setattr(pentry_newfile,
00717                                         &sattr,
00718                                         data->pcontext,
00719                                         &cache_status)) !=
00720                  CACHE_INODE_SUCCESS)
00721                 {
00722                   res_OPEN4.status = nfs4_Errno(cache_status);
00723                   cause2 = " cache_inode_setattr";
00724                   cache_inode_put(pentry_newfile);
00725                   goto out;
00726                 }
00727             }
00728 
00729           pthread_rwlock_wrlock(&pentry_newfile->state_lock);
00730           status4 = nfs4_do_open(op, data, pentry_newfile, pentry_parent,
00731               powner, &pfile_state, &filename, openflags, &text);
00732           pthread_rwlock_unlock(&pentry_newfile->state_lock);
00733           if (status4 != NFS4_OK)
00734             {
00735               cause2 = text;
00736               res_OPEN4.status = status4;
00737               cache_inode_put(pentry_newfile);
00738               goto out;
00739             }
00740 
00741           break;
00742 
00743         case OPEN4_NOCREATE:
00744           /* It was not a creation, but a regular open */
00745           cause = "OPEN4_NOCREATE";
00746 
00747           /* Does a file with this name already exist ? */
00748           if((pentry_newfile
00749               = cache_inode_lookup(pentry_parent,
00750                                    &filename,
00751                                    &attr_newfile,
00752                                    data->pcontext,
00753                                    &cache_status)) == NULL)
00754             {
00755                res_OPEN4.status = nfs4_Errno(cache_status);
00756                cause2 = " cache_inode_lookup";
00757                goto out;
00758             }
00759 
00760           /* OPEN4 is to be done on a file */
00761           if(pentry_newfile->type != REGULAR_FILE)
00762             {
00763               cache_inode_put(pentry_newfile);
00764               if(pentry_newfile->type == DIRECTORY)
00765                 {
00766                   res_OPEN4.status = NFS4ERR_ISDIR;
00767                   goto out;
00768                 }
00769               else
00770                 {
00771                   res_OPEN4.status = NFS4ERR_SYMLINK;
00772                   goto out;
00773                 }
00774             }
00775 
00776           status4 = nfs4_chk_shrdny(op, data, pentry_newfile, read_access,
00777               write_access, &openflags, FALSE, NULL, resp);
00778           if (status4 != NFS4_OK)
00779             {
00780               cause2 = " cache_inode_access";
00781               res_OPEN4.status = status4;
00782               cache_inode_put(pentry_newfile);
00783               goto out;
00784             }
00785 
00786 #ifdef WITH_MODE_0_CHECK
00787           /* If file mode is 000 then NFS4ERR_ACCESS should be
00788              returned for all cases and users */
00789           if(attr_newfile.mode == 0)
00790             {
00791               res_OPEN4.status = NFS4ERR_ACCESS;
00792               cause2 = " (mode is 0)";
00793               goto out;
00794             }
00795 #endif
00796 
00797           pthread_rwlock_wrlock(&pentry_newfile->state_lock);
00798           /* Try to find if the same open_owner already has acquired a
00799              stateid for this file */
00800           glist_for_each(glist, &pentry_newfile->state_list)
00801             {
00802               pstate_iterate = glist_entry(glist, state_t, state_list);
00803 
00804               // TODO FSF: currently only care about share types
00805               if(pstate_iterate->state_type != STATE_TYPE_SHARE)
00806                 continue;
00807 
00808               /* Check is open_owner is the same */
00809               if((pstate_iterate->state_powner->so_owner.so_nfs4_owner
00810                   .so_clientid == arg_OPEN4.owner.clientid) &&
00811                  ((pstate_iterate->state_powner->so_owner_len ==
00812                    arg_OPEN4.owner.owner.owner_len) &&
00813                   (!memcmp(arg_OPEN4.owner.owner.owner_val,
00814                            pstate_iterate->state_powner->so_owner_val,
00815                            pstate_iterate->state_powner->so_owner_len))))
00816                 {
00817                   /* We'll be re-using the found state */
00818                   pfile_state = pstate_iterate;
00819                   ReuseState  = TRUE;
00820                 }
00821               else
00822                 {
00823                   /* This is a different owner, check for possible conflicts */
00824                   if((pstate_iterate->state_data.share.share_access &
00825                       OPEN4_SHARE_ACCESS_WRITE)
00826                      && (arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE))
00827                     {
00828                       res_OPEN4.status = NFS4ERR_SHARE_DENIED;
00829                       cause2 = " (OPEN4_SHARE_DENY_WRITE)";
00830                       pthread_rwlock_unlock(&pentry_newfile->state_lock);
00831                       cache_inode_put(pentry_newfile);
00832                       goto out;
00833                     }
00834                 }
00835 
00836               /* In all cases opening in read access a read denied
00837                * file or write access to a write denied file should
00838                * fail, even if the owner is the same, see discussion
00839                * in 14.2.16 and 8.9
00840                */
00841 
00842               /* deny read access on read denied file */
00843               if((pstate_iterate->state_data.share.share_deny &
00844                   OPEN4_SHARE_DENY_READ)
00845                  && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ))
00846                 {
00847                   res_OPEN4.status = NFS4ERR_SHARE_DENIED;
00848                   cause2 = " (OPEN4_SHARE_ACCESS_READ)";
00849                   pthread_rwlock_unlock(&pentry_newfile->state_lock);
00850                   cache_inode_put(pentry_newfile);
00851                   goto out;
00852                 }
00853 
00854               /* deny write access on write denied file */
00855               if((pstate_iterate->state_data.share.share_deny &
00856                   OPEN4_SHARE_DENY_WRITE)
00857                  && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE))
00858                 {
00859                   res_OPEN4.status = NFS4ERR_SHARE_DENIED;
00860                   cause2 = " (OPEN4_SHARE_ACCESS_WRITE)";
00861                   pthread_rwlock_unlock(&pentry_newfile->state_lock);
00862                   cache_inode_put(pentry_newfile);
00863                   goto out;
00864                 }
00865             }
00866 
00867           status4 = nfs4_do_open(op, data, pentry_newfile, pentry_parent,
00868               powner, &pfile_state, &filename, openflags, &text);
00869           pthread_rwlock_unlock(&pentry_newfile->state_lock);
00870           if (status4 != NFS4_OK)
00871             {
00872               cause2 = text;
00873               res_OPEN4.status = status4;
00874               cache_inode_put(pentry_newfile);
00875               goto out;
00876             }
00877           break;
00878 
00879         default:
00880           cause = "INVALID OPEN TYPE";
00881           res_OPEN4.status = NFS4ERR_INVAL;
00882           goto out;
00883         }
00884 
00885       break;
00886 
00887     case CLAIM_PREVIOUS:
00888       powner->so_owner.so_nfs4_owner.so_confirmed = TRUE;
00889 
00890       /* pentry_parent is actually the file to be reclaimed, not the parent */
00891       pentry_newfile = pentry_parent;
00892       pthread_rwlock_wrlock(&pentry_newfile->state_lock);
00893       status4 = nfs4_do_open(op, data, pentry_newfile, NULL, powner,
00894           &pfile_state, NULL, openflags, &text);
00895       pthread_rwlock_unlock(&pentry_newfile->state_lock);
00896       if (status4 != NFS4_OK)
00897         {
00898           cause2 = text;
00899           res_OPEN4.status = status4;
00900           goto out;
00901         }
00902       goto out_prev;
00903 
00904     case CLAIM_DELEGATE_CUR:
00905     case CLAIM_DELEGATE_PREV:
00906       /* Check for name length */
00907       if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN)
00908         {
00909           res_OPEN4.status = NFS4ERR_NAMETOOLONG;
00910           LogDebug(COMPONENT_STATE,
00911                    "NFS4 OPEN returning NFS4ERR_NAMETOOLONG "
00912                    "for CLAIM_DELEGATE");
00913           dec_client_id_ref(pclientid);
00914           return res_OPEN4.status;
00915         }
00916 
00917       /* get the filename from the argument, it should not be empty */
00918       if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0)
00919         {
00920           res_OPEN4.status = NFS4ERR_INVAL;
00921           LogDebug(COMPONENT_STATE,
00922                    "NFS4 OPEN returning NFS4ERR_INVAL for CLAIM_DELEGATE");
00923           dec_client_id_ref(pclientid);
00924           return res_OPEN4.status;
00925         }
00926 
00927       res_OPEN4.status = NFS4ERR_NOTSUPP;
00928       LogDebug(COMPONENT_STATE,
00929                "NFS4 OPEN returning NFS4ERR_NOTSUPP for CLAIM_DELEGATE");
00930       dec_client_id_ref(pclientid);
00931       return res_OPEN4.status;
00932 
00933     default:
00934       /* Invalid claim type */
00935       cause = "INVALID CLAIM";
00936       res_OPEN4.status = NFS4ERR_INVAL;
00937       goto out;
00938     }                           /*  switch(  arg_OPEN4.claim.claim ) */
00939 
00940   /* Decrement the current entry here, because nfs4_create_fh
00941      replaces the current fh. */
00942   if (data->current_entry) {
00943       cache_inode_put(data->current_entry);
00944       data->current_entry = NULL;
00945   }
00946   status4 = nfs4_create_fh(data, pentry_newfile, &text);
00947   if(status4 != NFS4_OK)
00948     {
00949       cause2 = text;
00950       res_OPEN4.status = status4;
00951       goto out;
00952     }
00953 
00954   /* Status of parent directory after the operation */
00955   if((cache_status = cache_inode_getattr(pentry_parent,
00956                                          &attr_parent,
00957                                          data->pcontext,
00958                                          &cache_status))
00959      != CACHE_INODE_SUCCESS)
00960     {
00961       res_OPEN4.status = nfs4_Errno(cache_status);
00962       cause2 = " cache_inode_getattr";
00963       goto out;
00964     }
00965 
00966 out_prev:
00967 
00968   res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 3;
00969   if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val =
00970       gsh_calloc(res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len,
00971                  sizeof(uint32_t))) == NULL)
00972     {
00973       res_OPEN4.status = NFS4ERR_SERVERFAULT;
00974       res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 0;
00975       cause2 = " (allocation of attr failed)";
00976       goto out;
00977     }
00978 
00979   if(arg_OPEN4.openhow.opentype == OPEN4_CREATE)
00980     {
00981       tmp_attr[0] = FATTR4_SIZE;
00982       tmp_attr[1] = FATTR4_MODE;
00983       nfs4_list_to_bitmap4(&(res_OPEN4.OPEN4res_u.resok4.attrset), 2, tmp_attr);
00984     }
00985 
00986   res_OPEN4.OPEN4res_u.resok4.cinfo.after
00987        = cache_inode_get_changeid4(pentry_parent);
00988   res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = FALSE;
00989 
00990   /* No delegation */
00991   res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type |= OPEN_DELEGATE_NONE;
00992 
00993   /* If server use OPEN_CONFIRM4, set the correct flag */
00994   if(powner->so_owner.so_nfs4_owner.so_confirmed == FALSE)
00995     {
00996       res_OPEN4.OPEN4res_u.resok4.rflags |=
00997         OPEN4_RESULT_CONFIRM | OPEN4_RESULT_LOCKTYPE_POSIX;
00998     }
00999   else
01000     {
01001       res_OPEN4.OPEN4res_u.resok4.rflags |= OPEN4_RESULT_LOCKTYPE_POSIX ;
01002     }
01003 
01004  out_success:
01005 
01006   LogFullDebug(COMPONENT_STATE, "NFS4 OPEN returning NFS4_OK");
01007 
01008   /* regular exit */
01009   res_OPEN4.status = NFS4_OK;
01010 
01011   /* Handle stateid/seqid for success */
01012   update_stateid(pfile_state,
01013                  &res_OPEN4.OPEN4res_u.resok4.stateid,
01014                  data,
01015                  tag);
01016 
01017   /* If we are re-using stateid, then release extra reference to open owner */
01018   if(ReuseState)
01019     dec_state_owner_ref(powner);
01020 
01021  out:
01022 
01023   /* Save the response in the lock or open owner */
01024   Copy_nfs4_state_req(powner, arg_OPEN4.seqid, op, data, resp, tag);
01025 
01026  out2:
01027 
01028   /* Update the lease before exit */
01029   P(pclientid->cid_mutex);
01030 
01031   update_lease(pclientid);
01032 
01033   V(pclientid->cid_mutex);
01034 
01035   dec_client_id_ref(pclientid);
01036 
01037  out3:
01038 
01039   if(res_OPEN4.status != NFS4_OK)
01040     {
01041       const char *cause3 = "", *cause4 = "";
01042 
01043       if(cache_status != CACHE_INODE_SUCCESS)
01044         {
01045           cause3 = " returned ";
01046           cause4 = cache_inode_err_str(cache_status);
01047         }
01048 
01049       LogDebug(COMPONENT_STATE,
01050                "NFS4 OPEN returning %s for %s%s%s%s",
01051                nfsstat4_to_str(res_OPEN4.status),
01052                cause, cause2, cause3, cause4);
01053 
01054       /* Clean up if we have an error exit */
01055       if(pfile_state != NULL && !ReuseState)
01056         {
01057           /* Need to destroy open owner and state */
01058           if(state_del(pfile_state,
01059                        &state_status) != STATE_SUCCESS)
01060             LogDebug(COMPONENT_NFS_V4_LOCK,
01061                      "state_del failed with status %s",
01062                      state_err_str(state_status));
01063         }
01064       else if(powner != NULL)
01065         {
01066           /* Need to release the open owner */
01067           dec_state_owner_ref(powner);
01068         }
01069     }
01070 
01071   return res_OPEN4.status;
01072 }                               /* nfs4_op_open */
01073 
01084 void nfs4_op_open_Free(OPEN4res * resp)
01085 {
01086   if(resp->OPEN4res_u.resok4.attrset.bitmap4_val != NULL)
01087     gsh_free(resp->OPEN4res_u.resok4.attrset.bitmap4_val);
01088   resp->OPEN4res_u.resok4.attrset.bitmap4_len = 0;
01089 }                               /* nfs4_op_open_Free */
01090 
01091 void nfs4_op_open_CopyRes(OPEN4res * resp_dst, OPEN4res * resp_src)
01092 {
01093   if(resp_src->OPEN4res_u.resok4.attrset.bitmap4_val != NULL)
01094     {
01095       if((resp_dst->OPEN4res_u.resok4.attrset.bitmap4_val =
01096           gsh_calloc(resp_dst->OPEN4res_u.resok4.attrset.bitmap4_len,
01097                      sizeof(uint32_t))) == NULL)
01098         {
01099           resp_dst->OPEN4res_u.resok4.attrset.bitmap4_len = 0;
01100         }
01101     }
01102 }
01103 
01104 static nfsstat4
01105 nfs4_chk_shrdny(struct nfs_argop4 *op, compound_data_t *data,
01106     cache_entry_t *pentry, fsal_accessflags_t rd_acc,
01107     fsal_accessflags_t wr_acc, fsal_openflags_t *openflags,
01108     bool_t AttrProvided, fsal_attrib_list_t *sattr, struct nfs_resop4 *resop)
01109 {
01110         OPEN4args *args = &op->nfs_argop4_u.opopen;
01111         OPEN4res *resp = &resop->nfs_resop4_u.opopen;
01112         cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
01113 
01114         /* If the file is opened for write, OPEN4 while deny share
01115          * write access, in this case, check caller has write access
01116          * to the file */
01117         if(args->share_deny & OPEN4_SHARE_DENY_WRITE) {
01118                 if(cache_inode_access(pentry, wr_acc,
01119                     data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) {
01120                         return NFS4ERR_ACCESS;
01121                 }
01122         }
01123 
01124         /* Same check on read: check for readability of a file before opening
01125          * it for read */
01126         if(args->share_access & OPEN4_SHARE_ACCESS_READ) {
01127                 if(cache_inode_access(pentry, rd_acc,
01128                     data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) {
01129                         return NFS4ERR_ACCESS;
01130                 }
01131         }
01132 
01133         if(AttrProvided == TRUE) {      /* Set the attribute if provided */
01134                 if(cache_inode_setattr(pentry, sattr,
01135                     data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) {
01136                         return nfs4_Errno(cache_status);
01137                 }
01138 
01139                 resp->OPEN4res_u.resok4.attrset =
01140                     args->openhow.openflag4_u.how.createhow4_u.createattrs.
01141                     attrmask;
01142         }
01143         else
01144                 resp->OPEN4res_u.resok4.attrset.bitmap4_len = 0;
01145 
01146         /* Same check on write */
01147         if(args->share_access & OPEN4_SHARE_ACCESS_WRITE) {
01148                 if(cache_inode_access(pentry, wr_acc,
01149                     data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) {
01150                         return NFS4ERR_ACCESS;
01151                 }
01152         }
01153 
01154         return NFS4_OK;
01155 }
01156 
01157 static nfsstat4 nfs4_do_open(struct nfs_argop4  * op,
01158                              compound_data_t    * data,
01159                              cache_entry_t      * pentry_newfile,
01160                              cache_entry_t      * pentry_parent,
01161                              state_owner_t      * powner,
01162                              state_t           ** statep,
01163                              fsal_name_t        * filename,
01164                              fsal_openflags_t     openflags,
01165                              char              ** cause2)
01166 {
01167         OPEN4args *args = &op->nfs_argop4_u.opopen;
01168         state_data_t candidate_data;
01169         state_type_t candidate_type;
01170         state_status_t state_status;
01171         cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
01172         int new_state = 0;
01173 
01174         /* Set the state for the related file */
01175         /* Prepare state management structure */
01176         candidate_type                         = STATE_TYPE_SHARE;
01177         candidate_data.share.share_access      = args->share_access;
01178         candidate_data.share.share_deny        = args->share_deny;
01179         candidate_data.share.share_access_prev = 0;
01180         candidate_data.share.share_deny_prev   = 0;
01181 
01182         /* Quick exit if there is any share conflict */
01183         if(state_share_check_conflict(pentry_newfile,
01184                                       candidate_data.share.share_access,
01185                                       candidate_data.share.share_deny,
01186                                       &state_status) != STATE_SUCCESS)
01187           {
01188             *cause2 = " (share conflict)";
01189             return nfs4_Errno_state(state_status);
01190           }
01191 
01192         if(*statep == NULL) {
01193                 new_state = 1;
01194 
01195                 /* If file is opened under mode EXCLUSIVE4, open verifier
01196                  * should be kept to detect non vicious double open */
01197                 if(args->openhow.openflag4_u.how.mode == EXCLUSIVE4) {
01198                         strncpy(candidate_data.share.share_oexcl_verifier,
01199                           args->openhow.openflag4_u.how.createhow4_u.createverf,
01200                           NFS4_VERIFIER_SIZE);
01201                 }
01202 
01203                 if(state_add_impl(pentry_newfile, candidate_type, &candidate_data,
01204                     powner, data->pcontext, statep,
01205                     &state_status) != STATE_SUCCESS) {
01206                         *cause2 = STATE_ADD;
01207                         return nfs4_Errno_state(state_status);
01208                 }
01209 
01210                 init_glist(&((*statep)->state_data.share.share_lockstates));
01211 
01212                 /* Attach this open to an export */
01213                 (*statep)->state_pexport = data->pexport;
01214                 P(data->pexport->exp_state_mutex);
01215                 glist_add_tail(&data->pexport->exp_state_list,
01216                                &(*statep)->state_export_list);
01217                 V(data->pexport->exp_state_mutex);
01218         } else {
01219           /* Check if open from another export */
01220           if((*statep)->state_pexport != data->pexport)
01221             {
01222               LogEvent(COMPONENT_STATE,
01223                        "Lock Owner Export Conflict, Lock held for export %d (%s), request for export %d (%s)",
01224                        (*statep)->state_pexport->id,
01225                        (*statep)->state_pexport->fullpath,
01226                        data->pexport->id,
01227                        data->pexport->fullpath);
01228               return STATE_INVALID_ARGUMENT;
01229             }
01230         }
01231 
01232         if (pentry_parent != NULL) {    /* claim null */
01233           /* Open the file */
01234           if(cache_inode_open(pentry_newfile, openflags, data->pcontext,
01235                               0, &cache_status) != CACHE_INODE_SUCCESS) {
01236             *cause2 = " cache_inode_open";
01237             return NFS4ERR_ACCESS;
01238           }
01239         } else { /* claim previous */
01240           if (cache_inode_open(pentry_newfile, openflags,
01241                                data->pcontext, 0, &cache_status) != CACHE_INODE_SUCCESS) {
01242             *cause2 = CACHE_INODE_OPEN;
01243             return nfs4_Errno(cache_status);
01244           }
01245         }
01246 
01247         /* Push share state to SAL (and FSAL) and update the union of file
01248          * share state.
01249          */
01250         if(new_state)
01251           {
01252             if(state_share_add(pentry_newfile, data->pcontext, powner, *statep,
01253                                &state_status) != STATE_SUCCESS)
01254               {
01255                 if(cache_inode_close(pentry_newfile,
01256                                      0, &cache_status) != CACHE_INODE_SUCCESS)
01257                   {
01258                     /* Log bad close and continue. */
01259                     LogEvent(COMPONENT_STATE, "Failed to close cache inode: status=%d",
01260                              cache_status);
01261                   }
01262                 *cause2 = STATE_SHARE_ADD;
01263                 return nfs4_Errno_state(state_status);
01264               }
01265           }
01266         else
01267           {
01268             /* If we find the previous share state, update share state. */
01269             if((candidate_type == STATE_TYPE_SHARE) &&
01270                ((*statep)->state_type == STATE_TYPE_SHARE))
01271               {
01272                 LogFullDebug(COMPONENT_STATE, "Update existing share state");
01273                 if(state_share_upgrade(pentry_newfile, data->pcontext,
01274                                        &candidate_data, powner, *statep,
01275                                        &state_status) != STATE_SUCCESS)
01276                   {
01277                     if(cache_inode_close(pentry_newfile,
01278                                          0, &cache_status) != CACHE_INODE_SUCCESS)
01279                       {
01280                         /* Log bad close and continue. */
01281                         LogEvent(COMPONENT_STATE, "Failed to close cache inode: status=%d",
01282                                  cache_status);
01283                       }
01284                     LogEvent(COMPONENT_STATE, "Failed to update existing "
01285                                  "share state");
01286                     *cause2 = STATE_SHARE_UP;
01287                     return nfs4_Errno_state(state_status);
01288                   }
01289               }
01290           }
01291 
01292         return NFS4_OK;
01293 }
01294 
01295 static nfsstat4
01296 nfs4_create_fh(compound_data_t *data, cache_entry_t *pentry, char **cause2)
01297 {
01298         fsal_handle_t *pnewfsal_handle = NULL;
01299         nfs_fh4 newfh4;
01300         struct alloc_file_handle_v4 new_handle;
01301 
01302         newfh4.nfs_fh4_val = (caddr_t) &new_handle;
01303         newfh4.nfs_fh4_len = sizeof(struct alloc_file_handle_v4);
01304 
01305         /* Now produce the filehandle to this file */
01306         pnewfsal_handle = &pentry->handle;
01307 
01308         /* Building a new fh */
01309         if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data)) {
01310                 *cause2 = " (nfs4_FSALToFhandle failed)";
01311                 cache_inode_put(pentry);
01312                 return NFS4ERR_SERVERFAULT;
01313         }
01314 
01315         /* This new fh replaces the current FH */
01316         data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
01317         memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val,
01318             newfh4.nfs_fh4_len);
01319 
01320         data->current_entry = pentry;
01321         data->current_filetype = REGULAR_FILE;
01322 
01323         return NFS4_OK;
01324 }