/*************************************************************************** * * Copyright (C) 2001 International Business Machines * All rights reserved. * * This file is part of the GPFS mmfslinux kernel module. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *************************************************************************** */ /* @(#)65 1.116.1.3 src/avs/fs/mmfs/ts/kernext/ibm-linux/cxiSystem-plat.h, mmfs, avs_rgpfs24, rgpfs24s007a 10/25/06 17:52:33 */ /* * Interface definitions for basic common services, Linux version * * Contents: * cxiGetThreadId - get thread identifier * cxiUiomove - transfer data between kernel buffer and user buffer(s) * cxiCopyIn - copy data from user to kernel buffer (kernel service) * cxiCopyOut - copy data from kernel to user buffer (kernel service) * cxiCopyInstr - copy string from user to kernel space (kernel service) * */ #ifndef _h_cxiSystem_plat #define _h_cxiSystem_plat #ifndef _h_cxiSystem #error Platform header (XXX-plat.h) should not be included directly #endif /* Size of stack to allocate for GPFS threads */ #ifdef GPFS_ARCH_I386 #define GPFS_STACK_SIZE (256*1024UL) #endif /* GPFS_ARCH_I386 */ #ifdef GPFS_ARCH_POWER #define GPFS_STACK_SIZE (256*1024UL) #endif /* GPFS_ARCH_POWER */ #ifdef GPFS_ARCH_IA64 #define GPFS_STACK_SIZE (512*1024UL) #endif /* GPFS_ARCH_IA64 */ #ifdef GPFS_ARCH_PPC64 #define GPFS_STACK_SIZE (512*1024UL) #endif /* GPFS_ARCH_POWER */ #ifdef GPFS_ARCH_X86_64 #define GPFS_STACK_SIZE (512*1024UL) #endif /* GPFS_ARCH_POWER */ /* -------------------------------------------------------------- */ /* Interfaces usable from both kernel code and process-level code */ /* -------------------------------------------------------------- */ /* Main module device name */ #define GPFS_DEVNAME "/dev/ss0" /* Virtual memory page size. Used for aligning I/O buffers. */ /* NOTE: Shark-gpl.h grabs PAGE_SIZE for the portability layer */ #if !defined(GPFS_GPL) #ifdef GPFS_LINUX #if defined(GPFS_ARCH_IA64) /* Note that the page size can be adjusted in the IA64 Linux kernel */ /* Newer tool chain uses getpagesize() for PAGE_SIZE, which is a problem */ #define PAGE_SIZE 16384UL #else #include /* PAGE_SIZE */ #endif #if defined(GPFS_ARCH_POWER) || defined(GPFS_ARCH_PPC64) #ifndef PAGE_SIZE #define PAGE_SIZE 4096UL #endif #endif #endif /* GPFS_LINUX */ #endif /* !GPFS_GPL */ /* Process operations */ #if !defined(GPFS_GPL) EXTERNC pid_t getpid() __THROW; #else /* use of THROW causes conflicts in portability kernel code */ EXTERNC pid_t getpid(); #endif /* !GPFS_GPL */ /* Get the kernel thread ID, which is guaranteed to be non-zero. In a * process, this just calls getpid. Within the kernel, this calls a routine * that extracts the process ID from the current process block. */ #define MAX_GPFS_KERNEL_TID 32767 /* max kernel thread id (2^15 - 1) */ #ifdef _KERNEL EXTERNC cxiThreadId cxiGetThreadId(); EXTERNC UIntPtr cxiGetKernelStackSize(); EXTERNC int cxiInitVFS(int vfsType); #define cxiTermVFS() #else /* not _KERNEL */ #include #ifndef NPTL #define cxiGetTid() ((cxiThreadId)getpid()) /* Ensure that user cxiGetThreadId generates an id that is disjoint from * the kernel thread ids (current->pid) which range up to MAX_GPFS_KERNEL_TID. * A mask is applied to the thread id to remove it from this range; the * mask is chosen so that it is compatible with THREAD_OWNER_METHOD_THREADID * and the use of the upper 2 bits for mutex operations. */ #define GPFS_PTID_MASK 0x20000000 /* pthread id/handle mask */ #define cxiGetThreadId() ((cxiThreadId)(pthread_self() | GPFS_PTID_MASK)) #else EXTERNC cxiThreadId kxGetThreadID(); EXTERNC int kxGetTimeOfDay(cxiTimeStruc_t *tP); /* sys_gettid is defined in kernel, but sys call not implemented in glibc, so use our own ioctl with kxGetThreadID */ #define cxiGetTid() (kxGetThreadID()) /* cxiGetThreadId returns kernel thread id */ extern pthread_key_t pid_key; #define cxiGetThreadId() ((cxiThreadId)(PTR_TO_INT32(pthread_getspecific(pid_key)))) #endif /* !NPTL */ #endif /* _KERNEL */ #ifdef _KERNEL /* Convert a kernel stack address to the thread ID of the thread that uses that stack */ EXTERNC int cxiStackAddrToThreadId(char* stackP, cxiThreadId* tidP); /* Convert a kernel thread pointer to the corresponding thread ID */ EXTERNC int cxiThreadPtrToThreadId(char* threadP, cxiThreadId* tidP); #endif /* _KERNEL */ #ifdef _KERNEL /* Transfer data from buffer(s) in user space to or from a buffer in the * kernel. */ EXTERNC int cxiUiomove(char* kBufP, unsigned long nBytes, Boolean toKernel, struct cxiUio_t* uioP); EXTERNC void * cxiGetFcntlOwner(eflock_t *flP); #define cxiSetEflockOwner(eflockP, flP) (eflockP->l_owner = cxiGetFcntlOwner(flP)) #define FL_OFFSET_MAX (loff_t)(~0ULL>>1) #endif /* _KERNEL */ /* System priority operations */ /* Define priority constants inherited from AIX; priority can only be * relatively adjusted in Linux and not set directly. * AIX setpri priority numbers 0-99 (as recorded in the mmfs.cfg file) * will be decremented by 60 (PUSER+20) to get to the setpriority range * of -20 to 20. Linux setpriority will then bound anything outside that * range to the edges of the range. */ #define PRI_SCHED 16 #define PUSER 40 #define cxiSetPri(pid, newpri) (setpriority(PRIO_PGRP, (int)pid, \ (int)newpri-(PUSER+20))) #define cxiGetPri(pid) ((PUSER+20) + getpriority(PRIO_PGRP, (int)pid)) /* Threads are actually a cloned process with separate signal masks */ #define cxiSigThreadMask(a,b,c) sigprocmask((a),(b),(c)); #ifndef _KERNEL /* Assertion functions */ #include #define cxiAssertFailed(STRING,FILE,LINE) \ __assert_fail((STRING),(FILE),(LINE),__ASSERT_FUNCTION) #endif void dump_trace_back(char *failingExpr, char *srcFileName, int srcLineNumber); #ifdef INSTRUMENT_LOCKS /* Statistics kept per lock class: number of lock acquisitions and the number of times the lock appeared to be held before it was requested */ struct BlockingMutexStats { UInt32 bmsAcquires; /* number of times lock obtained */ UInt32 bmsConflicts; /* number of lock conflicts */ }; #define MAX_GPFS_LOCK_NAMES 48 #ifdef _KERNEL EXTERNC struct BlockingMutexStats BlockingMutexStatsTable[MAX_GPFS_LOCK_NAMES]; EXTERNC void InitBlockingMutexStats(); #endif #endif /* INSTRUMENT_LOCKS */ #ifdef _KERNEL /* String functions for the kernel */ static inline size_t cxiStrlen(const char *str1) { const char *beg1; if (str1 == NULL) return 0; for (beg1 = str1; *str1; str1++); return str1 - beg1; } static inline char *cxiStrcpy(char *str1, const char *str2) { char *beg1 = str1; while (*str1++ = *str2++); return beg1; } static inline char *cxiStrcat(char *str1, const char *str2) { char *beg1; for (beg1 = str1; *str1; str1++); while (*str1++ = *str2++); return beg1; } static inline int cxiStrcmp(const char *str1, const char *str2) { /* This cannot have an ENTER macro because it is used to implement ENTER processing */ for (; *str1 == *str2; str1++, str2++) if (*str1 == '\0') return 0; return *str1 - *str2; } static inline char *cxiStrncpy(char *str1, const char *str2, size_t num) { char *beg1 = str1; while (num) { num--; if ((*str1++ = *str2++) == '\0') break; } /* strncpy is defined to null out the total length */ while (num) { num--; *str1++ = '\0'; } return beg1; } static inline char *cxiStrncat(char *str1, const char *str2, size_t num) { char *beg1; for (beg1 = str1; *str1; str1++); while (num-- && (*str1 = *str2++)) str1++; *str1 = '\0'; return beg1; } static inline char *cxiStrrchr(const char *str1, int ch) { char *ret = NULL; do { if (*str1 == (char)ch) ret = (char *)str1; } while (*str1++); return ret; } static inline char *cxiStrchr(const char *str1, int ch) { char *ret = NULL; do { if (*str1 == (char)ch) { ret = (char *)str1; break; } } while (*str1++); return ret; } static inline int cxiMemcmp(const void *v1, const void *v2, size_t num) { char *str1 = (char *)v1; char *str2 = (char *)v2; for (; num && (*str1 == *str2); str1++, str2++, num--); if (num) return *str1 - *str2; else return 0; } static inline void *cxiMemcpy(void *v1, const void *v2, size_t num) { char *str1 = (char *)v1; char *str2 = (char *)v2; while (num--) *str1++ = *str2++; return v1; } static inline void *cxiMemset(void *v1, int c, size_t num) { char *str1 = (char *)v1; while (num--) *str1++ = c; return v1; } #endif /* _KERNEL */ /* Local file system list */ #define FILESYSTEM_FILE "/etc/fstab" #define VI_FILE "/bin/vi" #define ROOT_GROUP "root" #define ROOT_USER "root" /* AIX inherited constants from device.h */ #define CFG_INIT 0x1 #define CFG_TERM 0x2 #ifdef _KERNEL /* AIX inherited constants from sleep.h */ /* flags for e_thread_sleep */ #define INTERRUPTIBLE (1) /* sleep is interruptible */ #define LOCK_HANDLER (2) /* lock used by interrupt handlers */ //#define LOCK_READ (4) /* complex lock read mode specified */ #define LOCK_SIMPLE (8) /* simple lock specified */ //#define LOCK_WRITE (16) /* complex lock write mode specified */ /* return values from e_thread_block */ #define THREAD_AWAKENED (1) /* normal wakeup value */ #define THREAD_TIMED_OUT (2) /* sleep timed out */ #define THREAD_INTERRUPTED (4) /* sleep interrupted by signal */ #define THREAD_OTHER (4096) /* Beginning of subsystem values */ #endif /* _KERNEL */ /* --------------------------------------- */ /* Interfaces usable only from kernel code */ /* --------------------------------------- */ #ifdef _KERNEL /* Macros to convert Linux kernel version to a decimal integer that can be compared to the symbol LINUX_KERNEL_VERSION. See the description of LINUX_KERNEL_VERSION in site.mcr.proto. */ #define GPFS_KERNEL_VERSION(_major,_minor,_sub,_mod) \ ( (_major)*1000000 + (_minor)*10000 + (_sub)*100 + (_mod)) /* * Kernel memory allocation services: * * These are implemented as subroutines in gpl-linux/kxiSystem.C. All * allocations use storage class GFP_KERNEL. There is no distinction * between pinned and unpinned kernel memory in Linux, so the unpinned * interfaces are defined in terms of the pinned interfaces as macros. */ EXTERNC void* cxiMallocPinned(int nBytes); #define cxiMallocUnpinned(nBytes) cxiMallocPinned(nBytes) EXTERNC void cxiFreePinned(void* p); #define cxiFreeUnpinned(p) cxiFreePinned(p) EXTERNC void *cxiBigMalloc(int size); EXTERNC void cxiBigFree(char *ptr); /* cxiIsSuperUser - return true if caller has maximum authorization (is root) */ EXTERNC Boolean cxiIsSuperUser(); /* cxiGetMaxFileSize - return the maximum file size the calling process * is allowed to create. */ EXTERNC Int64 cxiGetMaxFileSize(); /* NFS services for Linux */ /* nfsd calls open and release for every file read/write. Provide a way to detect that nfsd is the caller and avoid the extra overhead. */ EXTERNC Boolean cxiIsNFSThread(); /* nfsd4 opens should not block waiting for conflicting oplocks to be * broken. They can accept EAGAIN and translate to NFS4ERR_DELAY as * it does if it initiates a delegation recall. */ EXTERNC Boolean cxiIsNFS4Thread(); EXTERNC Boolean cxiIsGPFSThread(); EXTERNC Boolean cxiIsKswapdThread(); EXTERNC Boolean cxiIsLockdThread(); /* See if a cxiFlock_t belongs to NFS (lockd) */ #define cxiGetLockCaller(lockP) ((lockP)->l_caller) #define cxiIsNFSLock(lockP) ((lockP)->l_caller == L_CALLER_LOCKD) /* No-op services on linux */ EXTERNC int socket_aio_dequeue(); /* kupdate services for Linux */ /* Use to identify syncs from kupdate that are generated way too often by Linux (every 5 seconds). */ EXTERNC Boolean cxiIsKupdateThread(); #ifdef SMB_LOCKS /* Samba services for Linux */ /* smbd calls open and subsequently makes calls to set open deny modes and op locks. Provide a way to distinguish these Samba calls from calls from other users for which default actions on open and op locks must be taken */ EXTERNC Boolean cxiIsSambaOrLockdThread(); /* Samba services for Linux */ /* Provide a way to distinguish Samba calls from calls from other users */ EXTERNC Boolean cxiIsSambaThread(); #endif /* The nfsd threads are allowed to FSYNC their writes. */ #define cxiAllowNFSFsync() cxiIsNFSThread() /* OS dependent VFS calls */ #define cxiDisconnectVfs(PVP) /* nothing ??? */ EXTERNC void cxiDeleteMmap(cxiVmid_t); /* delete memory map */ /* Set OS dependent virtual node type and device */ EXTERNC void cxiSetOSNodeType(struct cxiNode_t *cnP, cxiMode_t mode, cxiDev_t rdev); #define cxiOSNodeTypeIs(CNP,VTYPE) (((CNP)->nType) == (VTYPE)) EXTERNC Boolean cxiCanUncacheOSNode(void *osVfsP, struct cxiNode_t *cnP, void **vPP); #ifdef __cplusplus #ifdef CCL EXTERNC void *cxiAddOSNode(void *dentryP, void *vP, DentryOpTableTypes dopTabType, int lookup = 0); #else EXTERNC void *cxiAddOSNode(void *dentryP, void *vP, int lookup = 0); #endif #endif /* Kernel operations to copy data between user and kernel space */ EXTERNC int cxiCopyIn(char *from, char *to, unsigned long size); EXTERNC int cxiCopyOut(char *from, char *to, unsigned long size); EXTERNC int cxiCopyInstr(char *from, char *to, unsigned long size, unsigned long *len); EXTERNC long cxiSafeGetLong(long* from); EXTERNC void cxiSafePutLong(long val, long* to); EXTERNC int cxiSafeGetInt(int* from); EXTERNC void cxiSafePutInt(int val, int* to); /* Adhere to XPG 1170 behaviour */ #define cxiIsXPG() 1 /* Routine to send a signal to the current thread/process */ EXTERNC void cxiSendSigThread(int sig); /* Routines to manipulate cxiWaitEvent_t objects. */ EXTERNC void cxiWaitEventInit(cxiWaitEvent_t* weP); EXTERNC Boolean cxiWaitEventHasWaiters(cxiWaitEvent_t* weP); /* Kernel-only synchronization primitives. A cxiBlockingMutex_t can be used to protect a critical section. Requests to acquire a cxiBlockingMutex that is already held by another thread will block the caller. Must initialize the mutex before acquiring it, and must terminate it before deallocating the storage it occupies. Implemented using semaphores on Linux. */ EXTERNC void cxiBlockingMutexInit(cxiBlockingMutex_t* mP, int bmNameIdx); EXTERNC void cxiBlockingMutexAcquire(cxiBlockingMutex_t* mP) REGPARMS; EXTERNC void cxiBlockingMutexRelease(cxiBlockingMutex_t* mP) REGPARMS; EXTERNC void cxiBlockingMutexTerm(cxiBlockingMutex_t* mP); EXTERNC Boolean cxiBlockingMutexHeldByCaller(cxiBlockingMutex_t* mP); EXTERNC Boolean cxiBlockingMutexHasWaiters(cxiBlockingMutex_t* mP); /* Yield the CPU to allow other processes to run */ EXTERNC void cxiYield(); /* Well defined portability interface calling changing (depending on kernel * level) linux interface */ EXTERNC int cxiFillDir(void *argP, const char *nameP, int namelen, offset_t offset, ino_t ino); /* A cxiWaitEvent_t can be used like a condition variable using the calls below. There must be an associated cxiBlockingMutex_t held when calling cxiWaitEventWait that will be reacquired before returning. The routine cxiWaitEventSignal wakes up one thread waiting in cxiWaitEventWait, while cxiWaitEventBroadcast wakes all such waiting threads. The cxiWaitEventWakeupOne routine is the same as cxiWaitEventSignal except that multiple calls will each pick a different thread. The flags parameter to cxiWaitEventWait indicates whether or not the wait can be interrupted by a signal. It should be set to INTERRUPTIBLE if interrupts due to signals are desired, otherwise set to 0. */ EXTERNC int cxiWaitEventWait(cxiWaitEvent_t* weP, cxiBlockingMutex_t* mutexP, int waitFlags); EXTERNC void cxiWaitEventSignal(cxiWaitEvent_t* weP); EXTERNC void cxiWaitEventWakeupOne(cxiWaitEvent_t* weP); EXTERNC void cxiWaitEventBroadcast(cxiWaitEvent_t* weP); EXTERNC void cxiWaitEventBroadcastRC(cxiWaitEvent_t* weP, int rc); /* Kill the system due to a fatal error */ EXTERNC void cxiPanic(const char* panicStrP); /* Get the address of the first byte not addressible by processes */ EXTERNC UIntPtr cxiGetKernelBoundary(); /* Return true if this process holds the big kernel lock (BKL) */ EXTERNC Boolean cxiHoldsBKL(); EXTERNC void cxiExportModuleStruct(void *modAddr); EXTERNC void cxiIncModuleCounter(int up); EXTERNC void cxiSetBit(unsigned long *flagP, int flag_bit); EXTERNC void cxiClearBit(unsigned long *flagP, int flag_bit); EXTERNC Boolean cxiTestBit(unsigned long *flagP, int flag_bit); /* Tell OS if a thread is involved in handling VM page-out requests */ EXTERNC Boolean cxiSetPageoutThread(); EXTERNC void cxiClearPageoutThread(); #ifdef API_32BIT #ifdef GPFS_ARCH_IA64 /* Macros for 32-bit API support. 32-bit addresses are in region 0, so the upper 32-bits of 32-bit proc addresses are just zero extended. */ #define MASK_UPPER32 0xFFFFFFFF00000000UL #define cxiIS64U(addr) ((((UIntPtr)addr) & MASK_UPPER32) != 0) #endif /* GPFS_ARCH_IA64 */ #ifdef GPFS_ARCH_X86_64 /* Need to define cxiIS64U in portability layer for Opteron. */ EXTERNC int cxiIS64U(char *addr); #endif /* GPFS_ARCH_X86_64 */ #endif /* API_32BIT */ #endif /* _KERNEL */ /* Return current time of day in seconds and nanoseconds. */ #ifdef _KERNEL EXTERNC int cxiGetTOD(cxiTimeStruc_t *tP); static inline void cxiInvalidateAttr(cxiNode_t *cnP, int what) { cnP->icValid &= ~what; if (what & CXI_IC_PERM) cxiInvalidatePerm(cnP); } #else /* !_KERNEL */ struct timezone; EXTERNC int gettimeofday __P ((struct timeval *__tv, struct timezone *__tz)); /* cxiTimeStruc_t should have same size as linux struct timeval. * Call LGPL library function and translate microseconds from call * to nanoseconds. */ EXTERNC inline int cxiGetTOD(cxiTimeStruc_t *tP) { #ifdef STANDALONE_PROGRAM int rc = gettimeofday((struct timeval *)tP, NULL); tP->tv_nsec = tP->tv_nsec * 1000; return rc; #else return kxGetTimeOfDay(tP); #endif #define cxiSafeGetLong(_ptr) (*_ptr) #define cxiSafeGetInt(_ptr) (*_ptr) } /* String functions in user space */ #define cxiStrcpy strcpy #define cxiStrncpy strncpy #define cxiStrcat strcat #define cxiStrncat strncat #define cxiStrrchr strrchr #define cxiStrchr strchr #define cxiStrcmp strcmp #define cxiMemcpy memcpy #define cxiStrlen strlen #define cxiMemcmp memcmp #define cxiMemset memset #endif /* _KERNEL */ /* Samba share/delegate flags. Unlike NFSV4, the interface here is * just between our Samba vfs library and ourselves so we can define * these to be any values we choose. */ #define CXI_ACCESS_READ 1 #define CXI_ACCESS_WRITE 2 #define CXI_ACCESS_BOTH 3 #define CXI_DENY_NONE 0 #define CXI_DENY_READ 1 #define CXI_DENY_WRITE 2 #define CXI_DENY_BOTH 3 #define CXI_DELEGATE_NONE 0 #define CXI_DELEGATE_READ 1 #define CXI_DELEGATE_WRITE 2 /* Whatever the values specified in Samba for share, deny, and oplock flags, * we have to translate them to our SMB open and oplock flags. * Define macros to translate and error check. */ #define XLATE_SAMBA_ACCESS(SAMBA_SHARE, SHARE) \ if (SAMBA_SHARE == CXI_ACCESS_READ) SHARE |= coRead; \ else if (SAMBA_SHARE == CXI_ACCESS_WRITE) SHARE |= coWriteM|coWriteA; \ else if (SAMBA_SHARE == CXI_ACCESS_BOTH) SHARE |= coRead|coWriteM|coWriteA; \ else if (SAMBA_SHARE != 0) goto xerror; #define XLATE_SAMBA_DENY(SAMBA_DENY, SHARE) \ if (SAMBA_DENY == CXI_DENY_NONE) SHARE &= ~coDenyAll; \ else if (SAMBA_DENY == CXI_DENY_READ) SHARE |= coDenyR; \ else if (SAMBA_DENY == CXI_DENY_WRITE) SHARE |= coDenyWM|coDenyWA; \ else if (SAMBA_DENY == CXI_DENY_BOTH) SHARE |= coDenyR|coDenyWM|coDenyWA; \ else goto xerror; #define XLATE_SAMBA_DELEGATE(SAMBA_DELEGATE, OPLOCK) \ if (SAMBA_DELEGATE == CXI_DELEGATE_NONE) OPLOCK |= smbOplockNone; \ else if (SAMBA_DELEGATE == CXI_DELEGATE_READ) OPLOCK |= smbOplockShared; \ else if (SAMBA_DELEGATE == CXI_DELEGATE_WRITE) OPLOCK |= smbOplockExclusive; \ else goto xerror; /* Call Linux-specific F_SETLEASE operation. This will register the caller so that it will be notified via SIGIO when an OpLock break is required (REVOKE_LEASE is called). */ #define CXI_REGISTER_LEASE(FD, LTYPE) \ fcntl(FD, F_SETLEASE, (LTYPE == CXI_DELEGATE_READ )? F_RDLCK: \ (LTYPE == CXI_DELEGATE_WRITE)? F_WRLCK: F_UNLCK) /* Call Linux-specific F_GETLEASE */ #define CXI_GET_LEASE_HELD(FD, LEASE) \ LEASE = fcntl(FD, F_GETLEASE, 0); \ LEASE = (LEASE == F_RDLCK)? CXI_DELEGATE_READ: \ (LEASE == F_WRLCK)? CXI_DELEGATE_WRITE: \ (LEASE == F_UNLCK)? CXI_DELEGATE_NONE: LEASE #if defined(NFS4_CLUSTER) || defined(NFS4_VCM) #define OPEN4_SHARE_ACCESS_READ 0x00000001 #define OPEN4_SHARE_ACCESS_WRITE 0x00000002 #define OPEN4_SHARE_ACCESS_BOTH 0x00000003 #define OPEN4_SHARE_DENY_NONE 0x00000000 #define OPEN4_SHARE_DENY_READ 0x00000010 #define OPEN4_SHARE_DENY_WRITE 0x00000020 #define OPEN4_SHARE_DENY_BOTH 0x00000030 #define OPEN_DELEGATE_NONE 0x00000000 #define OPEN_DELEGATE_READ 0x00000100 #define OPEN_DELEGATE_WRITE 0x00000200 #define CXI_SHARE_ACCESS_READ OPEN4_SHARE_ACCESS_READ #define CXI_SHARE_ACCESS_WRITE OPEN4_SHARE_ACCESS_WRITE #define CXI_SHARE_ACCESS_BOTH OPEN4_SHARE_ACCESS_BOTH #define CXI_SHARE_DENY_NONE OPEN4_SHARE_DENY_NONE #define CXI_SHARE_DENY_READ OPEN4_SHARE_DENY_READ #define CXI_SHARE_DENY_WRITE OPEN4_SHARE_DENY_WRITE #define CXI_SHARE_DENY_BOTH OPEN4_SHARE_DENY_BOTH #define CXI_OPEN_DELEGATE_NONE OPEN_DELEGATE_NONE #define CXI_OPEN_DELEGATE_READ OPEN_DELEGATE_READ #define CXI_OPEN_DELEGATE_WRITE OPEN_DELEGATE_WRITE /* Whatever the values specified in the NFS4 interface for share, deny, and * delegate flags, we have to translate them to our SMB open and oplock flags. * Define macros to translate and error check. */ #define XLATE_NFS4_ACCESS(NFS4_SHARE, SHARE) \ if (NFS4_SHARE == CXI_SHARE_ACCESS_READ) SHARE |= coRead; \ else if (NFS4_SHARE == CXI_SHARE_ACCESS_WRITE) SHARE |= coWriteM|coWriteA; \ else if (NFS4_SHARE == CXI_SHARE_ACCESS_BOTH) SHARE |= coRead|coWriteM|coWriteA; \ else if (NFS4_SHARE != 0) goto xerror; #define XLATE_NFS4_DENY(NFS4_DENY, SHARE) \ if (NFS4_DENY == CXI_SHARE_DENY_NONE) SHARE &= ~coDenyAll; \ else if (NFS4_DENY == CXI_SHARE_DENY_READ) SHARE |= coDenyR; \ else if (NFS4_DENY == CXI_SHARE_DENY_WRITE) SHARE |= coDenyWM|coDenyWA; \ else if (NFS4_DENY == CXI_SHARE_DENY_BOTH) SHARE |= coDenyR|coDenyWM|coDenyWA; \ else goto xerror; #define XLATE_NFS4_DELEGATE(NFS4_DELEGATE, OPLOCK) \ if (NFS4_DELEGATE == CXI_OPEN_DELEGATE_NONE) OPLOCK |= smbOplockNone; \ else if (NFS4_DELEGATE == CXI_OPEN_DELEGATE_READ) OPLOCK |= smbOplockShared; \ else if (NFS4_DELEGATE == CXI_OPEN_DELEGATE_WRITE) OPLOCK |= smbOplockExclusive; \ else goto xerror; #endif /* NFS4_CLUSTER */ #ifdef NFS4_VCM /* VCM definitions */ #define boolean_t Boolean #define uint16_t UInt16 typedef void * vcm_peerHandle_t; typedef uint16_t vcm_opRights_t; typedef UInt64 vcm_revokeTag_t; /* VCM flags */ /* Flags for vcm_peerRegister() */ #define VCM_PRGY_RTN_OPENS 0x00000001 #define VCM_PRGY_ENF_VREG 0x00000002 #define VCM_PRGY_ENF_VDIR 0x00000004 #define VCM_PRGY_ENF_VLNK 0x00000008 /* Flags for vcm_peerRevoke() */ #define VCM_P_RVK_NOWAIT 0x00000001 #define VCM_P_RVK_FORCE 0x00000002 /* Flags for getOpRights */ #define VCM_P_GR_NOWAIT 0x00000001 /* Flags for returnOpRights */ #define VCM_P_RR_REL_OBJ 0x00000001 /* Flags for vcm_peerCreateReq_t */ #define VCM_P_CREQ_F_CREATE 0x00000001 /* GPFS peer-side utilities */ #define cxiPeerUnregister() (NOOP); #define cxiGetPeerTag() ((uint64_t)NULL) #define cxiGetPeerHandle() ((vcm_peerHandle_t)NULL) #define cxiWatchVCM(nfsP, doClose) (0); #define cxiCleanupVCM(nfsP) (0); #define cxiFSCleanupVCM(privVfsP) (0); #define cxiInitVCM(nfsP) \ { \ nfsP->vcmRights = 0; \ nfsP->vcmRevokeRights = 0; \ nfsP->vcmRevokeTag = 0; \ } /* GPFS peer-side interfaces */ #define gpfs_vcm_releaseObjHandle(peerTag, objHandleP) (0) #define delegateInternal(vP, vinfoP, acc, flags, cb_rtn, cookie) (0) /* VCM-side interfaces */ #define vcm_peerRegister(peerInfoP, peerHandleP) (0) #define vcm_peerUnregister(peerHandle) (0) #define vcm_peerRevoke(peerHandle, objHandle, peerOpHandle, peerTag, \ rights, flags, releObjHandleP) (0) #define vcm_peerTest(tc, fid, vfsP, opInfoP) (0) /* The CXI_OPEN/SHARE values will be set to the VCM Rights * Here some useful comparison macros based on these defines are included. */ #define CXI_DELEGATE (CXI_OPEN_DELEGATE_READ | CXI_OPEN_DELEGATE_WRITE) #define CXI_SHARE_ALLOW (CXI_SHARE_ACCESS_READ | CXI_SHARE_ACCESS_WRITE) #define CXI_SHARE_DENY (CXI_SHARE_DENY_READ | CXI_SHARE_DENY_WRITE) #define CXI_SHARE (CXI_SHARE_ALLOW | CXI_SHARE_DENY) #define CXI_IS_DELEGATE_READ(R) (0 != (R & CXI_OPEN_DELEGATE_READ)) #define CXI_IS_DELEGATE_WRITE(R) (0 != (R & CXI_OPEN_DELEGATE_WRITE)) #define CXI_IS_SHARE_READ(R) (0 != (R & CXI_SHARE_ACCESS_READ)) #define CXI_IS_SHARE_WRITE(R) (0 != (R & CXI_SHARE_ACCESS_WRITE)) #define CXI_IS_DENY_READ(R) (0 != (R & CXI_SHARE_DENY_READ)) #define CXI_IS_DENY_WRITE(R) (0 != (R & CXI_SHARE_DENY_WRITE)) #define CXI_IS_DELEGATE(R) (0 != (R & CXI_DELEGATE)) #define CXI_IS_SHARE_ALLOW(R) (0 != (R & CXI_SHARE_ALLOW)) #define CXI_IS_SHARE_DENY(R) (0 != (R & CXI_SHARE_DENY)) #define CXI_IS_SHARE(R) (0 != (R & CXI_SHARE)) #endif /* NFS4_VCM */ #if defined(DMAPI) || defined(SANERGY) EXTERNC int cxiPathToVfsP(void **privVfsPP, char *pathname, void **ndPP, void **gP, Boolean traverseLink); EXTERNC void cxiPathRel(void * ndP); EXTERNC void cxiSetCred(void *eCredP); #endif /* DMAPI or SANERGY */ #ifdef UIDREMAP EXTERNC size_t cxiGetUserEnvironmentSize(void); EXTERNC int cxiGetUserEnvironment(char* buf, size_t len); #endif EXTERNC Boolean cxiHasMountHelper(); EXTERNC int cxiCheckThreadState(cxiThreadId tid); #ifdef P_NFS4 EXTERNC int cxiSetFH(int *fhP, int sid); EXTERNC int cxiOpenState(void *vfsP, void *p); EXTERNC int cxiChangeState(void *vfsP, void *p); EXTERNC int cxiRecallLayout(void *vfsP, void *vP, void *p); EXTERNC int cxiGetDeviceList(int nDests, int *dests, void *p); EXTERNC int cxiGetDeviceInfo(void *p); EXTERNC int cxiGetLayout(int nDests, int *dests, cxiVattr_t *vattr, int myAddr, void *p); #endif #endif /* _h_cxiSystem_plat */