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 <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 */