nfs-ganesha 1.4

nfs41_op_layoutcommit.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 <fcntl.h>
00049 #include <sys/file.h>           /* for having FNDELAY */
00050 #include "HashData.h"
00051 #include "HashTable.h"
00052 #include "log.h"
00053 #include "ganesha_rpc.h"
00054 #include "nfs23.h"
00055 #include "nfs4.h"
00056 #include "mount.h"
00057 #include "nfs_core.h"
00058 #include "cache_inode.h"
00059 #include "nfs_exports.h"
00060 #include "nfs_creds.h"
00061 #include "nfs_proto_functions.h"
00062 #include "nfs_proto_tools.h"
00063 #include "nfs_file_handle.h"
00064 #include "nfs_tools.h"
00065 #ifdef _PNFS_MDS
00066 #include "fsal.h"
00067 #include "fsal_pnfs.h"
00068 #include "sal_data.h"
00069 #include "sal_functions.h"
00070 #endif /* _PNFS_MDS */
00071 
00089 #define arg_LAYOUTCOMMIT4 op->nfs_argop4_u.oplayoutcommit
00090 #define res_LAYOUTCOMMIT4 resp->nfs_resop4_u.oplayoutcommit
00091 
00092 int nfs41_op_layoutcommit(struct nfs_argop4 *op, compound_data_t * data,
00093                           struct nfs_resop4 *resp)
00094 {
00095      char __attribute__ ((__unused__)) funcname[] = "nfs41_op_layoutcommit";
00096 #ifdef _PNFS_MDS
00097      /* Return from cache_inode calls */
00098      cache_inode_status_t cache_status = 0;
00099      /* NFS4 return code */
00100      nfsstat4 nfs_status = 0;
00101      /* State indicated by client */
00102      state_t *layout_state = NULL;
00103      /* Tag for logging in state operations */
00104      const char *tag = "LAYOUTCOMMIT";
00105      /* Iterator along linked list */
00106      struct glist_head *glist = NULL;
00107      /* Input arguments of FSAL_layoutcommit */
00108      struct fsal_layoutcommit_arg arg;
00109      /* Input/output and output arguments of FSAL_layoutcommit */
00110      struct fsal_layoutcommit_res res;
00111      /* The segment being traversed */
00112      state_layout_segment_t *segment;
00113      /* The FSAL handle */
00114      fsal_handle_t *handle = NULL;
00115      /* XDR stream holding the lrf_body opaque */
00116      XDR lou_body;
00117      /* The beginning of the stream */
00118      unsigned int beginning = 0;
00119 #endif /* _PNFS_MDS */
00120 
00121   resp->resop = NFS4_OP_LAYOUTCOMMIT;
00122 
00123 #ifdef _PNFS_MDS
00124      if ((nfs_status = nfs4_sanity_check_FH(data,
00125                                             REGULAR_FILE))
00126          != NFS4_OK) {
00127           goto out;
00128      }
00129 
00130      handle = cache_inode_get_fsal_handle(data->current_entry,
00131                                        &cache_status);
00132 
00133      if (cache_status != CACHE_INODE_SUCCESS) {
00134           nfs_status = nfs4_Errno(cache_status);
00135           goto out;
00136      }
00137 
00138      memset(&arg, 0, sizeof(struct fsal_layoutcommit_arg));
00139      memset(&res, 0, sizeof(struct fsal_layoutcommit_res));
00140 
00141      /* Suggest a new size, if we have it */
00142      if (arg_LAYOUTCOMMIT4.loca_last_write_offset.no_newoffset) {
00143           arg.new_offset = TRUE;
00144           arg.last_write =
00145                arg_LAYOUTCOMMIT4.loca_last_write_offset.newoffset4_u.no_offset;
00146      } else {
00147           arg.new_offset = FALSE;
00148      }
00149 
00150      arg.reclaim = arg_LAYOUTCOMMIT4.loca_reclaim;
00151 
00152      xdrmem_create(&lou_body,
00153                    arg_LAYOUTCOMMIT4.loca_layoutupdate.lou_body.lou_body_val,
00154                    arg_LAYOUTCOMMIT4.loca_layoutupdate.lou_body.lou_body_len,
00155                    XDR_DECODE);
00156 
00157      beginning = xdr_getpos(&lou_body);
00158 
00159      /* Suggest a new modification time if we have it */
00160      if (arg_LAYOUTCOMMIT4.loca_time_modify.nt_timechanged) {
00161           arg.time_changed = TRUE;
00162           arg.new_time.seconds =
00163                arg_LAYOUTCOMMIT4.loca_time_modify.newtime4_u.nt_time.seconds;
00164           arg.new_time.nseconds =
00165                arg_LAYOUTCOMMIT4.loca_time_modify.newtime4_u.nt_time.nseconds;
00166      }
00167 
00168      /* Retrieve state corresponding to supplied ID */
00169 
00170      if ((nfs_status
00171           = nfs4_Check_Stateid(&arg_LAYOUTCOMMIT4.loca_stateid,
00172                                data->current_entry,
00173                                &layout_state,
00174                                data,
00175                                STATEID_SPECIAL_CURRENT,
00176                                tag)) != NFS4_OK) {
00177           goto out;
00178      }
00179 
00180      arg.type = layout_state->state_data.layout.state_layout_type;
00181 
00182      /* Check to see if the layout is valid */
00183 
00184      glist_for_each(glist,
00185                     &layout_state->state_data.layout.state_segments) {
00186           segment = glist_entry(glist,
00187                                 state_layout_segment_t,
00188                                 sls_state_segments);
00189 
00190           pthread_mutex_lock(&segment->sls_mutex);
00191 
00192           /*
00193            * XXX This assumes a single FSAL and must be changed after
00194            * XXX the Lieb Rearchitecture.  The MDS function structure
00195            * XXX associated with the current filehandle should be
00196            * XXX used.
00197            */
00198 
00199           nfs_status
00200                = fsal_mdsfunctions.layoutcommit(handle,
00201                                                 data->pcontext,
00202                                                 &lou_body,
00203                                                 &arg,
00204                                                 &res);
00205 
00206           pthread_mutex_unlock(&segment->sls_mutex);
00207 
00208           if (nfs_status != NFS4_OK) {
00209                goto out;
00210           }
00211 
00212           if (res.commit_done) {
00213                break;
00214           }
00215 
00216           /* This really should work in all cases for an in-memory
00217              decode stream. */
00218           xdr_setpos(&lou_body, beginning);
00219      }
00220 
00221      if (arg_LAYOUTCOMMIT4.loca_time_modify.nt_timechanged ||
00222          arg_LAYOUTCOMMIT4.loca_last_write_offset.no_newoffset ||
00223          res.size_supplied) {
00224           if (cache_inode_kill_entry(data->current_entry))
00225               != CACHE_INODE_SUCCESS) {
00226                nfs_status = nfs4_Errno(cache_status);
00227                goto out;
00228           }
00229      }
00230 
00231      (res_LAYOUTCOMMIT4.LAYOUTCOMMIT4res_u.locr_resok4
00232       .locr_newsize.ns_sizechanged) = res.size_supplied;
00233 
00234      if (res.size_supplied) {
00235           (res_LAYOUTCOMMIT4.LAYOUTCOMMIT4res_u.locr_resok4
00236            .locr_newsize.newsize4_u.ns_size) = res.new_size;
00237      }
00238 
00239      nfs_status = NFS4_OK;
00240 
00241 out:
00242 
00243      xdr_destroy(&lou_body);
00244 
00245      res_LAYOUTCOMMIT4.locr_status = nfs_status;
00246 
00247 #else /* !_PNFS_MDS */
00248      res_LAYOUTCOMMIT4.locr_status = NFS4ERR_NOTSUPP;
00249 #endif /* !_PNFS_MDS */
00250      return res_LAYOUTCOMMIT4.locr_status;
00251 } /* nfs41_op_layoutcommit */
00252 
00263 void nfs41_op_layoutcommit_Free(LOCK4res * resp)
00264 {
00265      return;
00266 }                               /* nfs41_op_layoutcommit_Free */