nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 * 00004 * Copyright (C) 2011 The Linux Box Corporation 00005 * Author: Adam C. Emerson 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 3 of the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 * 00021 * --------------------------------------- 00022 */ 00023 00024 #ifdef HAVE_CONFIG_H 00025 #include "config.h" 00026 #endif 00027 00028 #include <sys/types.h> 00029 #include <stdint.h> 00030 #include <stddef.h> 00031 #include <stdlib.h> 00032 #include <errno.h> 00033 #include <string.h> 00034 #include <pthread.h> 00035 #include <sys/quota.h> 00036 #include "log.h" 00037 #include "fsal.h" 00038 #include "fsal_pnfs.h" 00039 #include "pnfs_common.h" 00040 #include "fsal_pnfs_files.h" 00041 #include "nfs4.h" 00042 #include "cache_inode.h" 00043 #include "nfs_exports.h" 00044 #include "nfs_file_handle.h" 00045 #include "nfs_proto_functions.h" 00046 00056 #ifdef _PNFS_MDS 00057 00058 /* 00059 * Functions potentially useful to all MDSs of layout types 00060 */ 00061 00079 bool_t 00080 xdr_fsal_deviceid(XDR *xdrs, struct pnfs_deviceid *deviceid) 00081 { 00082 if(!xdr_uint64_t(xdrs, &deviceid->export_id)) { 00083 return FALSE; 00084 } 00085 if(!xdr_uint64_t(xdrs, &deviceid->devid)) { 00086 return FALSE; 00087 } 00088 return TRUE; 00089 } 00090 00108 nfsstat4 00109 FSAL_encode_ipv4_netaddr(XDR *xdrs, 00110 uint16_t proto, 00111 uint32_t addr, 00112 uint16_t port) 00113 { 00114 char* mark = NULL; 00115 /* Six groups of up to three digits each, five dots, and a null */ 00116 #define V4_ADDRBUFF_LEN 24 00117 /* The buffer to which we output the string form of the address */ 00118 char addrbuff[24]; 00119 /* Pointer to the beginning of the buffer, the reference of which 00120 is passed to xdr_string */ 00121 char *buffptr = &addrbuff[0]; 00122 /* Return value from snprintf to check for overflow or error */ 00123 size_t written_length = 0; 00124 00125 /* First, we output the correct netid for the protocol */ 00126 00127 switch (proto) { 00128 case 6: 00129 mark = "tcp"; 00130 break; 00131 00132 case 17: 00133 mark = "udp"; 00134 break; 00135 00136 case 123: 00137 mark = "sctp"; 00138 00139 default: 00140 LogCrit(COMPONENT_FSAL, 00141 "Caller supplied invalid protocol %u", 00142 proto); 00143 return NFS4ERR_SERVERFAULT; 00144 } 00145 00146 if (!xdr_string(xdrs, &mark, 5)) { 00147 LogCrit(COMPONENT_FSAL, 00148 "Unable to encode protocol mark."); 00149 return NFS4ERR_SERVERFAULT; 00150 } 00151 00152 /* Then we convert the address and port to a string and encode it. */ 00153 00154 written_length 00155 = snprintf(addrbuff, 00156 V4_ADDRBUFF_LEN, 00157 "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", 00158 ((addr & 0xff000000) >> 0x18), 00159 ((addr & 0x00ff0000) >> 0x10), 00160 ((addr & 0x0000ff00) >> 0x08), 00161 (addr & 0x000000ff), 00162 ((port & 0xff00) >> 0x08), 00163 (port & 0x00ff)); 00164 if (written_length >= V4_ADDRBUFF_LEN) { 00165 LogCrit(COMPONENT_FSAL, 00166 "Programming error in FSAL_encode_ipv4_netaddr " 00167 "defined in src/FSAL/common_pnfs.c causing " 00168 "snprintf to overflow address buffer."); 00169 return NFS4ERR_SERVERFAULT; 00170 } 00171 00172 if (!xdr_string(xdrs, &buffptr, V4_ADDRBUFF_LEN)) { 00173 LogCrit(COMPONENT_FSAL, 00174 "Unable to encode address."); 00175 return NFS4ERR_SERVERFAULT; 00176 } 00177 00178 return NFS4_OK; 00179 } 00180 #endif /* _PNFS_MDS */ 00181 00182 #ifdef _PNFS_MDS 00183 00184 /* 00185 * Functions specific to NFSV4_1_FILES layouts 00186 */ 00187 00204 static nfsstat4 00205 make_file_handle_v4(fsal_handle_t *fsal_handle, 00206 unsigned short export_id, 00207 fsal_export_context_t *export, 00208 nfs_fh4 *wirehandle) 00209 { 00210 /* Return code from FSAL functions */ 00211 fsal_status_t fsal_status = {0, 0}; 00212 /* We only use this to convert the FSAL error code */ 00213 cache_inode_status_t cache_status = 0; 00214 struct fsal_handle_desc fh_desc; 00215 file_handle_v4_t *v4_handle = (file_handle_v4_t *)wirehandle->nfs_fh4_val; 00216 00217 wirehandle->wirehandle->nfs_fh4_len = sizeof(struct alloc_file_handle_v4); 00218 memset(wirehandle->wirehandle->nfs_fh4_val, 00219 0, 00220 wirehandle->wirehandle->nfs_fh4_len); 00221 fh_desc.start = wirehandle->nfs_fh4_val; 00222 fh_desc.len = wirehandle->nfs_fh4_len - offsetof(file_handle_v4_t, fsopaque); 00223 00224 fsal_status = 00225 FSAL_DigestHandle(export, FSAL_DIGEST_NFSV4, fsal_handle, 00226 &fh_desc); 00227 00228 if (FSAL_IS_ERROR(fsal_status)) { 00229 cache_status = cache_inode_error_convert(fsal_status); 00230 return nfs4_Errno(cache_status); 00231 } 00232 00233 v4_handle->fhversion = GANESHA_FH_VERSION; 00234 v4_handle->fs_len = fh_desc.len; 00235 v4_handle->exportid = export_id; 00236 v4_handle->ds_flag = 1; 00237 00238 return NFS4_OK; 00239 } 00240 00259 nfsstat4 00260 FSAL_fh4_dshandle(fsal_handle_t *fsal_handle, 00261 unsigned short export_id, 00262 fsal_export_context_t *export, 00263 nfs_fh4 *wirehandle) 00264 { 00265 return make_file_handle_v4( 00266 fsal_handle, 00267 export_id, 00268 export, 00269 wirehandle); 00270 } 00271 00295 nfsstat4 00296 FSAL_encode_file_layout(XDR *xdrs, 00297 fsal_op_context_t *context, 00298 const struct pnfs_deviceid *deviceid, 00299 nfl_util4 util, 00300 uint32_t first_idx, 00301 offset4 ptrn_ofst, 00302 uint32_t num_fhs, 00303 fsal_handle_t *fhs) 00304 { 00305 /* Index for traversing FH array */ 00306 size_t i = 0; 00307 /* NFS status code */ 00308 nfsstat4 nfs_status = 0; 00309 00310 if (!xdr_fsal_deviceid(xdrs, (struct pnfs_deviceid *)deviceid)) { 00311 LogMajor(COMPONENT_PNFS, "Failed encoding deviceid."); 00312 return NFS4ERR_SERVERFAULT; 00313 } 00314 00315 if (!xdr_nfl_util4(xdrs, &util)) { 00316 LogMajor(COMPONENT_PNFS, "Failed encoding nfl_util4."); 00317 return NFS4ERR_SERVERFAULT; 00318 } 00319 00320 if (!xdr_uint32_t(xdrs, &first_idx)) { 00321 LogMajor(COMPONENT_PNFS, "Failed encoding first_stripe_index."); 00322 return NFS4ERR_SERVERFAULT; 00323 } 00324 00325 if (!xdr_offset4(xdrs, &ptrn_ofst)) { 00326 LogMajor(COMPONENT_PNFS, "Failed encoding pattern_offset."); 00327 return NFS4ERR_SERVERFAULT; 00328 } 00329 00330 if (!xdr_uint32_t(xdrs, &num_fhs)) { 00331 LogMajor(COMPONENT_PNFS, "Failed encoding length of FH array."); 00332 return NFS4ERR_SERVERFAULT; 00333 } 00334 00335 for (i = 0; i < num_fhs; i++) { 00336 /* Temporary external handle that hodls the converted handle before 00337 encoding */ 00338 struct alloc_file_handle_v4 temphandle; 00339 nfs_fh4 handle; 00340 00341 handle.nfs_fh4_val = (caddr_t) &temphandle; 00342 handle.nfs_fh4_len = sizeof(temphandle); 00343 memset(handle.nfs_fh4_val, 0, handle.nfs_fh4_len); 00344 00345 if ((nfs_status 00346 = make_file_handle_v4(fhs + i, 00347 deviceid->export_id, 00348 context->export_context, 00349 &handle)) != NFS4_OK) { 00350 LogMajor(COMPONENT_PNFS, 00351 "Failed converting FH %lu.", i); 00352 return nfs_status; 00353 } 00354 00355 if (!xdr_bytes(xdrs, (char **)&handle.nfs_fh4_val, 00356 &handle.nfs_fh4_len, 00357 handle.nfs_fh4_len)) { 00358 LogMajor(COMPONENT_PNFS, 00359 "Failed encoding FH %lu.", i); 00360 return NFS4ERR_SERVERFAULT; 00361 } 00362 } 00363 00364 return NFS4_OK; 00365 } 00366 00381 nfsstat4 00382 FSAL_encode_v4_multipath(XDR *xdrs, 00383 uint32_t num_hosts, 00384 fsal_multipath_member_t *hosts) 00385 { 00386 /* Index for traversing host array */ 00387 size_t i = 0; 00388 /* NFS status */ 00389 nfsstat4 nfs_status = 0; 00390 00391 if (!xdr_uint32_t(xdrs, &num_hosts)) { 00392 LogMajor(COMPONENT_PNFS, "Failed encoding length of FH array."); 00393 return NFS4ERR_SERVERFAULT; 00394 } 00395 00396 for (i = 0; i < num_hosts; i++) { 00397 if ((nfs_status 00398 = FSAL_encode_ipv4_netaddr(xdrs, 00399 hosts[i].proto, 00400 hosts[i].addr, 00401 hosts[i].port)) 00402 != NFS4_OK) { 00403 return nfs_status; 00404 } 00405 } 00406 00407 return NFS4_OK; 00408 } 00409 #endif /* _PNFS_MDS */ 00410 00421 nfsstat4 00422 posix2nfs4_error(int posix_errorcode) 00423 { 00424 switch (posix_errorcode) { 00425 case EPERM: 00426 return NFS4ERR_PERM; 00427 00428 case ENOENT: 00429 return NFS4ERR_NOENT; 00430 00431 /* connection error */ 00432 #ifdef _AIX_5 00433 case ENOCONNECT: 00434 #elif defined _LINUX 00435 case ECONNREFUSED: 00436 case ECONNABORTED: 00437 case ECONNRESET: 00438 #endif 00439 00440 /* IO error */ 00441 case EIO: 00442 00443 /* too many open files */ 00444 case ENFILE: 00445 case EMFILE: 00446 00447 /* broken pipe */ 00448 case EPIPE: 00449 00450 /* all shown as IO errors */ 00451 return NFS4ERR_IO; 00452 00453 /* no such device */ 00454 case ENODEV: 00455 case ENXIO: 00456 return NFS4ERR_NXIO; 00457 00458 /* invalid file descriptor : */ 00459 case EBADF: 00460 return NFS4ERR_OPENMODE; 00461 00462 case ENOMEM: 00463 return NFS4ERR_SERVERFAULT; 00464 00465 case EACCES: 00466 return NFS4ERR_ACCESS; 00467 00468 case EFAULT: 00469 return NFS4ERR_SERVERFAULT; 00470 00471 case EEXIST: 00472 return NFS4ERR_EXIST; 00473 00474 case EXDEV: 00475 return NFS4ERR_XDEV; 00476 00477 case ENOTDIR: 00478 return NFS4ERR_NOTDIR; 00479 00480 case EISDIR: 00481 return NFS4ERR_ISDIR; 00482 00483 case EINVAL: 00484 return NFS4ERR_INVAL; 00485 00486 case EFBIG: 00487 return NFS4ERR_FBIG; 00488 00489 case ENOSPC: 00490 return NFS4ERR_NOSPC; 00491 00492 case EMLINK: 00493 return NFS4ERR_MLINK; 00494 00495 case EDQUOT: 00496 return NFS4ERR_DQUOT; 00497 00498 case ENAMETOOLONG: 00499 return NFS4ERR_NAMETOOLONG; 00500 00507 #ifdef _AIX 00508 case 87: 00509 #else 00510 case ENOTEMPTY: 00511 #endif 00512 return NFS4ERR_NOTEMPTY; 00513 00514 case ESTALE: 00515 return NFS4ERR_STALE; 00516 00517 /* Error code that needs a retry */ 00518 case EAGAIN: 00519 case EBUSY: 00520 return NFS4ERR_DELAY; 00521 00522 case ENOTSUP: 00523 return NFS4ERR_NOTSUPP; 00524 00525 default: 00526 00527 /* other unexpected errors */ 00528 return NFS4ERR_SERVERFAULT; 00529 } 00530 } 00531 00532 /* Glue */ 00533 00534 #ifdef _PNFS_MDS 00535 fsal_mdsfunctions_t fsal_mdsfunctions; 00536 #endif /* _PNFS_MDS */ 00537 #ifdef _PNFS_DS 00538 fsal_dsfunctions_t fsal_dsfunctions; 00539 #endif /* _PNFS_DS */ 00540 00541 #ifdef _PNFS_MDS 00542 void FSAL_LoadMDSFunctions(void) 00543 { 00544 fsal_mdsfunctions = FSAL_GetMDSFunctions(); 00545 } 00546 #endif /* _PNFS_MDS */ 00547 #ifdef _PNFS_DS 00548 void FSAL_LoadDSFunctions(void) 00549 { 00550 fsal_dsfunctions = FSAL_GetDSFunctions(); 00551 } 00552 #endif /* _PNFS_DS */