NFS update

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4825 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo
2012-06-10 23:17:10 +00:00
parent 7aecf6e0d4
commit 744fec5239
9 changed files with 412 additions and 321 deletions
+1
View File
@@ -4,6 +4,7 @@
* Copyright (C) 2012 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
* *
* Leveraged from OpenBSD: * Leveraged from OpenBSD:
* *
+23 -74
View File
@@ -4,6 +4,7 @@
* Copyright (C) 2012 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
* *
* Leveraged from OpenBSD: * Leveraged from OpenBSD:
* *
@@ -53,91 +54,39 @@
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Values for n_commitflags */ /* Flags for struct nfsnode n_flag */
#define NFS_COMMIT_PUSH_VALID 0x0001 /* Push range valid */ #define NFSNODE_OPEN (1 << 0) /* File is still open */
#define NFS_COMMIT_PUSHED_VALID 0x0002 /* Pushed range valid */ #define NFSNODE_MODIFIED (1 << 1) /* Might have a modified buffer */
#define n_atim n_un1.nf_atim
#define n_mtim n_un2.nf_mtim
#define n_cookieverf n_un1.nd_cookieverf
/* Flags for n_flag */
#define NFLUSHWANT 0x0001/* Want wakeup from a flush in prog. */
#define NFLUSHINPROG 0x0002/* Avoid multiple calls to vinvalbuf() */
#define NMODIFIED 0x0004/* Might have a modified buffer in bio */
#define NWRITEERR 0x0008/* Flag write errors so close will know */
#define NACC 0x0100/* Special file accessed */
#define NUPD 0x0200/* Special file updated */
#define NCHG 0x0400/* Special file times changed */
#define NFS_INVALIDATE_ATTRCACHE(np) ((np)->n_attrstamp = 0)
/* Convert between nfsnode pointers and vnode pointers */
#define VTONFS(vp) ((struct nfsnode *)(vp)->f_priv)
#define NFSTOV(np) ((np)->n_vnode)
#define n_atim n_un1.nf_atim
#define n_mtim n_un2.nf_mtim
#define n_sillyrename n_un3.nf_silly
#define n_cookieverf n_un1.nd_cookieverf
#define n4_cookieverf n_un1.nd4_cookieverf
#define n_cookies n_un3.nd_cook
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
/* The nfsnode is the nfs equivalent to ufs's inode. Any similarity /* There is a unique nfsnode allocated for each active file. An nfsnode is
* is purely coincidental. * 'named' by its file handle.
* There is a unique nfsnode allocated for each active file, *
* each current directory, each mounted-on file, text file, and the root. * NOTE: n_size, n_mtime, and n_ctime are duplicted withing n_attr. We could
* An nfsnode is 'named' by its file handle. (nget/nfs_node.c) * eliminate those fields and save some memory.
* If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
* type definitions), file handles of > 32 bytes should probably be split out
* into a separate malloc()'d data structure. (Reduce the size of nfsfh_t by
* changing the definition in sys/mount.h of NFS_SMALLFH.)
* NB: Hopefully the current order of the fields is such that everything will
* be well aligned and, therefore, tightly packed.
*/ */
struct nfsnode struct nfsnode
{ {
struct nfsnode *n_next; /* Retained in a singly linked list filehandle/node tree. */ struct nfsnode *n_next; /* Retained in a singly linked list. */
bool n_open; /* true: The file is (still) open */ uint8_t n_type; /* File type */
uint64_t n_size; /* Current size of file */ uint8_t n_fhsize; /* Size in bytes of the file handle */
struct nfs_fattr n_fattr; /* nfs file attribute cache */ uint8_t n_flags; /* Node flags */
uint8_t nfsv3_type; /* File type */ uint16_t n_buflen; /* Size of I/O buffer */
time_t n_attrstamp; /* Attr. cache timestamp */ struct nfs_fattr n_fattr; /* nfs file attribute cache (network order) */
struct timespec n_mtime; /* Prev modify time. */ struct timespec n_mtime; /* Prev modify time (see NOTE) */
time_t n_ctime; /* Prev create time. */ time_t n_ctime; /* Prev create time (see NOTE) */
nfsfh_t n_fhp; /* NFS File Handle */ nfsfh_t n_fhandle; /* NFS File Handle */
uint32_t n_error; /* Save write error value */ uint64_t n_size; /* Current size of file (see NOTE) */
union
{
struct timespec nf_atim; /* Special file times */
uint8_t nd_cookieverf[NFSX_V3WRITEVERF]; /* Cookie verifier (dir only) */
} n_un1;
union
{
struct timespec nf_mtim;
} n_un2;
uint32_t n_fhsize; /* size in bytes, of fh */
short n_flag; /* Flag for locking.. */
//nfsfh_t n_fh; /* Small File Handle */
time_t n_accstamp; /* Access cache timestamp */
uid_t n_accuid; /* Last access requester */
int n_accmode; /* Last mode requested */
int n_accerror; /* Last returned error */
//off_t n_pushedlo; /* 1st blk in commited range */ /* I/O buffer (must be a aligned to 32-bit boundaries) */
//off_t n_pushedhi; /* Last block in range */
//off_t n_pushlo; /* 1st block in commit range */ uint8_t n_iobuffer[1]; /* Actual size is given by n_buflen */
//off_t n_pushhi; /* Last block in range */
//struct rwlock n_commitlock; /* Serialize commits */
//int n_commitflags;
}; };
#define SIZEOF_nfsnode(n) (sizeof(struct nfsnode) + ((n)-1))
#endif /* __FS_NFS_NFS_NODE_H */ #endif /* __FS_NFS_NFS_NODE_H */
+84 -70
View File
@@ -4,6 +4,7 @@
* Copyright (C) 2012 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
* *
* Leveraged from OpenBSD: * Leveraged from OpenBSD:
* *
@@ -214,95 +215,95 @@
#define NFSV3SATTRTIME_TOSERVER 1 #define NFSV3SATTRTIME_TOSERVER 1
#define NFSV3SATTRTIME_TOCLIENT 2 #define NFSV3SATTRTIME_TOCLIENT 2
#define NFSV3ACCESS_READ 0x01 #define NFSV3ACCESS_READ 0x01
#define NFSV3ACCESS_LOOKUP 0x02 #define NFSV3ACCESS_LOOKUP 0x02
#define NFSV3ACCESS_MODIFY 0x04 #define NFSV3ACCESS_MODIFY 0x04
#define NFSV3ACCESS_EXTEND 0x08 #define NFSV3ACCESS_EXTEND 0x08
#define NFSV3ACCESS_DELETE 0x10 #define NFSV3ACCESS_DELETE 0x10
#define NFSV3ACCESS_EXECUTE 0x20 #define NFSV3ACCESS_EXECUTE 0x20
#define NFSV3WRITE_UNSTABLE 0 #define NFSV3WRITE_UNSTABLE 0
#define NFSV3WRITE_DATASYNC 1 #define NFSV3WRITE_DATASYNC 1
#define NFSV3WRITE_FILESYNC 2 #define NFSV3WRITE_FILESYNC 2
#define NFSV3CREATE_UNCHECKED 0 #define NFSV3CREATE_UNCHECKED 0
#define NFSV3CREATE_GUARDED 1 #define NFSV3CREATE_GUARDED 1
#define NFSV3CREATE_EXCLUSIVE 2 #define NFSV3CREATE_EXCLUSIVE 2
#define NFSV3FSINFO_LINK 0x01 #define NFSV3FSINFO_LINK 0x01
#define NFSV3FSINFO_SYMLINK 0x02 #define NFSV3FSINFO_SYMLINK 0x02
#define NFSV3FSINFO_HOMOGENEOUS 0x08 #define NFSV3FSINFO_HOMOGENEOUS 0x08
#define NFSV3FSINFO_CANSETTIME 0x10 #define NFSV3FSINFO_CANSETTIME 0x10
/* NFS mount option flags */ /* NFS mount option flags */
#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */ #define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
#define NFSMNT_WSIZE 0x00000002 /* set write size */ #define NFSMNT_WSIZE 0x00000002 /* set write size */
#define NFSMNT_RSIZE 0x00000004 /* set read size */ #define NFSMNT_RSIZE 0x00000004 /* set read size */
#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */ #define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */ #define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */ #define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */ #define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */ #define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
/* 0x100 free, was NFSMNT_NQNFS */ /* 0x100 free, was NFSMNT_NQNFS */
#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */ #define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
/* 0x400 free, was NFSMNT_KERB */ /* 0x400 free, was NFSMNT_KERB */
#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */ #define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
/* 0x1000 free, was NFSMNT_LEASETERM */ /* 0x1000 free, was NFSMNT_LEASETERM */
#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */ #define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */ #define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */ #define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */ #define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */ #define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
#define NFSMNT_ACREGMIN 0x00040000 #define NFSMNT_ACREGMIN 0x00040000
#define NFSMNT_ACREGMAX 0x00080000 #define NFSMNT_ACREGMAX 0x00080000
#define NFSMNT_ACDIRMIN 0x00100000 #define NFSMNT_ACDIRMIN 0x00100000
#define NFSMNT_ACDIRMAX 0x00200000 #define NFSMNT_ACDIRMAX 0x00200000
#define NFSMNT_NOLOCKD 0x00400000 /* Locks are local */ #define NFSMNT_NOLOCKD 0x00400000 /* Locks are local */
#define NFSMNT_NFSV4 0x00800000 /* Use NFS Version 4 protocol */ #define NFSMNT_NFSV4 0x00800000 /* Use NFS Version 4 protocol */
#define NFSMNT_HASWRITEVERF 0x01000000 /* NFSv4 Write verifier */ #define NFSMNT_HASWRITEVERF 0x01000000 /* NFSv4 Write verifier */
#define NFSMNT_GOTFSINFO 0x00000004 /* Got the V3 fsinfo */ #define NFSMNT_GOTFSINFO 0x00000004 /* Got the V3 fsinfo */
#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */ #define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
#define NFSMNT_NOAC 0x00080000 /* Turn off attribute cache */ #define NFSMNT_NOAC 0x00080000 /* Turn off attribute cache */
/* Conversion macros */ /* Conversion macros */
#define vtonfsv2_mode(t,m) \ #define vtonfsv2_mode(t,m) \
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \ txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
MAKEIMODE((t), (m))) MAKEIMODE((t), (m)))
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777) #define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
#define nfstov_mode(a) (fxdr_unsigned(u_int16_t, (a))&07777) #define nfstov_mode(a) (fxdr_unsigned(u_int16_t, (a))&07777)
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))]) #define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))])
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))]) #define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))])
#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(uint32_t,(a))&0x7] #define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(uint32_t,(a))&0x7]
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(uint32_t,(a))&0x7] #define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(uint32_t,(a))&0x7]
#define NFS_MAXFHSIZE 64 #define NFS_MAXFHSIZE 64
/* Mode bit values */ /* Mode bit values */
#define NFSMMODE_IXOTH 0x00001 /* Execute permission for others on a file */ #define NFSMODE_IXOTH 0x00001 /* Execute permission for others on a file */
#define NFSMMODE_IWOTH 0x00002 /* Write permission for others */ #define NFSMODE_IWOTH 0x00002 /* Write permission for others */
#define NFSMMODE_IROTH 0x00004 /* Read permission for others */ #define NFSMODE_IROTH 0x00004 /* Read permission for others */
#define NFSMMODE_IXGRP 0x00008 /* Execute permission for group on a file */ #define NFSMODE_IXGRP 0x00008 /* Execute permission for group on a file */
#define NFSMMODE_IWGRP 0x00010 /* Write permission for group */ #define NFSMODE_IWGRP 0x00010 /* Write permission for group */
#define NFSMMODE_IRGRP 0x00020 /* Read permission for group */ #define NFSMODE_IRGRP 0x00020 /* Read permission for group */
#define NFSMMODE_IXUSR 0x00040 /* Execute permission for owner on a file */ #define NFSMODE_IXUSR 0x00040 /* Execute permission for owner on a file */
#define NFSMMODE_IWUSR 0x00080 /* Write permission for owner */ #define NFSMODE_IWUSR 0x00080 /* Write permission for owner */
#define NFSMMODE_IRUSR 0x00100 /* Read permission for owner */ #define NFSMODE_IRUSR 0x00100 /* Read permission for owner */
#define NFSMMODE_SAVETEXT 0x00200 /* Save swapped text */ #define NFSMODE_SAVETEXT 0x00200 /* Save swapped text */
#define NFSMMODE_ISGID 0x00400 /* Set group ID on execution */ #define NFSMODE_ISGID 0x00400 /* Set group ID on execution */
#define NFSMMODE_ISUID 0x00800 /* Set user ID on execution */ #define NFSMODE_ISUID 0x00800 /* Set user ID on execution */
/* File identifier */ /* File identifier */
#define MAXFIDSZ 16 #define MAXFIDSZ 16
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
@@ -620,29 +621,42 @@ struct LOOKUP3resok
struct READ3args struct READ3args
{ {
nfstype file; struct file_handle fshandle; /* Variable length */
uint64_t offset; uint64_t offset;
uint32_t count; uint32_t count;
}; };
struct nfs_rdhdr_s
{
uint32_t attributes_follow;
struct nfs_fattr attributes; /* Will not be present if attributes_follow == 0 */
uint32_t count; /* Number of bytes read */
uint32_t eof; /* Non-zero if at the end of file */
uint32_t length; /* Length of data (same as count?) */
};
struct READ3resok struct READ3resok
{ {
struct nfs_fattr file_attributes; struct nfs_rdhdr_s hdr;
uint32_t count; uint8_t data[1]; /* Actual data size depends on count */
bool eof;
const char *data;
}; };
#define SIZEOF_READ3resok(n) (sizeof(struct nfs_rdhdr_s) + (n))
struct nfs_wrhdr_s
struct WRITE3args
{ {
nfstype file; struct file_handle fshandle; /* Variable length */
uint64_t offset; uint64_t offset;
uint32_t count; uint32_t count;
uint32_t stable; uint32_t stable;
const char *data;
}; };
struct WRITE3args
{
struct nfs_wrhdr_s hdr;
uint8_t data[1]; /* Actual data size depends on count */
};
#define SIZEOF_WRITE3args(n) (sizeof(struct nfs_wrhdr_s) + (n))
struct WRITE3resok struct WRITE3resok
{ {
struct wcc_data file_wcc; struct wcc_data file_wcc;
+1
View File
@@ -4,6 +4,7 @@
* Copyright (C) 2012 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
* *
* Leveraged from OpenBSD: * Leveraged from OpenBSD:
* *
+1 -1
View File
@@ -186,7 +186,7 @@ int nfs_checkmount(struct nfsmount *nmp)
for (file = nmp->nm_head; file; file = file->n_next) for (file = nmp->nm_head; file; file = file->n_next)
{ {
file->n_open = false; file->n_flags &= ~NFSNODE_OPEN;
} }
return -ENODEV; return -ENODEV;
+280 -165
View File
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -4,6 +4,7 @@
* Copyright (C) 2012 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
* *
* Leveraged from OpenBSD: * Leveraged from OpenBSD:
* *
@@ -342,8 +343,9 @@ struct rpc_call_read
struct rpc_call_write struct rpc_call_write
{ {
struct rpc_call_header ch; struct rpc_call_header ch;
struct WRITE3args write; struct WRITE3args write; /* Variable length */
}; };
#define SIZEOF_rpc_call_write(n) (sizeof(struct rpc_call_header) + SIZEOF_WRITE3args(n))
struct rpc_call_remove struct rpc_call_remove
{ {
@@ -429,8 +431,9 @@ struct rpc_reply_read
{ {
struct rpc_reply_header rh; struct rpc_reply_header rh;
uint32_t status; uint32_t status;
struct READ3resok read; struct READ3resok read; /* Variable length */
}; };
#define SIZEOF_rpc_reply_read(n) (sizeof(struct rpc_reply_header) + sizeof(uint32_t) + SIZEOF_READ3resok(n))
struct rpc_reply_remove struct rpc_reply_remove
{ {
+15 -8
View File
@@ -4,6 +4,7 @@
* Copyright (C) 2012 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
* *
* Leveraged from OpenBSD: * Leveraged from OpenBSD:
* *
@@ -1137,15 +1138,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve
case NFSPROC_READ: case NFSPROC_READ:
{ {
/* Copy the variable, caller-provided data into the call message structure */ /* Copy the variable length, caller-provided data into the call
* message structure.
*/
struct rpc_call_read *callmsg = (struct rpc_call_read *)msgbuf; struct rpc_call_read *callmsg = (struct rpc_call_read *)msgbuf;
memcpy(&callmsg->read, request, *reqlen); memcpy(&callmsg->read, request, *reqlen);
/* Return the full size of the message (including messages headers) */ /* Return the full size of the message (the size of variable data
* plus the size of the messages header).
*/
DEBUGASSERT(*reqlen == sizeof(struct READ3args)); *reqlen += sizeof(struct rpc_call_header);
*reqlen = sizeof(struct rpc_call_read);
/* Format the message header */ /* Format the message header */
@@ -1156,15 +1160,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve
case NFSPROC_WRITE: case NFSPROC_WRITE:
{ {
/* Copy the variable, caller-provided data into the call message structure */ /* Copy the variable length, caller-provided data into the call
* message structure.
*/
struct rpc_call_write *callmsg = (struct rpc_call_write *)msgbuf; struct rpc_call_write *callmsg = (struct rpc_call_write *)msgbuf;
memcpy(&callmsg->write, request, *reqlen); memcpy(&callmsg->write, request, *reqlen);
/* Return the full size of the message (including messages headers) */ /* Return the full size of the message (the size of variable data
* plus the size of the messages header).
*/
DEBUGASSERT(*reqlen == sizeof(struct WRITE3args)); *reqlen += sizeof(struct rpc_call_header);
*reqlen = sizeof(struct rpc_call_write);
/* Format the message header */ /* Format the message header */
+1
View File
@@ -6,6 +6,7 @@
* Copyright (C) 2012 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
* *
* Leveraged from OpenBSD: * Leveraged from OpenBSD:
* *