nfs-ganesha 1.4

common_pnfs.c

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