diff options
author | attilio <attilio@FreeBSD.org> | 2013-03-08 00:03:07 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2013-03-08 00:03:07 +0000 |
commit | bf1dc904466a6994f1b4cd94d2187edfeca7b187 (patch) | |
tree | 7d66370442268ff1c2639db0446b7970c995c657 /sys/fs | |
parent | e98f58faf63a90d85e0e2ad78353915f9615a4eb (diff) | |
parent | 281d1157a14218414e773086b47c81754114b42a (diff) | |
download | FreeBSD-src-bf1dc904466a6994f1b4cd94d2187edfeca7b187.zip FreeBSD-src-bf1dc904466a6994f1b4cd94d2187edfeca7b187.tar.gz |
MFC
Diffstat (limited to 'sys/fs')
43 files changed, 0 insertions, 15789 deletions
diff --git a/sys/fs/coda/README b/sys/fs/coda/README deleted file mode 100644 index 19de799..0000000 --- a/sys/fs/coda/README +++ /dev/null @@ -1,62 +0,0 @@ -$FreeBSD$ - - Announcing the Availability of the - Coda Distributed - Filesystem - for - BSD Unix Systems - - Coda is a distributed filesystem like NFS and AFS. It is -freely available, like NFS. But it functions much like AFS in being a -"stateful" filesystem. Coda and AFS cache files on your local -machine to improve performance. But Coda goes a step further than AFS -by letting you access the cached files when there is no available -network, viz. disconnected laptops and network outages. In Coda, both -the client and server are outside the kernel which makes them easier -to experiment with. - -To get more information on Coda, I would like to refer people to - http://www.coda.cs.cmu.edu -There is a wealth of documents, papers, and theses there. There is -also a good introduction to the Coda File System in - http://www.coda.cs.cmu.edu/ljpaper/lj.html - -Coda was originally developed as an academic prototype/testbed. It is -being polished and rewritten where necessary. Coda is a work in -progress and does have bugs. It is, though, very usable. Our -interest is in making Coda available to as many people as possible and -to have Coda evolve and flourish. - -The bulk of the Coda filesystem code supports the Coda client -program, the Coda server program and the utilities needed by both. -All these programs are unix programs and can run equally well on any -Unix platform. Our main development thrust is improving these -programs. There is a small part of Coda that deals with the kernel to -filesystem interface. This code is OS specific (but should not be -platform specific). - -Coda is currently available for several OS's and platforms: - Freebsd-2.2.5: i386 - Freebsd-2.2.6: i386 - Freebsd -current: i386 - linux 2.0: i386 & sparc - linux 2.1: i386 & sparc - NetBSD 1.3: i386 - NetBSD -current: i386 -The relevant sources, binaries, and docs can be found in - ftp://ftp.coda.cs.cmu.edu/pub/coda/ - -We intend to come out with new Coda releases often, not daily. We -don't want to slight any OS/platform not mentioned above. We are just -limited in our resources as to what we can support internally. We -will be happy to integrate OpenBSD support as well as other OS -support. Also, adding platform support should be relatively easy and -we can discuss this. The only difficulty is that Coda has a light weight -process package. It does some manipulations in assembler which would -have to be redone for a different platform. - -There are several mailing lists @coda.cs.cmu.edu that discuss coda: -coda-announce and linux-coda. We are going to revise linux-coda to be -OS neutral, since it is mainly Coda we want to discuss. We appreciate -comments, feedback, bug reports, bug fixes, enhancements, etc. - diff --git a/sys/fs/coda/TODO b/sys/fs/coda/TODO deleted file mode 100644 index a0a618a..0000000 --- a/sys/fs/coda/TODO +++ /dev/null @@ -1,16 +0,0 @@ -OOPS: - FreeBSD does not fsync!!! - -Near term: - Fix bug in executing/mapping new files. - cfs_mount bug: interaction with cfs_inactive no cfs_unsave. - vref/vn_lock == vget except no VXWANT which may be on. - Review locks: vn_lock/VOP_UNLOCK/lockmgr ... - -Medium term: - Add missing VFS methods. - Do performance profile. - Tune hash algorithm used in cfs_subr. - Make MPSAFE - -$FreeBSD$ diff --git a/sys/fs/coda/cnode.h b/sys/fs/coda/cnode.h deleted file mode 100644 index 27531a4..0000000 --- a/sys/fs/coda/cnode.h +++ /dev/null @@ -1,206 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/cnode.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - -/*- - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon University. - * Contributers include David Steere, James Kistler, and M. Satyanarayanan. - */ - -#ifndef _CNODE_H_ -#define _CNODE_H_ - -#include <sys/vnode.h> -#include <sys/lock.h> - -MALLOC_DECLARE(M_CODA); - -/* - * Cnode lookup stuff. - * - * NOTE: CODA_CACHESIZE must be a power of 2 for cfshash to work! - */ -#define CODA_CACHESIZE 512 - -#define CODA_ALLOC(ptr, cast, size) do { \ - ptr = (cast)malloc((unsigned long) size, M_CODA, M_WAITOK); \ - if (ptr == NULL) \ - panic("kernel malloc returns 0 at %s:%d\n", __FILE__, \ - __LINE__); \ -} while (0) - -#define CODA_FREE(ptr, size) free((ptr), M_CODA) - -/* - * Used to select debugging statements throughout the cfs code. - */ -extern int codadebug; -extern int coda_printf_delay; -extern int coda_vnop_print_entry; -extern int coda_psdev_print_entry; -extern int coda_vfsop_print_entry; - -#define CODADBGMSK(N) (1 << N) - -#define CODADEBUG(N, STMT) do { \ - if (codadebug & CODADBGMSK(N)) { \ - STMT \ - } \ -} while (0) - -#define myprintf(args) do { \ - if (coda_printf_delay) \ - DELAY(coda_printf_delay); \ - printf args ; \ -} while (0) - -struct cnode { - struct vnode *c_vnode; - u_short c_flags; /* flags (see below) */ - struct CodaFid c_fid; /* file handle */ - struct vnode *c_ovp; /* open vnode pointer */ - u_short c_ocount; /* count of openers */ - u_short c_owrite; /* count of open for write */ - struct vattr c_vattr; /* attributes */ - char *c_symlink; /* pointer to symbolic link */ - u_short c_symlen; /* length of symbolic link */ - uid_t c_cached_uid; /* cached uid */ - accmode_t c_cached_mode; /* cached access mode */ - struct cnode *c_next; /* links if on FreeBSD machine */ -}; -#define VTOC(vp) ((struct cnode *)(vp)->v_data) -#define CTOV(cp) ((struct vnode *)((cp)->c_vnode)) - -/* flags */ -#define C_VATTR 0x01 /* Validity of vattr in the cnode */ -#define C_SYMLINK 0x02 /* Validity of symlink pointer in the Code */ -#define C_ACCCACHE 0x04 /* Validity of access cache */ -#define C_WANTED 0x08 /* Set if lock wanted */ -#define C_LOCKED 0x10 /* Set if lock held */ -#define C_UNMOUNTING 0X20 /* Set if unmounting */ -#define C_PURGING 0x40 /* Set if purging a fid */ - -#define VALID_VATTR(cp) ((cp->c_flags) & C_VATTR) -#define VALID_SYMLINK(cp) ((cp->c_flags) & C_SYMLINK) -#define VALID_ACCCACHE(cp) ((cp->c_flags) & C_ACCCACHE) -#define IS_UNMOUNTING(cp) ((cp)->c_flags & C_UNMOUNTING) - -struct vcomm { - u_long vc_seq; - struct selinfo vc_selproc; - TAILQ_HEAD(, vmsg) vc_requests; - TAILQ_HEAD(, vmsg) vc_replies; - int vc_open; -}; - -#define VC_OPEN(vcp) ((vcp)->vc_open == 1) -#define MARK_VC_CLOSED(vcp) (vcp)->vc_open = 0 -#define MARK_VC_OPEN(vcp) (vcp)->vc_open = 1 - -struct coda_clstat { - int ncalls; /* client requests */ - int nbadcalls; /* upcall failures */ - int reqs[CODA_NCALLS]; /* count of each request */ -}; -extern struct coda_clstat coda_clstat; - -/* - * CODA structure to hold mount/filesystem information. - */ -struct coda_mntinfo { - struct vnode *mi_rootvp; - struct mount *mi_vfsp; - struct vcomm mi_vcomm; - struct cdev *dev; - int mi_started; - LIST_ENTRY(coda_mntinfo) mi_list; -}; -struct coda_mntinfo *dev2coda_mntinfo(struct cdev *dev); - -/* - * vfs pointer to mount info. - */ -#define vftomi(vfsp) ((struct coda_mntinfo *)(vfsp->mnt_data)) -#define CODA_MOUNTED(vfsp) (vftomi((vfsp)) != NULL) - -/* - * vnode pointer to mount info. - */ -#define vtomi(vp) ((struct coda_mntinfo *)(vp->v_mount->mnt_data)) - -/* - * Used for identifying usage of "Control" object. - */ -extern struct vnode *coda_ctlvp; -#define IS_CTL_VP(vp) ((vp) == coda_ctlvp) -#define IS_CTL_NAME(vp, name, l) ((l == CODA_CONTROLLEN) \ - && ((vp) == vtomi((vp))->mi_rootvp) && \ - strncmp(name, CODA_CONTROL, l) == 0) - -/* - * An enum to tell us whether something that will remove a reference to a - * cnode was a downcall or not. - */ -enum dc_status { - IS_DOWNCALL = 6, - NOT_DOWNCALL = 7 -}; - -/* cfs_psdev.h */ -int coda_call(struct coda_mntinfo *mntinfo, int inSize, int *outSize, - caddr_t buffer); - -extern int coda_kernel_version; - -/* cfs_subr.h */ -int handleDownCall(struct coda_mntinfo *mnt, int opcode, - union outputArgs *out); -void coda_unmounting(struct mount *whoIam); -int coda_vmflush(struct cnode *cp); - -/* cfs_vnodeops.h */ -struct cnode *make_coda_node(struct CodaFid *fid, struct mount *vfsp, - short type); -int coda_vnodeopstats_init(void); - -/* sigh */ -#define CODA_RDWR ((u_long) 31) - -#endif /* _CNODE_H_ */ diff --git a/sys/fs/coda/coda.h b/sys/fs/coda/coda.h deleted file mode 100644 index 2cfb712..0000000 --- a/sys/fs/coda/coda.h +++ /dev/null @@ -1,838 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - - -/* - * - * Based on cfs.h from Mach, but revamped for increased simplicity. - * Linux modifications by Peter Braam, Aug 1996 - */ - -#ifndef _CODA_HEADER_ -#define _CODA_HEADER_ - -#ifdef _KERNEL -#include "opt_coda.h" /* for CODA_COMPAT_5 option */ -#endif - -/* Avoid CODA_COMPAT_5 redefinition in coda5 module */ -#if defined (CODA5_MODULE) && !defined(CODA_COMPAT_5) -#define CODA_COMPAT_5 -#endif - -/* Catch new _KERNEL defn for NetBSD */ -#ifdef __NetBSD__ -#include <sys/types.h> -#endif - -#ifndef CODA_MAXSYMLINKS -#define CODA_MAXSYMLINKS 10 -#endif - -#if defined(DJGPP) || defined(__CYGWIN32__) -#ifdef _KERNEL -typedef unsigned long u_long; -typedef unsigned int u_int; -typedef unsigned short u_short; -typedef u_long ino_t; -typedef u_long struct cdev *; -typedef void * caddr_t; -#ifdef DOS -typedef unsigned __int64 u_quad_t; -#else -typedef unsigned long long u_quad_t; -#endif - -#define inline - -struct timespec { - long ts_sec; - long ts_nsec; -}; -#else /* DJGPP but not _KERNEL */ -#include <sys/types.h> -#include <sys/time.h> -typedef unsigned long long u_quad_t; -#endif /* !_KERNEL */ -#endif /* !DJGPP */ - - -#if defined(__linux__) -#define cdev_t u_quad_t -#if !defined(_UQUAD_T_) && (!defined(__GLIBC__) || __GLIBC__ < 2) -#define _UQUAD_T_ 1 -typedef unsigned long long u_quad_t; -#endif -#else -#define cdev_t dev_t -#endif - -#ifdef __CYGWIN32__ -typedef unsigned char u_int8_t; -struct timespec { - time_t tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ -}; -#endif - -typedef u_int32_t cuid_t; -typedef u_int32_t cgid_t; - -/* - * Cfs constants - */ -#define CODA_MAXNAMLEN 255 -#define CODA_MAXPATHLEN 1024 -#define CODA_MAXSYMLINK 10 - -/* these are Coda's version of O_RDONLY etc combinations - * to deal with VFS open modes - */ -#define C_O_READ 0x001 -#define C_O_WRITE 0x002 -#define C_O_TRUNC 0x010 -#define C_O_EXCL 0x100 -#define C_O_CREAT 0x200 - -/* these are to find mode bits in Venus */ -#define C_M_READ 00400 -#define C_M_WRITE 00200 - -/* for access Venus will use */ -#define C_A_C_OK 8 /* Test for writing upon create. */ -#define C_A_R_OK 4 /* Test for read permission. */ -#define C_A_W_OK 2 /* Test for write permission. */ -#define C_A_X_OK 1 /* Test for execute permission. */ -#define C_A_F_OK 0 /* Test for existence. */ - - -#ifndef _VENUS_DIRENT_T_ -#define _VENUS_DIRENT_T_ 1 -struct venus_dirent { - unsigned int d_fileno; /* file number of entry */ - unsigned short d_reclen; /* length of this record */ - unsigned char d_type; /* file type, see below */ - unsigned char d_namlen; /* length of string in d_name */ - char d_name[CODA_MAXNAMLEN + 1];/* name must be no longer than this */ -}; -#undef DIRSIZ -#define DIRSIZ(dp) ((sizeof (struct venus_dirent) - (CODA_MAXNAMLEN+1)) + \ - (((dp)->d_namlen+1 + 3) &~ 3)) - -/* - * File types - */ -#define CDT_UNKNOWN 0 -#define CDT_FIFO 1 -#define CDT_CHR 2 -#define CDT_DIR 4 -#define CDT_BLK 6 -#define CDT_REG 8 -#define CDT_LNK 10 -#define CDT_SOCK 12 -#define CDT_WHT 14 - -/* - * Convert between stat structure types and directory types. - */ -#define IFTOCDT(mode) (((mode) & 0170000) >> 12) -#define CDTTOIF(dirtype) ((dirtype) << 12) - -#endif - -#ifdef CODA_COMPAT_5 - -struct CodaFid { - u_long Volume; - u_long Vnode; - u_long Unique; -}; - -static __inline__ ino_t coda_f2i(struct CodaFid *fid) -{ - if (!fid) return 0; - return (fid->Unique + (fid->Vnode<<10) + (fid->Volume<<20)); -} - -static __inline__ char * coda_f2s(struct CodaFid *fid) -{ - static char fid_str [35]; - snprintf (fid_str, 35, "[%lx.%lx.%lx]", fid->Volume, - fid->Vnode, fid->Unique); - return fid_str; -} - -static __inline__ int coda_fid_eq (struct CodaFid *fid1, struct CodaFid *fid2) -{ - return (fid1->Volume == fid2->Volume && - fid1->Vnode == fid2->Vnode && - fid1->Unique == fid2->Unique); -} - -struct coda_cred { - u_int32_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/ - u_int32_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */ -}; - -#else /* CODA_COMPAT_5 */ - -struct CodaFid { - u_int32_t opaque[4]; -}; - -static __inline__ ino_t coda_f2i(struct CodaFid *fid) -{ - if ( ! fid ) - return 0; - return (fid->opaque[3] ^ (fid->opaque[2]<<10) ^ (fid->opaque[1]<<20) ^ fid->opaque[0]); -} - -static __inline__ char * coda_f2s(struct CodaFid *fid) - { - static char fid_str [35]; - snprintf (fid_str, 35, "[%x.%x.%x.%x]", fid->opaque[0], - fid->opaque[1], fid->opaque[2], fid->opaque[3]); - return fid_str; - } - -static __inline__ int coda_fid_eq (struct CodaFid *fid1, struct CodaFid *fid2) -{ - return (fid1->opaque[0] == fid2->opaque[0] && - fid1->opaque[1] == fid2->opaque[1] && - fid1->opaque[2] == fid2->opaque[2] && - fid1->opaque[3] == fid2->opaque[3]); -} - -#endif /* CODA_COMPAT_5 */ - -#ifndef _VENUS_VATTR_T_ -#define _VENUS_VATTR_T_ -/* - * Vnode types. VNON means no type. - */ -enum coda_vtype { C_VNON, C_VREG, C_VDIR, C_VBLK, C_VCHR, C_VLNK, C_VSOCK, C_VFIFO, C_VBAD }; - -struct coda_vattr { - long va_type; /* vnode type (for create) */ - u_short va_mode; /* files access mode and type */ - short va_nlink; /* number of references to file */ - cuid_t va_uid; /* owner user id */ - cgid_t va_gid; /* owner group id */ - long va_fileid; /* file id */ - u_quad_t va_size; /* file size in bytes */ - long va_blocksize; /* blocksize preferred for i/o */ - struct timespec va_atime; /* time of last access */ - struct timespec va_mtime; /* time of last modification */ - struct timespec va_ctime; /* time file changed */ - u_long va_gen; /* generation number of file */ - u_long va_flags; /* flags defined for file */ - cdev_t va_rdev; /* device special file represents */ - u_quad_t va_bytes; /* bytes of disk space held by file */ - u_quad_t va_filerev; /* file modification number */ -}; - -#endif - -/* structure used by CODA_STATFS for getting cache information from venus */ -struct coda_statfs { - int32_t f_blocks; - int32_t f_bfree; - int32_t f_bavail; - int32_t f_files; - int32_t f_ffree; -}; - -/* - * Kernel <--> Venus communications. - */ - -#define CODA_ROOT 2 -#define CODA_OPEN_BY_FD 3 -#define CODA_OPEN 4 -#define CODA_CLOSE 5 -#define CODA_IOCTL 6 -#define CODA_GETATTR 7 -#define CODA_SETATTR 8 -#define CODA_ACCESS 9 -#define CODA_LOOKUP 10 -#define CODA_CREATE 11 -#define CODA_REMOVE 12 -#define CODA_LINK 13 -#define CODA_RENAME 14 -#define CODA_MKDIR 15 -#define CODA_RMDIR 16 -#define CODA_READDIR 17 -#define CODA_SYMLINK 18 -#define CODA_READLINK 19 -#define CODA_FSYNC 20 -#define CODA_INACTIVE 21 -#define CODA_VGET 22 -#define CODA_SIGNAL 23 -#define CODA_REPLACE 24 -#define CODA_FLUSH 25 -#define CODA_PURGEUSER 26 -#define CODA_ZAPFILE 27 -#define CODA_ZAPDIR 28 -#define CODA_PURGEFID 30 -#define CODA_OPEN_BY_PATH 31 -#define CODA_RESOLVE 32 -#define CODA_REINTEGRATE 33 -#define CODA_STATFS 34 -#define CODA_NCALLS 35 - -#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID) - -#define VC_MAXDATASIZE 8192 -#define VC_MAXMSGSIZE sizeof(union inputArgs)+sizeof(union outputArgs) +\ - VC_MAXDATASIZE - -#define CIOC_KERNEL_VERSION _IOWR('c', 10, int) -#if 0 - /* don't care about kernel version number */ -#define CODA_KERNEL_VERSION 0 - /* The old venus 4.6 compatible interface */ -#define CODA_KERNEL_VERSION 1 -#endif /* realms/cells */ -#ifdef CODA_COMPAT_5 - /* venus_lookup gets an extra parameter to aid windows.*/ -#define CODA_KERNEL_VERSION 2 -#else - /* 128-bit fids for realms */ -#define CODA_KERNEL_VERSION 3 -#endif - -/* - * Venus <-> Coda RPC arguments - */ -#ifdef CODA_COMPAT_5 -struct coda_in_hdr { - unsigned long opcode; - unsigned long unique; /* Keep multiple outstanding msgs distinct */ - u_short pid; /* Common to all */ - u_short pgid; /* Common to all */ - u_short sid; /* Common to all */ - struct coda_cred cred; /* Common to all */ -}; -#else -struct coda_in_hdr { - u_int32_t opcode; - u_int32_t unique; /* Keep multiple outstanding msgs distinct */ - pid_t pid; - pid_t pgid; - cuid_t uid; -}; -#endif - -/* Really important that opcode and unique are 1st two fields! */ -struct coda_out_hdr { - u_int32_t opcode; - u_int32_t unique; - u_int32_t result; -}; - -/* coda_root: NO_IN */ -struct coda_root_out { - struct coda_out_hdr oh; - struct CodaFid Fid; -}; - -struct coda_root_in { - struct coda_in_hdr in; -}; - -/* coda_sync: */ -/* Nothing needed for coda_sync */ - -/* coda_open: */ -struct coda_open_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_open_out { - struct coda_out_hdr oh; - cdev_t dev; - ino_t inode; -}; - - -/* coda_close: */ -struct coda_close_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_close_out { - struct coda_out_hdr out; -}; - -/* coda_ioctl: */ -struct coda_ioctl_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int cmd; - int len; - int rwflag; - char *data; /* Place holder for data. */ -}; - -struct coda_ioctl_out { - struct coda_out_hdr oh; - int len; - caddr_t data; /* Place holder for data. */ -}; - - -/* coda_getattr: */ -struct coda_getattr_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -struct coda_getattr_out { - struct coda_out_hdr oh; - struct coda_vattr attr; -}; - - -/* coda_setattr: NO_OUT */ -struct coda_setattr_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - struct coda_vattr attr; -}; - -struct coda_setattr_out { - struct coda_out_hdr out; -}; - -/* coda_access: NO_OUT */ -struct coda_access_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_access_out { - struct coda_out_hdr out; -}; - - -/* lookup flags */ -#define CLU_CASE_SENSITIVE 0x01 -#define CLU_CASE_INSENSITIVE 0x02 - -/* coda_lookup: */ -struct coda_lookup_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int name; /* Place holder for data. */ - int flags; -}; - -struct coda_lookup_out { - struct coda_out_hdr oh; - struct CodaFid Fid; - int vtype; -}; - - -/* coda_create: */ -struct coda_create_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - struct coda_vattr attr; - int excl; - int mode; - int name; /* Place holder for data. */ -}; - -struct coda_create_out { - struct coda_out_hdr oh; - struct CodaFid Fid; - struct coda_vattr attr; -}; - - -/* coda_remove: NO_OUT */ -struct coda_remove_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int name; /* Place holder for data. */ -}; - -struct coda_remove_out { - struct coda_out_hdr out; -}; - -/* coda_link: NO_OUT */ -struct coda_link_in { - struct coda_in_hdr ih; - struct CodaFid sourceFid; /* cnode to link *to* */ - struct CodaFid destFid; /* Directory in which to place link */ - int tname; /* Place holder for data. */ -}; - -struct coda_link_out { - struct coda_out_hdr out; -}; - - -/* coda_rename: NO_OUT */ -struct coda_rename_in { - struct coda_in_hdr ih; - struct CodaFid sourceFid; - int srcname; - struct CodaFid destFid; - int destname; -}; - -struct coda_rename_out { - struct coda_out_hdr out; -}; - -/* coda_mkdir: */ -struct coda_mkdir_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - struct coda_vattr attr; - int name; /* Place holder for data. */ -}; - -struct coda_mkdir_out { - struct coda_out_hdr oh; - struct CodaFid Fid; - struct coda_vattr attr; -}; - - -/* coda_rmdir: NO_OUT */ -struct coda_rmdir_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int name; /* Place holder for data. */ -}; - -struct coda_rmdir_out { - struct coda_out_hdr out; -}; - -/* coda_readdir: */ -struct coda_readdir_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int count; - int offset; -}; - -struct coda_readdir_out { - struct coda_out_hdr oh; - int size; - caddr_t data; /* Place holder for data. */ -}; - -/* coda_symlink: NO_OUT */ -struct coda_symlink_in { - struct coda_in_hdr ih; - struct CodaFid Fid; /* Directory to put symlink in */ - int srcname; - struct coda_vattr attr; - int tname; -}; - -struct coda_symlink_out { - struct coda_out_hdr out; -}; - -/* coda_readlink: */ -struct coda_readlink_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -struct coda_readlink_out { - struct coda_out_hdr oh; - int count; - caddr_t data; /* Place holder for data. */ -}; - - -/* coda_fsync: NO_OUT */ -struct coda_fsync_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -struct coda_fsync_out { - struct coda_out_hdr out; -}; - -/* coda_inactive: NO_OUT */ -struct coda_inactive_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -/* coda_vget: */ -struct coda_vget_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -struct coda_vget_out { - struct coda_out_hdr oh; - struct CodaFid Fid; - int vtype; -}; - - -/* CODA_SIGNAL is out-of-band, doesn't need data. */ -/* CODA_INVALIDATE is a venus->kernel call */ -/* CODA_FLUSH is a venus->kernel call */ - -/* coda_purgeuser: */ -/* CODA_PURGEUSER is a venus->kernel call */ -struct coda_purgeuser_out { - struct coda_out_hdr oh; -#ifdef CODA_COMPAT_5 - struct coda_cred cred; -#else - cuid_t uid; -#endif -}; - -/* coda_zapfile: */ -/* CODA_ZAPFILE is a venus->kernel call */ -struct coda_zapfile_out { - struct coda_out_hdr oh; - struct CodaFid Fid; -}; - -/* coda_zapdir: */ -/* CODA_ZAPDIR is a venus->kernel call */ -struct coda_zapdir_out { - struct coda_out_hdr oh; - struct CodaFid Fid; -}; - -/* coda_zapnode: */ -/* CODA_ZAPVNODE is a venus->kernel call */ -struct coda_zapvnode_out { - struct coda_out_hdr oh; -#ifdef CODA_COMPAT_5 - struct coda_cred cred; -#endif - struct CodaFid Fid; -}; - -/* coda_purgefid: */ -/* CODA_PURGEFID is a venus->kernel call */ -struct coda_purgefid_out { - struct coda_out_hdr oh; - struct CodaFid Fid; -}; - -/* coda_replace: */ -/* CODA_REPLACE is a venus->kernel call */ -struct coda_replace_out { /* coda_replace is a venus->kernel call */ - struct coda_out_hdr oh; - struct CodaFid NewFid; - struct CodaFid OldFid; -}; - -/* coda_open_by_fd: */ -struct coda_open_by_fd_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_open_by_fd_out { - struct coda_out_hdr oh; - int fd; -#ifdef _KERNEL - /* not passed from userspace but used in-kernel only */ - struct vnode *vp; -#endif -}; - -/* coda_open_by_path: */ -struct coda_open_by_path_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_open_by_path_out { - struct coda_out_hdr oh; - int path; -}; - -/* coda_statfs: NO_IN */ -struct coda_statfs_in { - struct coda_in_hdr ih; -}; - -struct coda_statfs_out { - struct coda_out_hdr oh; - struct coda_statfs stat; -}; - -/* - * Occasionally, we don't cache the fid returned by CODA_LOOKUP. - * For instance, if the fid is inconsistent. - * This case is handled by setting the top bit of the type result parameter. - */ -#define CODA_NOCACHE 0x80000000 - -union inputArgs { - struct coda_in_hdr ih; /* NB: every struct below begins with an ih */ - struct coda_open_in coda_open; - struct coda_close_in coda_close; - struct coda_ioctl_in coda_ioctl; - struct coda_getattr_in coda_getattr; - struct coda_setattr_in coda_setattr; - struct coda_access_in coda_access; - struct coda_lookup_in coda_lookup; - struct coda_create_in coda_create; - struct coda_remove_in coda_remove; - struct coda_link_in coda_link; - struct coda_rename_in coda_rename; - struct coda_mkdir_in coda_mkdir; - struct coda_rmdir_in coda_rmdir; - struct coda_readdir_in coda_readdir; - struct coda_symlink_in coda_symlink; - struct coda_readlink_in coda_readlink; - struct coda_fsync_in coda_fsync; - struct coda_vget_in coda_vget; - struct coda_open_by_fd_in coda_open_by_fd; - struct coda_open_by_path_in coda_open_by_path; - struct coda_statfs_in coda_statfs; -}; - -union outputArgs { - struct coda_out_hdr oh; /* NB: every struct below begins with an oh */ - struct coda_root_out coda_root; - struct coda_open_out coda_open; - struct coda_ioctl_out coda_ioctl; - struct coda_getattr_out coda_getattr; - struct coda_lookup_out coda_lookup; - struct coda_create_out coda_create; - struct coda_mkdir_out coda_mkdir; - struct coda_readdir_out coda_readdir; - struct coda_readlink_out coda_readlink; - struct coda_vget_out coda_vget; - struct coda_purgeuser_out coda_purgeuser; - struct coda_zapfile_out coda_zapfile; - struct coda_zapdir_out coda_zapdir; - struct coda_zapvnode_out coda_zapvnode; - struct coda_purgefid_out coda_purgefid; - struct coda_replace_out coda_replace; - struct coda_open_by_fd_out coda_open_by_fd; - struct coda_open_by_path_out coda_open_by_path; - struct coda_statfs_out coda_statfs; -}; - -union coda_downcalls { - /* CODA_INVALIDATE is a venus->kernel call */ - /* CODA_FLUSH is a venus->kernel call */ - struct coda_purgeuser_out purgeuser; - struct coda_zapfile_out zapfile; - struct coda_zapdir_out zapdir; - struct coda_zapvnode_out zapvnode; - struct coda_purgefid_out purgefid; - struct coda_replace_out replace; -}; - - -/* - * Used for identifying usage of "Control" and pioctls - */ - -#define PIOCPARM_MASK 0x0000ffff -struct ViceIoctl { - caddr_t in, out; /* Data to be transferred in, or out */ - unsigned short in_size; /* Size of input buffer <= 8K */ - unsigned short out_size; /* Maximum size of output buffer, <= 8K */ -}; - -#if defined(__CYGWIN32__) || defined(DJGPP) -struct PioctlData { - unsigned long cmd; - const char *path; - int follow; - struct ViceIoctl vi; -}; -#else -struct PioctlData { - const char *path; - int follow; - struct ViceIoctl vi; -}; -#endif - -#define CODA_CONTROL ".CONTROL" -#define CODA_CONTROLLEN 8 -#define CTL_VOL -1 -#define CTL_VNO -1 -#define CTL_UNI -1 -#define CTL_INO -1 -#define CTL_FILE "/coda/.CONTROL" - -#ifdef CODA_COMPAT_5 -#define CTL_FID { -1, -1, -1 } -#define IS_CTL_FID(fidp) ((fidp)->Volume == -1 &&\ - (fidp)->Vnode == -1 &&\ - (fidp)->Unique == -1) -#define INVAL_FID { 0, 0, 0 } -#else -#define CTL_FID { { -1, -1, -1, -1 } } -#define IS_CTL_FID(fidp) ((fidp)->opaque[1] == CTL_VOL && \ - (fidp)->opaque[2] == CTL_VNO && \ - (fidp)->opaque[3] == CTL_UNI) -#define INVAL_FID { { 0, 0, 0, 0 } } -#endif - -/* Data passed to mount */ - -#define CODA_MOUNT_VERSION 1 - -struct coda_mount_data { - int version; - int fd; /* Opened device */ -}; - -#endif - diff --git a/sys/fs/coda/coda_fbsd.c b/sys/fs/coda/coda_fbsd.c deleted file mode 100644 index 62d0857..0000000 --- a/sys/fs/coda/coda_fbsd.c +++ /dev/null @@ -1,148 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_fbsd.cr,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/ucred.h> -#include <sys/vnode.h> - -#include <vm/vm.h> -#include <vm/vnode_pager.h> - -#include <fs/coda/coda.h> -#include <fs/coda/cnode.h> -#include <fs/coda/coda_vnops.h> -#include <fs/coda/coda_psdev.h> - -static struct cdevsw codadevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = vc_open, - .d_close = vc_close, - .d_read = vc_read, - .d_write = vc_write, - .d_ioctl = vc_ioctl, - .d_poll = vc_poll, - .d_name = "coda", -}; - -static eventhandler_tag clonetag; - -static LIST_HEAD(, coda_mntinfo) coda_mnttbl; - -/* - * For DEVFS, using bpf & tun drivers as examples. - * - * XXX: Why use a cloned interface, aren't we really just interested in - * having a single /dev/cfs0? It's not clear the coda module knows what to - * do with more than one. - */ -static void coda_fbsd_clone(void *arg, struct ucred *cred, char *name, - int namelen, struct cdev **dev); - -static int -codadev_modevent(module_t mod, int type, void *data) -{ - struct coda_mntinfo *mnt; - - switch (type) { - case MOD_LOAD: - LIST_INIT(&coda_mnttbl); - clonetag = EVENTHANDLER_REGISTER(dev_clone, coda_fbsd_clone, - 0, 1000); - break; - - case MOD_UNLOAD: - /* - * XXXRW: At the very least, a busy check should occur here - * to prevent untimely unload. Much more serious collection - * of allocated memory needs to take place; right now we leak - * like a sieve. - */ - EVENTHANDLER_DEREGISTER(dev_clone, clonetag); - while ((mnt = LIST_FIRST(&coda_mnttbl)) != NULL) { - LIST_REMOVE(mnt, mi_list); - destroy_dev(mnt->dev); - free(mnt, M_CODA); - } - break; - - default: - return (EOPNOTSUPP); - } - return (0); -} - -static moduledata_t codadev_mod = { - "codadev", - codadev_modevent, - NULL -}; -DECLARE_MODULE(codadev, codadev_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); - -static void -coda_fbsd_clone(void *arg, struct ucred *cred, char *name, int namelen, - struct cdev **dev) -{ - struct coda_mntinfo *mnt; - int u; - - if (*dev != NULL) - return; - if (dev_stdclone(name, NULL, "cfs", &u) != 1) - return; - *dev = make_dev(&codadevsw, u, UID_ROOT, GID_WHEEL, 0600, - "cfs%d", u); - dev_ref(*dev); - mnt = malloc(sizeof(struct coda_mntinfo), M_CODA, M_WAITOK|M_ZERO); - LIST_INSERT_HEAD(&coda_mnttbl, mnt, mi_list); - mnt->dev = *dev; -} - -struct coda_mntinfo * -dev2coda_mntinfo(struct cdev *dev) -{ - struct coda_mntinfo *mnt; - - LIST_FOREACH(mnt, &coda_mnttbl, mi_list) { - if (mnt->dev == dev) - return (mnt); - } - return (NULL); -} diff --git a/sys/fs/coda/coda_io.h b/sys/fs/coda/coda_io.h deleted file mode 100644 index 6058cf0..0000000 --- a/sys/fs/coda/coda_io.h +++ /dev/null @@ -1,73 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_io.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - -/*- - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon University. - * Contributers include David Steere, James Kistler, and M. Satyanarayanan. - */ - -#ifndef _CODAIO_H_ -#define _CODAIO_H_ - -/* - * Define ioctl commands for vcioctl, /dev/cfs. - * - * Resize Coda namecache. - */ -#define CODARESIZE _IOW('c', 1, struct coda_resize) - -/* - * Collect statistics. - */ -#define CODASTATS _IO('c', 2) - -/* - * Print cache. - */ -#define CODAPRINT _IO('c', 3) -#define CODATEST _IO('c', 4) - -struct coda_resize { - int hashsize; - int heapsize; -}; - -#endif /* !_CODAIO_H_ */ diff --git a/sys/fs/coda/coda_opstats.h b/sys/fs/coda/coda_opstats.h deleted file mode 100644 index 36805e8..0000000 --- a/sys/fs/coda/coda_opstats.h +++ /dev/null @@ -1,130 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_opstats.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - -#ifndef _CODA_OPSTATS_H_ -#define _CODA_OPSTATS_H_ - -/* - * Operation stats: what the minicache can intercept that *isn't* seen by - * venus. These stats are kept to augment the stats maintained by the - * Volume-Session mechanism. - */ - -/*- - * vfsops: - * mount: not currently bounced to Venus - * umount: nope - * root: only first call, rest is cached. - * statfs: none (bogus) - * sync: none (bogus) - * vget: all - */ -#define CODA_MOUNT_STATS 0 -#define CODA_UMOUNT_STATS 1 -#define CODA_ROOT_STATS 2 -#define CODA_STATFS_STATS 3 -#define CODA_SYNC_STATS 4 -#define CODA_VGET_STATS 5 -#define CODA_VFSOPS_SIZE 6 - -/*- - * vnodeops: - * open: all to venus - * close: all to venus - * rdrw: bogus. Maybe redirected to UFS. - * May call open/close for internal opens/closes - * (Does exec not call open?) - * ioctl: causes a lookupname - * passes through - * select: can't get there from here. - * getattr: can be satsified by cache - * setattr: all go through - * access: can be satisfied by cache - * readlink: can be satisfied by cache - * fsync: passes through - * inactive: passes through - * lookup: can be satisfied by cache - * create: passes through - * remove: passes through - * link: passes through - * rename: passes through - * mkdir: passes through - * rmdir: passes through - * symlink: passes through - * readdir: may be redirected to UFS - * may cause an "internal" open/close - */ -#define CODA_OPEN_STATS 0 -#define CODA_CLOSE_STATS 1 -#define CODA_RDWR_STATS 2 -#define CODA_IOCTL_STATS 3 -#define CODA_SELECT_STATS 4 -#define CODA_GETATTR_STATS 5 -#define CODA_SETATTR_STATS 6 -#define CODA_ACCESS_STATS 7 -#define CODA_READLINK_STATS 8 -#define CODA_FSYNC_STATS 9 -#define CODA_INACTIVE_STATS 10 -#define CODA_LOOKUP_STATS 11 -#define CODA_CREATE_STATS 12 -#define CODA_REMOVE_STATS 13 -#define CODA_LINK_STATS 14 -#define CODA_RENAME_STATS 15 -#define CODA_MKDIR_STATS 16 -#define CODA_RMDIR_STATS 17 -#define CODA_SYMLINK_STATS 18 -#define CODA_READDIR_STATS 19 -#define CODA_VNODEOPS_SIZE 20 - -/* - * I propose the following structres: - */ -struct coda_op_stats { - int opcode; /* vfs opcode */ - long entries; /* number of times call attempted */ - long sat_intrn; /* number of times call satisfied by cache */ - long unsat_intrn; /* number of times call failed in cache, but */ - /* was not bounced to venus proper. */ - long gen_intrn; /* number of times call generated internally */ - /* (do we need that?) */ -}; - -/* - * With each call to the minicache, we'll bump the counters whenver a call is - * satisfied internally (through the cache or through a redirect), and - * whenever an operation is caused internally. Then, we can add the total - * operations caught by the minicache to the world-wide totals, and leave a - * caveat for the specific graphs later. - */ - -#endif /* !_CODA_OPSTATS_H_ */ diff --git a/sys/fs/coda/coda_pioctl.h b/sys/fs/coda/coda_pioctl.h deleted file mode 100644 index 3c9d0c6..0000000 --- a/sys/fs/coda/coda_pioctl.h +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_pioctl.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - -/*- - * Mach Operating System - * Copyright (c) 1989 Carnegie-Mellon University - * Copyright (c) 1988 Carnegie-Mellon University - * Copyright (c) 1987 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * ITC Remote filesystem - vice ioctl interface module - * - * TODO: Find /usr/local/include/viceioctl.h. - */ - -#ifndef _SYS_PIOCTL_H_ -#define _SYS_PIOCTL_H_ - -/* - * The 2K limits above are a consequence of the size of the kernel buffer - * used to buffer requests from the user to venus--2*MAXPATHLEN. The buffer - * pointers may be null, or the counts may be 0 if there are no input or - * output parameters. - */ -#define _VICEIOCTL(id) ((unsigned int )_IOW('V', id, struct ViceIoctl)) - -/* - * Use this macro to define up to 256 vice ioctl's. These ioctl's all - * potentially have in/out parameters--this depends upon the values in the - * ViceIoctl structure. This structure is itself passed into the kernel by - * the normal ioctl parameter passing mechanism. - */ -#define _VALIDVICEIOCTL(com) (com >= _VICEIOCTL(0) && \ - com <= _VICEIOCTL(255)) - -#endif /* !_SYS_PIOCTL_H_ */ diff --git a/sys/fs/coda/coda_psdev.c b/sys/fs/coda/coda_psdev.c deleted file mode 100644 index e982a2c..0000000 --- a/sys/fs/coda/coda_psdev.c +++ /dev/null @@ -1,675 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ -/*- - * Mach Operating System - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. */ - -/* - * These routines define the psuedo device for communication between Coda's - * Venus and Minicache in Mach 2.6. They used to be in cfs_subr.c, but I - * moved them to make it easier to port the Minicache without porting coda. - * -- DCS 10/12/94 - */ - -/* - * These routines are the device entry points for Venus. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/capability.h> -#include <sys/conf.h> -#include <sys/ioccom.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/file.h> /* must come after sys/malloc.h */ -#include <sys/mount.h> -#include <sys/mutex.h> -#include <sys/poll.h> -#include <sys/proc.h> -#include <sys/filedesc.h> - -#include <fs/coda/coda.h> -#include <fs/coda/cnode.h> -#include <fs/coda/coda_io.h> -#include <fs/coda/coda_psdev.h> - -/* - * Variables to determine how Coda sleeps and whether or not it is - * interruptible when it does sleep waiting for Venus. - */ -/* #define CTL_C */ - -#ifdef CTL_C -#include <sys/signalvar.h> -#endif - -int coda_psdev_print_entry = 0; -static int outstanding_upcalls = 0; -int coda_call_sleep = PZERO - 1; -#ifdef CTL_C -int coda_pcatch = PCATCH; -#else -#endif - -#define ENTRY do { \ - if (coda_psdev_print_entry) \ - myprintf(("Entered %s\n", __func__)); \ -} while (0) - -struct vmsg { - TAILQ_ENTRY(vmsg) vm_chain; - caddr_t vm_data; - u_short vm_flags; - u_short vm_inSize; /* Size is at most 5000 bytes */ - u_short vm_outSize; - u_short vm_opcode; /* Copied from data to save ptr deref */ - int vm_unique; - caddr_t vm_sleep; /* Not used by Mach. */ -}; - -#define VM_READ 1 -#define VM_WRITE 2 -#define VM_INTR 4 /* Unused. */ - -int -vc_open(struct cdev *dev, int flag, int mode, struct thread *td) -{ - struct vcomm *vcp; - struct coda_mntinfo *mnt; - - ENTRY; - mnt = dev2coda_mntinfo(dev); - KASSERT(mnt, ("Coda: tried to open uninitialized cfs device")); - vcp = &mnt->mi_vcomm; - if (VC_OPEN(vcp)) - return (EBUSY); - bzero(&(vcp->vc_selproc), sizeof (struct selinfo)); - TAILQ_INIT(&vcp->vc_requests); - TAILQ_INIT(&vcp->vc_replies); - MARK_VC_OPEN(vcp); - mnt->mi_vfsp = NULL; - mnt->mi_rootvp = NULL; - return (0); -} - -int -vc_close(struct cdev *dev, int flag, int mode, struct thread *td) -{ - struct vcomm *vcp; - struct vmsg *vmp, *nvmp = NULL; - struct coda_mntinfo *mi; - int err; - - ENTRY; - mi = dev2coda_mntinfo(dev); - KASSERT(mi, ("Coda: closing unknown cfs device")); - vcp = &mi->mi_vcomm; - KASSERT(VC_OPEN(vcp), ("Coda: closing unopened cfs device")); - - /* - * Prevent future operations on this vfs from succeeding by - * auto-unmounting any vfs mounted via this device. This frees user - * or sysadm from having to remember where all mount points are - * located. Put this before WAKEUPs to avoid queuing new messages - * between the WAKEUP and the unmount (which can happen if we're - * unlucky). - */ - if (mi->mi_rootvp == NULL) { - /* - * Just a simple open/close with no mount. - */ - MARK_VC_CLOSED(vcp); - return (0); - } - - /* - * Let unmount know this is for real. - */ - VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING; - coda_unmounting(mi->mi_vfsp); - - /* - * Wakeup clients so they can return. - */ - outstanding_upcalls = 0; - TAILQ_FOREACH_SAFE(vmp, &vcp->vc_requests, vm_chain, nvmp) { - /* - * Free signal request messages and don't wakeup cause no one - * is waiting. - */ - if (vmp->vm_opcode == CODA_SIGNAL) { - CODA_FREE((caddr_t)vmp->vm_data, - (u_int)VC_IN_NO_DATA); - CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg)); - continue; - } - outstanding_upcalls++; - wakeup(&vmp->vm_sleep); - } - TAILQ_FOREACH(vmp, &vcp->vc_replies, vm_chain) { - outstanding_upcalls++; - wakeup(&vmp->vm_sleep); - } - MARK_VC_CLOSED(vcp); - if (outstanding_upcalls) { -#ifdef CODA_VERBOSE - printf("presleep: outstanding_upcalls = %d\n", - outstanding_upcalls); -#endif - (void) tsleep(&outstanding_upcalls, coda_call_sleep, - "coda_umount", 0); -#ifdef CODA_VERBOSE - printf("postsleep: outstanding_upcalls = %d\n", - outstanding_upcalls); -#endif - } - err = dounmount(mi->mi_vfsp, flag, td); - if (err) - myprintf(("Error %d unmounting vfs in vcclose(%s)\n", err, - devtoname(dev))); - return (0); -} - -int -vc_read(struct cdev *dev, struct uio *uiop, int flag) -{ - struct vcomm *vcp; - struct vmsg *vmp; - int error = 0; - - ENTRY; - vcp = &dev2coda_mntinfo(dev)->mi_vcomm; - - /* - * Get message at head of request queue. - */ - vmp = TAILQ_FIRST(&vcp->vc_requests); - if (vmp == NULL) - return (0); /* Nothing to read */ - - /* - * Move the input args into userspace. - * - * XXXRW: This is not safe in the presence of >1 reader, as vmp is - * still on the head of the list. - */ - uiop->uio_rw = UIO_READ; - error = uiomove(vmp->vm_data, vmp->vm_inSize, uiop); - if (error) { - myprintf(("vcread: error (%d) on uiomove\n", error)); - error = EINVAL; - } - TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain); - - /* - * If request was a signal, free up the message and don't enqueue it - * in the reply queue. - */ - if (vmp->vm_opcode == CODA_SIGNAL) { - if (codadebug) - myprintf(("vcread: signal msg (%d, %d)\n", - vmp->vm_opcode, vmp->vm_unique)); - CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA); - CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg)); - return (error); - } - vmp->vm_flags |= VM_READ; - TAILQ_INSERT_TAIL(&vcp->vc_replies, vmp, vm_chain); - return (error); -} - -int -vc_write(struct cdev *dev, struct uio *uiop, int flag) -{ - struct vcomm *vcp; - struct vmsg *vmp; - struct coda_out_hdr *out; - u_long seq; - u_long opcode; - int buf[2]; - int error = 0; - - ENTRY; - vcp = &dev2coda_mntinfo(dev)->mi_vcomm; - - /* - * Peek at the opcode, unique without transfering the data. - */ - uiop->uio_rw = UIO_WRITE; - error = uiomove((caddr_t)buf, sizeof(int) * 2, uiop); - if (error) { - myprintf(("vcwrite: error (%d) on uiomove\n", error)); - return (EINVAL); - } - opcode = buf[0]; - seq = buf[1]; - if (codadebug) - myprintf(("vcwrite got a call for %ld.%ld\n", opcode, seq)); - if (DOWNCALL(opcode)) { - union outputArgs pbuf; - - /* - * Get the rest of the data. - */ - uiop->uio_rw = UIO_WRITE; - error = uiomove((caddr_t)&pbuf.coda_purgeuser.oh.result, - sizeof(pbuf) - (sizeof(int)*2), uiop); - if (error) { - myprintf(("vcwrite: error (%d) on uiomove (Op %ld " - "seq %ld)\n", error, opcode, seq)); - return (EINVAL); - } - return (handleDownCall(dev2coda_mntinfo(dev), opcode, &pbuf)); - } - - /* - * Look for the message on the (waiting for) reply queue. - */ - TAILQ_FOREACH(vmp, &vcp->vc_replies, vm_chain) { - if (vmp->vm_unique == seq) - break; - } - if (vmp == NULL) { - if (codadebug) - myprintf(("vcwrite: msg (%ld, %ld) not found\n", - opcode, seq)); - return (ESRCH); - } - - /* - * Remove the message from the reply queue. - */ - TAILQ_REMOVE(&vcp->vc_replies, vmp, vm_chain); - - /* - * Move data into response buffer. - */ - out = (struct coda_out_hdr *)vmp->vm_data; - - /* - * Don't need to copy opcode and uniquifier. - * - * Get the rest of the data. - */ - if (vmp->vm_outSize < uiop->uio_resid) { - myprintf(("vcwrite: more data than asked for (%d < %zd)\n", - vmp->vm_outSize, uiop->uio_resid)); - - /* - * Notify caller of the error. - */ - wakeup(&vmp->vm_sleep); - return (EINVAL); - } - - /* - * Save the value. - */ - buf[0] = uiop->uio_resid; - uiop->uio_rw = UIO_WRITE; - error = uiomove((caddr_t) &out->result, vmp->vm_outSize - - (sizeof(int) * 2), uiop); - if (error) { - myprintf(("vcwrite: error (%d) on uiomove (op %ld seq %ld)\n", - error, opcode, seq)); - return (EINVAL); - } - - /* - * I don't think these are used, but just in case. - * - * XXX - aren't these two already correct? -bnoble - */ - out->opcode = opcode; - out->unique = seq; - vmp->vm_outSize = buf[0]; /* Amount of data transferred? */ - vmp->vm_flags |= VM_WRITE; - error = 0; - if (opcode == CODA_OPEN_BY_FD) { - struct coda_open_by_fd_out *tmp = - (struct coda_open_by_fd_out *)out; - struct file *fp; - struct vnode *vp = NULL; - - if (tmp->oh.result == 0) { - error = getvnode(uiop->uio_td->td_proc->p_fd, CAP_WRITE, - tmp->fd, &fp); - if (!error) { - /* - * XXX: Since the whole driver runs with - * Giant, don't actually need to acquire it - * explicitly here yet. - */ - mtx_lock(&Giant); - vp = fp->f_vnode; - VREF(vp); - fdrop(fp, uiop->uio_td); - mtx_unlock(&Giant); - } - } - tmp->vp = vp; - } - wakeup(&vmp->vm_sleep); - return (error); -} - -int -vc_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, - struct thread *t) -{ - - ENTRY; - switch(cmd) { - case CODARESIZE: - return (ENODEV); - - case CODASTATS: - return (ENODEV); - - case CODAPRINT: - return (ENODEV); - - case CIOC_KERNEL_VERSION: - switch (*(u_int *)addr) { - case 0: - *(u_int *)addr = coda_kernel_version; - return (0); - - case 1: - case 2: - if (coda_kernel_version != *(u_int *)addr) - return (ENOENT); - else - return (0); - - default: - return (ENOENT); - } - - default: - return (EINVAL); - } -} - -int -vc_poll(struct cdev *dev, int events, struct thread *td) -{ - struct vcomm *vcp; - int event_msk = 0; - - ENTRY; - vcp = &dev2coda_mntinfo(dev)->mi_vcomm; - event_msk = events & (POLLIN|POLLRDNORM); - if (!event_msk) - return (0); - if (!TAILQ_EMPTY(&vcp->vc_requests)) - return (events & (POLLIN|POLLRDNORM)); - selrecord(td, &(vcp->vc_selproc)); - return (0); -} - -/* - * Statistics. - */ -struct coda_clstat coda_clstat; - -/* - * Key question: whether to sleep interuptably or uninteruptably when waiting - * for Venus. The former seems better (cause you can ^C a job), but then - * GNU-EMACS completion breaks. Use tsleep with no timeout, and no longjmp - * happens. But, when sleeping "uninterruptibly", we don't get told if it - * returns abnormally (e.g. kill -9). - */ -int -coda_call(struct coda_mntinfo *mntinfo, int inSize, int *outSize, - caddr_t buffer) -{ - struct vcomm *vcp; - struct vmsg *vmp; - int error; -#ifdef CTL_C - struct thread *td = curthread; - struct proc *p = td->td_proc; - sigset_t psig_omask; - sigset_t tempset; - int i; -#endif - - /* - * Unlikely, but could be a race condition with a dying warden. - */ - if (mntinfo == NULL) - return ENODEV; - vcp = &(mntinfo->mi_vcomm); - coda_clstat.ncalls++; - coda_clstat.reqs[((struct coda_in_hdr *)buffer)->opcode]++; - if (!VC_OPEN(vcp)) - return (ENODEV); - CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg)); - - /* - * Format the request message. - */ - vmp->vm_data = buffer; - vmp->vm_flags = 0; - vmp->vm_inSize = inSize; - vmp->vm_outSize - = *outSize ? *outSize : inSize; /* |buffer| >= inSize */ - vmp->vm_opcode = ((struct coda_in_hdr *)buffer)->opcode; - vmp->vm_unique = ++vcp->vc_seq; - if (codadebug) - myprintf(("Doing a call for %d.%d\n", vmp->vm_opcode, - vmp->vm_unique)); - - /* - * Fill in the common input args. - */ - ((struct coda_in_hdr *)buffer)->unique = vmp->vm_unique; - - /* - * Append msg to request queue and poke Venus. - */ - TAILQ_INSERT_TAIL(&vcp->vc_requests, vmp, vm_chain); - selwakeuppri(&(vcp->vc_selproc), coda_call_sleep); - - /* - * We can be interrupted while we wait for Venus to process our - * request. If the interrupt occurs before Venus has read the - * request, we dequeue and return. If it occurs after the read but - * before the reply, we dequeue, send a signal message, and return. - * If it occurs after the reply we ignore it. In no case do we want - * to restart the syscall. If it was interrupted by a venus shutdown - * (vcclose), return ENODEV. - * - * Ignore return, we have to check anyway. - */ -#ifdef CTL_C - /* - * This is work in progress. Setting coda_pcatch lets tsleep - * reawaken on a ^c or ^z. The problem is that emacs sets certain - * interrupts as SA_RESTART. This means that we should exit sleep - * handle the "signal" and then go to sleep again. Mostly this is - * done by letting the syscall complete and be restarted. We are not - * idempotent and can not do this. A better solution is necessary. - */ - i = 0; - PROC_LOCK(p); - psig_omask = td->td_sigmask; - do { - error = msleep(&vmp->vm_sleep, &p->p_mtx, - (coda_call_sleep|coda_pcatch), "coda_call", hz*2); - if (error == 0) - break; - else if (error == EWOULDBLOCK) { -#ifdef CODA_VERBOSE - printf("coda_call: tsleep TIMEOUT %d sec\n", 2+2*i); -#endif - } - else { - SIGEMPTYSET(tempset); - SIGADDSET(tempset, SIGIO); - if (SIGSETEQ(td->td_siglist, tempset)) { - SIGADDSET(td->td_sigmask, SIGIO); -#ifdef CODA_VERBOSE - printf("coda_call: tsleep returns %d SIGIO, " - "cnt %d\n", error, i); -#endif - } else { - SIGDELSET(tempset, SIGIO); - SIGADDSET(tempset, SIGALRM); - if (SIGSETEQ(td->td_siglist, tempset)) { - SIGADDSET(td->td_sigmask, SIGALRM); -#ifdef CODA_VERBOSE - printf("coda_call: tsleep returns " - "%d SIGALRM, cnt %d\n", error, i); -#endif - } else { -#ifdef CODA_VERBOSE - printf("coda_call: tsleep returns " - "%d, cnt %d\n", error, i); -#endif - -#ifdef notyet - tempset = td->td_siglist; - SIGSETNAND(tempset, td->td_sigmask); - printf("coda_call: siglist = %p, " - "sigmask = %p, mask %p\n", - td->td_siglist, td->td_sigmask, - tempset); - break; - SIGSETOR(td->td_sigmask, td->td_siglist); - tempset = td->td_siglist; - SIGSETNAND(tempset, td->td_sigmask); - printf("coda_call: new mask, " - "siglist = %p, sigmask = %p, " - "mask %p\n", td->td_siglist, - td->td_sigmask, tempset); -#endif - } - } - } - } while (error && i++ < 128 && VC_OPEN(vcp)); - td->td_sigmask = psig_omask; - signotify(td); - PROC_UNLOCK(p); -#else - (void)tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0); -#endif - if (VC_OPEN(vcp)) { - /* - * Venus is still alive. - * - * Op went through, interrupt or not... - */ - if (vmp->vm_flags & VM_WRITE) { - error = 0; - *outSize = vmp->vm_outSize; - } else if (!(vmp->vm_flags & VM_READ)) { - /* Interrupted before venus read it. */ -#ifdef CODA_VERBOSE - if (1) -#else - if (codadebug) -#endif - myprintf(("interrupted before read: op = " - "%d.%d, flags = %x\n", vmp->vm_opcode, - vmp->vm_unique, vmp->vm_flags)); - TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain); - error = EINTR; - } else { - /* - * (!(vmp->vm_flags & VM_WRITE)) means interrupted - * after upcall started. - * - * Interrupted after start of upcall, send venus a - * signal. - */ - struct coda_in_hdr *dog; - struct vmsg *svmp; - -#ifdef CODA_VERBOSE - if (1) -#else - if (codadebug) -#endif - myprintf(("Sending Venus a signal: op = " - "%d.%d, flags = %x\n", vmp->vm_opcode, - vmp->vm_unique, vmp->vm_flags)); - TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain); - error = EINTR; - CODA_ALLOC(svmp, struct vmsg *, sizeof(struct vmsg)); - CODA_ALLOC((svmp->vm_data), char *, - sizeof(struct coda_in_hdr)); - dog = (struct coda_in_hdr *)svmp->vm_data; - svmp->vm_flags = 0; - dog->opcode = svmp->vm_opcode = CODA_SIGNAL; - dog->unique = svmp->vm_unique = vmp->vm_unique; - svmp->vm_inSize = sizeof (struct coda_in_hdr); -/*??? rvb */ svmp->vm_outSize = sizeof (struct coda_in_hdr); - if (codadebug) - myprintf(("coda_call: enqueing signal msg " - "(%d, %d)\n", svmp->vm_opcode, - svmp->vm_unique)); - - /* - * Insert at head of queue! - * - * XXXRW: Actually, the tail. - */ - TAILQ_INSERT_TAIL(&vcp->vc_requests, svmp, vm_chain); - selwakeuppri(&(vcp->vc_selproc), coda_call_sleep); - } - } else { - /* If venus died (!VC_OPEN(vcp)) */ - if (codadebug) - myprintf(("vcclose woke op %d.%d flags %d\n", - vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags)); - error = ENODEV; - } - CODA_FREE(vmp, sizeof(struct vmsg)); - if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0)) - wakeup(&outstanding_upcalls); - if (!error) - error = ((struct coda_out_hdr *)buffer)->result; - return (error); -} diff --git a/sys/fs/coda/coda_psdev.h b/sys/fs/coda/coda_psdev.h deleted file mode 100644 index 021456b..0000000 --- a/sys/fs/coda/coda_psdev.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -#ifndef _CODA_PSDEV_H_ -#define _CODA_PSDEV_H_ - -/* - * Prototypes for cfs device operations. - */ -d_open_t vc_open; -d_close_t vc_close; -d_read_t vc_read; -d_write_t vc_write; -d_ioctl_t vc_ioctl; -d_poll_t vc_poll; - -#endif /* !_CODA_PSDEV_H_ */ diff --git a/sys/fs/coda/coda_subr.c b/sys/fs/coda/coda_subr.c deleted file mode 100644 index a7ae354..0000000 --- a/sys/fs/coda/coda_subr.c +++ /dev/null @@ -1,628 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_subr.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ - -/*- - * Mach Operating System - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. - */ - -/*- - * NOTES: rvb - * 1. Added coda_unmounting to mark all cnodes as being UNMOUNTING. This - * has to be done before dounmount is called. Because some of the - * routines that dounmount calls before coda_unmounted might try to - * force flushes to venus. The vnode pager does this. - * 2. coda_unmounting marks all cnodes scanning coda_cache. - * 3. cfs_checkunmounting (under DEBUG) checks all cnodes by chasing the - * vnodes under the /coda mount point. - * 4. coda_cacheprint (under DEBUG) prints names with vnode/cnode address. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/mount.h> - -#include <fs/coda/coda.h> -#include <fs/coda/cnode.h> -#include <fs/coda/coda_subr.h> - -static int coda_active = 0; -static int coda_reuse = 0; -static int coda_new = 0; - -static struct cnode *coda_freelist = NULL; -static struct cnode *coda_cache[CODA_CACHESIZE]; - -#define CNODE_NEXT(cp) ((cp)->c_next) - -#ifdef CODA_COMPAT_5 -#define coda_hash(fid) (((fid)->Volume + (fid)->Vnode) & (CODA_CACHESIZE-1)) -#define IS_DIR(cnode) (cnode.Vnode & 0x1) -#else -#define coda_hash(fid) (coda_f2i(fid) & (CODA_CACHESIZE-1)) -#define IS_DIR(cnode) (cnode.opaque[2] & 0x1) -#endif - -/* - * Allocate a cnode. - */ -struct cnode * -coda_alloc(void) -{ - struct cnode *cp; - - if (coda_freelist != NULL) { - cp = coda_freelist; - coda_freelist = CNODE_NEXT(cp); - coda_reuse++; - } else { - CODA_ALLOC(cp, struct cnode *, sizeof(struct cnode)); - - /* - * FreeBSD vnodes don't have any Pager info in them ('cause - * there are no external pagers, duh!). - */ -#define VNODE_VM_INFO_INIT(vp) /* MT */ - VNODE_VM_INFO_INIT(CTOV(cp)); - coda_new++; - } - bzero(cp, sizeof (struct cnode)); - return (cp); -} - -/* - * Deallocate a cnode. - */ -void -coda_free(struct cnode *cp) -{ - - CNODE_NEXT(cp) = coda_freelist; - coda_freelist = cp; -} - -/* - * Put a cnode in the hash table. - */ -void -coda_save(struct cnode *cp) -{ - - CNODE_NEXT(cp) = coda_cache[coda_hash(&cp->c_fid)]; - coda_cache[coda_hash(&cp->c_fid)] = cp; -} - -/* - * Remove a cnode from the hash table. - */ -void -coda_unsave(struct cnode *cp) -{ - struct cnode *ptr; - struct cnode *ptrprev = NULL; - - ptr = coda_cache[coda_hash(&cp->c_fid)]; - while (ptr != NULL) { - if (ptr == cp) { - if (ptrprev == NULL) - coda_cache[coda_hash(&cp->c_fid)] = - CNODE_NEXT(ptr); - else - CNODE_NEXT(ptrprev) = CNODE_NEXT(ptr); - CNODE_NEXT(cp) = (struct cnode *)NULL; - return; - } - ptrprev = ptr; - ptr = CNODE_NEXT(ptr); - } -} - -/* - * Lookup a cnode by fid. If the cnode is dying, it is bogus so skip it. - * - * NOTE: this allows multiple cnodes with same fid -- dcs 1/25/95 - */ -struct cnode * -coda_find(struct CodaFid *fid) -{ - struct cnode *cp; - - cp = coda_cache[coda_hash(fid)]; - while (cp) { - if (coda_fid_eq(&(cp->c_fid), fid) && (!IS_UNMOUNTING(cp))) { - coda_active++; - return (cp); - } - cp = CNODE_NEXT(cp); - } - return (NULL); -} - -/* - * Clear all cached access control decisions from Coda. - */ -static void -coda_acccache_purge(struct mount *mnt) -{ - struct cnode *cp; - int hash; - - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == mnt && VALID_ACCCACHE(cp)) { - CODADEBUG(CODA_FLUSH, myprintf(("acccache " - "purge fid %s uid %d mode 0x%x\n", - coda_f2s(&cp->c_fid), cp->c_cached_uid, - (int)cp->c_cached_mode));); - cp->c_flags &= ~C_ACCCACHE; - } - } - } -} - -/* - * When a user loses their tokens (or other related events), we invalidate - * any cached access rights in the access cache. In the Linux version of - * Coda, we maintain a global epoch and simply bump it to invalidate all - * cached results generated in the epoch. For now, we walk all cnodes and - * manually invalidate just that uid in FreeBSD. - */ -static void -coda_acccache_purgeuser(struct mount *mnt, uid_t uid) -{ - struct cnode *cp; - int hash; - - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == mnt && - VALID_ACCCACHE(cp) && (cp->c_cached_uid == uid)) { - CODADEBUG(CODA_PURGEUSER, myprintf(( - "acccache purgeuser fid %s uid %d mode " - "0x%x\n", coda_f2s(&cp->c_fid), - cp->c_cached_uid, (int)cp->c_cached_mode));); - cp->c_flags &= ~C_ACCCACHE; - } - } - } -} - -/* - * coda_kill is called as a side effect to vcopen. To prevent any cnodes - * left around from an earlier run of a venus or warden from causing problems - * with the new instance, mark any outstanding cnodes as dying. Future - * operations on these cnodes should fail (excepting coda_inactive of - * course!). Since multiple venii/wardens can be running, only kill the - * cnodes for a particular entry in the coda_mnttbl. -- DCS 12/1/94 - * - * XXX: I don't believe any special behavior is required with respect to the - * global namecache here, as /coda will have unmounted and hence cache_flush - * will have run...? - */ -int -coda_kill(struct mount *whoIam, enum dc_status dcstat) -{ - int hash, count = 0; - struct cnode *cp; - - /*- - * Algorithm is as follows: - * Second, flush whatever vnodes we can from the name cache. - * - * Finally, step through whatever is left and mark them dying. - * This prevents any operation at all. - * - * This is slightly overkill, but should work. Eventually it'd be - * nice to only flush those entries from the namecache that reference - * a vnode in this vfs. - * - * XXXRW: Perhaps we no longer need to purge the name cache when - * using the VFS name cache, as unmount will do that. - */ - cache_purgevfs(whoIam); - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash];cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == whoIam) { -#ifdef DEBUG - printf("coda_kill: vp %p, cp %p\n", CTOV(cp), - cp); -#endif - count++; - CODADEBUG(CODA_FLUSH, myprintf(("Live cnode " - "fid %s flags %d count %d\n", - coda_f2s(&cp->c_fid), cp->c_flags, - vrefcnt(CTOV(cp))));); - } - } - } - return (count); -} - -/* - * There are two reasons why a cnode may be in use, it may be in the name - * cache or it may be executing. - */ -void -coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat) -{ - int hash; - struct cnode *cp; - - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_FLUSH]++; - - coda_acccache_purge(mnt->mi_vfsp); - cache_purgevfs(mnt->mi_vfsp); - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - /* - * Only files that can be executed need to be flushed - * from the VM. - * - * NOTE: Currently this doesn't do anything, but - * perhaps it should? - */ - if (!IS_DIR(cp->c_fid)) - coda_vmflush(cp); - } - } -} - -/* - * As a debugging measure, print out any cnodes that lived through a name - * cache flush. - */ -void -coda_testflush(void) -{ - int hash; - struct cnode *cp; - - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) - myprintf(("Live cnode fid %s count %d\n", - coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount)); - } -} - -/* - * First, step through all cnodes and mark them unmounting. FreeBSD kernels - * may try to fsync them now that venus is dead, which would be a bad thing. - */ -void -coda_unmounting(struct mount *whoIam) -{ - int hash; - struct cnode *cp; - - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == whoIam) { - if (cp->c_flags & (C_LOCKED|C_WANTED)) { - printf("coda_unmounting: Unlocking " - "%p\n", cp); - cp->c_flags &= ~(C_LOCKED|C_WANTED); - wakeup((caddr_t) cp); - } - cp->c_flags |= C_UNMOUNTING; - } - } - } -} - -#ifdef DEBUG -void -coda_checkunmounting(struct mount *mp) -{ - struct vnode *vp, *nvp; - struct cnode *cp; - int count = 0, bad = 0; - - MNT_VNODE_FOREACH_ALL(vp, mp, nvp) { - cp = VTOC(vp); - count++; - if (!(cp->c_flags & C_UNMOUNTING)) { - bad++; - printf("vp %p, cp %p missed\n", vp, cp); - cp->c_flags |= C_UNMOUNTING; - } - VI_UNLOCK(vp); - } -} - -void -coda_cacheprint(struct mount *whoIam) -{ - int hash; - struct cnode *cp; - int count = 0; - - printf("coda_cacheprint: coda_ctlvp %p, cp %p", coda_ctlvp, - VTOC(coda_ctlvp)); - -#if 0 - coda_nc_name(VTOC(coda_ctlvp)); -#endif - printf("\n"); - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == whoIam) { - printf("coda_cacheprint: vp %p, cp %p", - CTOV(cp), cp); -#if 0 - coda_nc_name(cp); -#endif - printf("\n"); - count++; - } - } - } - printf("coda_cacheprint: count %d\n", count); -} -#endif - -/*- - * There are 6 cases where invalidations occur. The semantics of each is - * listed here: - * - * CODA_FLUSH -- Flush all entries from the name cache and the cnode - * cache. - * - * CODA_PURGEUSER -- Flush all entries from the name cache for a specific - * user. This call is a result of token expiration. - * - * The next two are the result of callbacks on a file or directory: - * - * CODA_ZAPDIR -- Flush the attributes for the dir from its cnode. Zap - * all children of this directory from the namecache. - * - * CODA_ZAPFILE -- Flush the attributes for a file. - * - * The fifth is a result of Venus detecting an inconsistent file: - * - * CODA_PURGEFID -- Flush the attribute for the file; if it is a dir (odd - * vnode), purge its children from the namecache; remove - * the file from the namecache. - * - * The sixth allows Venus to replace local fids with global ones during - * reintegration. - * - * CODA_REPLACE -- Replace one CodaFid with another throughout the name - * cache. - */ -int -handleDownCall(struct coda_mntinfo *mnt, int opcode, union outputArgs *out) -{ - int error; - - /* - * Handle invalidate requests. - */ - switch (opcode) { - case CODA_FLUSH: { - coda_flush(mnt, IS_DOWNCALL); - - /* Print any remaining cnodes. */ - CODADEBUG(CODA_FLUSH, coda_testflush();); - return (0); - } - - case CODA_PURGEUSER: { - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_PURGEUSER]++; - - /* XXX - need to prevent fsync's. */ - - /* - * Purge any access cache entries for the uid. - */ -#ifdef CODA_COMPAT_5 - coda_acccache_purgeuser(mnt->mi_vfsp, - out->coda_purgeuser.cred.cr_uid); -#else - coda_acccache_purgeuser(mnt->mi_vfsp, - out->coda_purgeuser.uid); -#endif - return (0); - } - - case CODA_ZAPFILE: { - struct cnode *cp; - - error = 0; - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_ZAPFILE]++; - cp = coda_find(&out->coda_zapfile.Fid); - if (cp != NULL) { - vref(CTOV(cp)); - cache_purge(CTOV(cp)); - cp->c_flags &= ~(C_VATTR | C_ACCCACHE); - ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall"); - if (VOP_IS_TEXT(CTOV(cp))) - error = coda_vmflush(cp); - CODADEBUG(CODA_ZAPFILE, - myprintf(("zapfile: fid = %s, refcnt = %d, error = " - "%d\n", coda_f2s(&cp->c_fid), - CTOV(cp)->v_usecount - 1, error));); - if (vrefcnt(CTOV(cp)) == 1) - cp->c_flags |= C_PURGING; - vrele(CTOV(cp)); - } - return (error); - } - - case CODA_ZAPDIR: { - struct cnode *cp; - - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_ZAPDIR]++; - cp = coda_find(&out->coda_zapdir.Fid); - if (cp != NULL) { - vref(CTOV(cp)); - cache_purge(CTOV(cp)); - cp->c_flags &= ~(C_VATTR | C_ACCCACHE); - CODADEBUG(CODA_ZAPDIR, myprintf(("zapdir: fid = %s, " - "refcnt = %d\n", coda_f2s(&cp->c_fid), - CTOV(cp)->v_usecount - 1));); - if (vrefcnt(CTOV(cp)) == 1) - cp->c_flags |= C_PURGING; - vrele(CTOV(cp)); - } - return (0); - } - - case CODA_PURGEFID: { - struct cnode *cp; - - error = 0; - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_PURGEFID]++; - cp = coda_find(&out->coda_purgefid.Fid); - if (cp != NULL) { - vref(CTOV(cp)); - cache_purge(CTOV(cp)); - cp->c_flags &= ~(C_VATTR | C_ACCCACHE); - ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall"); - if (!(IS_DIR(out->coda_purgefid.Fid)) - && VOP_IS_TEXT(CTOV(cp))) - error = coda_vmflush(cp); - CODADEBUG(CODA_PURGEFID, myprintf(("purgefid: fid " - "= %s, refcnt = %d, error = %d\n", - coda_f2s(&cp->c_fid), - CTOV(cp)->v_usecount - 1, error));); - if (vrefcnt(CTOV(cp)) == 1) - cp->c_flags |= C_PURGING; - vrele(CTOV(cp)); - } - return (error); - } - - case CODA_REPLACE: { - struct cnode *cp = NULL; - - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_REPLACE]++; - cp = coda_find(&out->coda_replace.OldFid); - if (cp != NULL) { - /* - * Remove the cnode from the hash table, replace the - * fid, and reinsert. Clear the attribute cache as - * the "inode number" may have changed (it's just a - * hash of the fid, and the fid is changing). - */ - vref(CTOV(cp)); - coda_unsave(cp); - cp->c_fid = out->coda_replace.NewFid; - cp->c_flags &= ~C_VATTR; - coda_save(cp); - CODADEBUG(CODA_REPLACE, myprintf(("replace: oldfid " - "= %s, newfid = %s, cp = %p\n", - coda_f2s(&out->coda_replace.OldFid), - coda_f2s(&cp->c_fid), cp));); - vrele(CTOV(cp)); - } - return (0); - } - default: - myprintf(("handleDownCall: unknown opcode %d\n", opcode)); - return (EINVAL); - } -} - -int -coda_vmflush(struct cnode *cp) -{ - - return (0); -} - -/* - * Kernel-internal debugging switches. - */ -void -coda_debugon(void) -{ - - codadebug = -1; - coda_vnop_print_entry = 1; - coda_psdev_print_entry = 1; - coda_vfsop_print_entry = 1; -} - -void -coda_debugoff(void) -{ - - codadebug = 0; - coda_vnop_print_entry = 0; - coda_psdev_print_entry = 0; - coda_vfsop_print_entry = 0; -} - -/*- - * Utilities used by both client and server - * Standard levels: - * 0) no debugging - * 1) hard failures - * 2) soft failures - * 3) current test software - * 4) main procedure entry points - * 5) main procedure exit points - * 6) utility procedure entry points - * 7) utility procedure exit points - * 8) obscure procedure entry points - * 9) obscure procedure exit points - * 10) random stuff - * 11) all <= 1 - * 12) all <= 2 - * 13) all <= 3 - * ... - */ diff --git a/sys/fs/coda/coda_subr.h b/sys/fs/coda/coda_subr.h deleted file mode 100644 index b8edfd3..0000000 --- a/sys/fs/coda/coda_subr.h +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_subr.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -#ifndef _CODA_SUBR_H_ -#define _CODA_SUBR_H_ - -struct cnode *coda_alloc(void); -void coda_free(struct cnode *cp); -struct cnode *coda_find(struct CodaFid *fid); -void coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat); -void coda_testflush(void); -void coda_checkunmounting(struct mount *mp); -void coda_cacheprint(struct mount *whoIam); -void coda_debugon(void); -void coda_debugoff(void); -int coda_kill(struct mount *whoIam, enum dc_status dcstat); -void coda_save(struct cnode *cp); -void coda_unsave(struct cnode *cp); - -#endif /* !_CODA_SUBR_H_ */ diff --git a/sys/fs/coda/coda_venus.c b/sys/fs/coda/coda_venus.c deleted file mode 100644 index 9d012dd..0000000 --- a/sys/fs/coda/coda_venus.c +++ /dev/null @@ -1,705 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/cfs/coda_venus.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/fcntl.h> -#include <sys/ioccom.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/sx.h> - -#include <fs/coda/coda.h> -#include <fs/coda/cnode.h> -#include <fs/coda/coda_venus.h> -#include <fs/coda/coda_pioctl.h> - -#define DECL_NO_IN(name) \ - struct coda_in_hdr *inp; \ - struct name ## _out *outp; \ - int name ## _size = sizeof (struct coda_in_hdr); \ - int Isize = sizeof (struct coda_in_hdr); \ - int Osize = sizeof (struct name ## _out); \ - int error - -#define DECL(name) \ - struct name ## _in *inp; \ - struct name ## _out *outp; \ - int name ## _size = sizeof (struct name ## _in); \ - int Isize = sizeof (struct name ## _in); \ - int Osize = sizeof (struct name ## _out); \ - int error - -#define DECL_NO_OUT(name) \ - struct name ## _in *inp; \ - struct coda_out_hdr *outp; \ - int name ## _size = sizeof (struct name ## _in); \ - int Isize = sizeof (struct name ## _in); \ - int Osize = sizeof (struct coda_out_hdr); \ - int error - -#define ALLOC_NO_IN(name) \ - if (Osize > name ## _size) \ - name ## _size = Osize; \ - CODA_ALLOC(inp, struct coda_in_hdr *, name ## _size); \ - outp = (struct name ## _out *) inp - -#define ALLOC(name) \ - if (Osize > name ## _size) \ - name ## _size = Osize; \ - CODA_ALLOC(inp, struct name ## _in *, name ## _size); \ - outp = (struct name ## _out *) inp - -#define ALLOC_NO_OUT(name) \ - if (Osize > name ## _size) \ - name ## _size = Osize; \ - CODA_ALLOC(inp, struct name ## _in *, name ## _size); \ - outp = (struct coda_out_hdr *) inp - -#define STRCPY(struc, name, len) \ - bcopy(name, (char *)inp + (int)inp->struc, len); \ - ((char*)inp + (int)inp->struc)[len++] = 0; \ - Isize += len - -#ifdef CODA_COMPAT_5 -#define INIT_IN(in, op, ident, p) do { \ - (in)->opcode = (op); \ - sx_slock(&proctree_lock); \ - (in)->pid = p ? p->p_pid : -1; \ - (in)->pgid = p ? p->p_pgid : -1; \ - (in)->sid = (p && p->p_session && p->p_session->s_leader) ? \ - (p->p_session->s_leader->p_pid) : -1; \ - sx_sunlock(&proctree_lock); \ - if (ident != NOCRED) { \ - (in)->cred.cr_uid = ident->cr_uid; \ - (in)->cred.cr_groupid = ident->cr_gid; \ - } else { \ - bzero(&((in)->cred),sizeof(struct coda_cred)); \ - (in)->cred.cr_uid = -1; \ - (in)->cred.cr_groupid = -1; \ - } \ -} while (0) -#else -#define INIT_IN(in, op, ident, p) do { \ - (in)->opcode = (op); \ - (in)->pid = p ? p->p_pid : -1; \ - (in)->pgid = p ? p->p_pgid : -1; \ - if (ident != NOCRED) \ - (in)->uid = ident->cr_uid; \ - else \ - (in)->uid = -1; \ -} while (0) -#endif - -#define CNV_OFLAG(to, from) do { \ - to = 0; \ - if (from & FREAD) to |= C_O_READ; \ - if (from & FWRITE) to |= C_O_WRITE; \ - if (from & O_TRUNC) to |= C_O_TRUNC; \ - if (from & O_EXCL) to |= C_O_EXCL; \ - if (from & O_CREAT) to |= C_O_CREAT; \ -} while (0) - -#define CNV_VV2V_ATTR(top, fromp) do { \ - (top)->va_type = (fromp)->va_type; \ - (top)->va_mode = (fromp)->va_mode; \ - (top)->va_nlink = (fromp)->va_nlink; \ - (top)->va_uid = (fromp)->va_uid; \ - (top)->va_gid = (fromp)->va_gid; \ - (top)->va_fsid = VNOVAL; \ - (top)->va_fileid = (fromp)->va_fileid; \ - (top)->va_size = (fromp)->va_size; \ - (top)->va_blocksize = (fromp)->va_blocksize; \ - (top)->va_atime = (fromp)->va_atime; \ - (top)->va_mtime = (fromp)->va_mtime; \ - (top)->va_ctime = (fromp)->va_ctime; \ - (top)->va_gen = (fromp)->va_gen; \ - (top)->va_flags = (fromp)->va_flags; \ - (top)->va_rdev = (fromp)->va_rdev; \ - (top)->va_bytes = (fromp)->va_bytes; \ - (top)->va_filerev = (fromp)->va_filerev; \ - (top)->va_vaflags = VNOVAL; \ - (top)->va_spare = VNOVAL; \ -} while (0) - -#define CNV_V2VV_ATTR(top, fromp) do { \ - (top)->va_type = (fromp)->va_type; \ - (top)->va_mode = (fromp)->va_mode; \ - (top)->va_nlink = (fromp)->va_nlink; \ - (top)->va_uid = (fromp)->va_uid; \ - (top)->va_gid = (fromp)->va_gid; \ - (top)->va_fileid = (fromp)->va_fileid; \ - (top)->va_size = (fromp)->va_size; \ - (top)->va_blocksize = (fromp)->va_blocksize; \ - (top)->va_atime = (fromp)->va_atime; \ - (top)->va_mtime = (fromp)->va_mtime; \ - (top)->va_ctime = (fromp)->va_ctime; \ - (top)->va_gen = (fromp)->va_gen; \ - (top)->va_flags = (fromp)->va_flags; \ - (top)->va_rdev = (fromp)->va_rdev; \ - (top)->va_bytes = (fromp)->va_bytes; \ - (top)->va_filerev = (fromp)->va_filerev; \ -} while (0) - -int coda_kernel_version = CODA_KERNEL_VERSION; - -int -venus_root(void *mdp, struct ucred *cred, struct proc *p, - /*out*/ struct CodaFid *VFid) -{ - DECL_NO_IN(coda_root); /* sets Isize & Osize */ - ALLOC_NO_IN(coda_root); /* sets inp & outp */ - - /* send the open to venus. */ - INIT_IN(inp, CODA_ROOT, cred, p); - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) - *VFid = outp->Fid; - - CODA_FREE(inp, coda_root_size); - return (error); -} - -int -venus_open(void *mdp, struct CodaFid *fid, int flag, struct ucred *cred, - struct proc *p, /*out*/ struct vnode **vp) -{ - int cflag; - DECL(coda_open_by_fd); /* sets Isize & Osize */ - ALLOC(coda_open_by_fd); /* sets inp & outp */ - - /* send the open to venus. */ - INIT_IN(&inp->ih, CODA_OPEN_BY_FD, cred, p); - inp->Fid = *fid; - CNV_OFLAG(cflag, flag); - inp->flags = cflag; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - *vp = error ? NULL : outp->vp; - - CODA_FREE(inp, coda_open_by_fd_size); - return (error); -} - -int -venus_close(void *mdp, struct CodaFid *fid, int flag, struct ucred *cred, - struct proc *p) -{ - int cflag; - DECL_NO_OUT(coda_close); /* sets Isize & Osize */ - ALLOC_NO_OUT(coda_close); /* sets inp & outp */ - - INIT_IN(&inp->ih, CODA_CLOSE, cred, p); - inp->Fid = *fid; - CNV_OFLAG(cflag, flag); - inp->flags = cflag; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_close_size); - return (error); -} - -/* - * These two calls will not exist!!! The container file is read/written - * directly. - */ -void -venus_read(void) -{ -} - -void -venus_write(void) -{ -} - -/* - * This is a bit sad too. the ioctl's are for the control file, not for - * normal files. - */ -int -venus_ioctl(void *mdp, struct CodaFid *fid, int com, int flag, caddr_t data, - struct ucred *cred, struct proc *p) -{ - DECL(coda_ioctl); /* sets Isize & Osize */ - struct PioctlData *iap = (struct PioctlData *)data; - int tmp; - - coda_ioctl_size = VC_MAXMSGSIZE; - ALLOC(coda_ioctl); /* sets inp & outp */ - - INIT_IN(&inp->ih, CODA_IOCTL, cred, p); - inp->Fid = *fid; - - /* - * Command was mutated by increasing its size field to reflect the - * path and follow args. we need to subtract that out before sending - * the command to venus. - */ - inp->cmd = (com & ~(IOCPARM_MASK << 16)); - tmp = ((com >> 16) & IOCPARM_MASK) - sizeof (char *) - sizeof (int); - inp->cmd |= (tmp & IOCPARM_MASK) << 16; - - if (iap->vi.in_size > VC_MAXMSGSIZE || - iap->vi.out_size > VC_MAXMSGSIZE) { - CODA_FREE(inp, coda_ioctl_size); - return (EINVAL); - } - - inp->rwflag = flag; - inp->len = iap->vi.in_size; - inp->data = (char *)(sizeof (struct coda_ioctl_in)); - - error = copyin(iap->vi.in, (char*)inp + (long)inp->data, - iap->vi.in_size); - if (error) { - CODA_FREE(inp, coda_ioctl_size); - return (error); - } - - Osize = VC_MAXMSGSIZE; - error = coda_call(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp); - - /* - * Copy out the out buffer. - */ - if (!error) { - if (outp->len > iap->vi.out_size) - error = EINVAL; - else - error = copyout((char *)outp + (long)outp->data, - iap->vi.out, iap->vi.out_size); - } - - CODA_FREE(inp, coda_ioctl_size); - return (error); -} - -int -venus_getattr(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct vattr *vap) -{ - struct proc *p; - DECL(coda_getattr); /* sets Isize & Osize */ - ALLOC(coda_getattr); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - p = curthread->td_proc; - INIT_IN(&inp->ih, CODA_GETATTR, cred, p); - inp->Fid = *fid; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) - CNV_VV2V_ATTR(vap, &outp->attr); - - CODA_FREE(inp, coda_getattr_size); - return (error); -} - -int -venus_setattr(void *mdp, struct CodaFid *fid, struct vattr *vap, - struct ucred *cred) -{ - struct proc *p; - DECL_NO_OUT(coda_setattr); /* sets Isize & Osize */ - ALLOC_NO_OUT(coda_setattr); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - p = curthread->td_proc; - INIT_IN(&inp->ih, CODA_SETATTR, cred, p); - inp->Fid = *fid; - CNV_V2VV_ATTR(&inp->attr, vap); - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_setattr_size); - return (error); -} - -int -venus_access(void *mdp, struct CodaFid *fid, accmode_t accmode, - struct ucred *cred, struct proc *p) -{ - DECL_NO_OUT(coda_access); /* sets Isize & Osize */ - ALLOC_NO_OUT(coda_access); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_ACCESS, cred, p); - inp->Fid = *fid; - - /* - * NOTE: FreeBSD and Venus internals use the "data" in the low 3 - * bits. Hence, the conversion. - * - * XXX: We cast accmode_t variable into an int. - */ - inp->flags = (int)accmode>>6; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_access_size); - return (error); -} - -int -venus_readlink(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ char **str, int *len) -{ - DECL(coda_readlink); /* sets Isize & Osize */ - coda_readlink_size += CODA_MAXPATHLEN; - ALLOC(coda_readlink); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_READLINK, cred, p); - inp->Fid = *fid; - - Osize += CODA_MAXPATHLEN; - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - CODA_ALLOC(*str, char *, outp->count); - *len = outp->count; - bcopy((char *)outp + (long)outp->data, *str, *len); - } - - CODA_FREE(inp, coda_readlink_size); - return (error); -} - -int -venus_fsync(void *mdp, struct CodaFid *fid, struct proc *p) -{ - DECL_NO_OUT(coda_fsync); /* sets Isize & Osize */ - ALLOC_NO_OUT(coda_fsync); /* sets inp & outp */ - - /* - * Send the open to venus. - * - * XXX: should be cached mount cred. - */ - INIT_IN(&inp->ih, CODA_FSYNC, NOCRED, p); - inp->Fid = *fid; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_fsync_size); - return (error); -} - -int -venus_lookup(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p, /*out*/ struct CodaFid *VFid, - int *vtype) -{ - DECL(coda_lookup); /* sets Isize & Osize */ - coda_lookup_size += len + 1; - ALLOC(coda_lookup); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_LOOKUP, cred, p); - inp->Fid = *fid; - - /* - * NOTE: Between version 1 and version 2 we have added an extra flag - * field to this structure. But because the string was at the end - * and because of the wierd way we represent strings by having the - * slot point to where the string characters are in the "heap", we - * can just slip the flag parameter in after the string slot pointer - * and veni that don't know better won't see this new flag field ... - * Otherwise we'd need two different venus_lookup functions. - */ - inp->name = Isize; - inp->flags = CLU_CASE_SENSITIVE; /* doesn't really matter for BSD */ - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - *VFid = outp->Fid; - *vtype = outp->vtype; - } - - CODA_FREE(inp, coda_lookup_size); - return (error); -} - -int -venus_create(void *mdp, struct CodaFid *fid, const char *nm, int len, - int exclusive, int mode, struct vattr *va, struct ucred *cred, - struct proc *p, /*out*/ struct CodaFid *VFid, struct vattr *attr) -{ - DECL(coda_create); /* sets Isize & Osize */ - coda_create_size += len + 1; - ALLOC(coda_create); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_CREATE, cred, p); - inp->Fid = *fid; - inp->excl = exclusive ? C_O_EXCL : 0; - inp->mode = mode; - CNV_V2VV_ATTR(&inp->attr, va); - - inp->name = Isize; - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - *VFid = outp->Fid; - CNV_VV2V_ATTR(attr, &outp->attr); - } - - CODA_FREE(inp, coda_create_size); - return (error); -} - -int -venus_remove(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p) -{ - DECL_NO_OUT(coda_remove); /* sets Isize & Osize */ - coda_remove_size += len + 1; - ALLOC_NO_OUT(coda_remove); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_REMOVE, cred, p); - inp->Fid = *fid; - - inp->name = Isize; - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_remove_size); - return (error); -} - -int -venus_link(void *mdp, struct CodaFid *fid, struct CodaFid *tfid, - const char *nm, int len, struct ucred *cred, struct proc *p) -{ - DECL_NO_OUT(coda_link); /* sets Isize & Osize */ - coda_link_size += len + 1; - ALLOC_NO_OUT(coda_link); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_LINK, cred, p); - inp->sourceFid = *fid; - inp->destFid = *tfid; - - inp->tname = Isize; - STRCPY(tname, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_link_size); - return (error); -} - -int -venus_rename(void *mdp, struct CodaFid *fid, struct CodaFid *tfid, - const char *nm, int len, const char *tnm, int tlen, struct ucred *cred, - struct proc *p) -{ - DECL_NO_OUT(coda_rename); /* sets Isize & Osize */ - coda_rename_size += len + 1 + tlen + 1; - ALLOC_NO_OUT(coda_rename); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_RENAME, cred, p); - inp->sourceFid = *fid; - inp->destFid = *tfid; - - inp->srcname = Isize; - STRCPY(srcname, nm, len); /* increments Isize */ - - inp->destname = Isize; - STRCPY(destname, tnm, tlen); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_rename_size); - return (error); -} - -int -venus_mkdir(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct vattr *va, struct ucred *cred, struct proc *p, - /*out*/ struct CodaFid *VFid, struct vattr *ova) -{ - DECL(coda_mkdir); /* sets Isize & Osize */ - coda_mkdir_size += len + 1; - ALLOC(coda_mkdir); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_MKDIR, cred, p); - inp->Fid = *fid; - CNV_V2VV_ATTR(&inp->attr, va); - - inp->name = Isize; - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - *VFid = outp->Fid; - CNV_VV2V_ATTR(ova, &outp->attr); - } - - CODA_FREE(inp, coda_mkdir_size); - return (error); -} - -int -venus_rmdir(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p) -{ - DECL_NO_OUT(coda_rmdir); /* sets Isize & Osize */ - coda_rmdir_size += len + 1; - ALLOC_NO_OUT(coda_rmdir); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_RMDIR, cred, p); - inp->Fid = *fid; - - inp->name = Isize; - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_rmdir_size); - return (error); -} - -int -venus_symlink(void *mdp, struct CodaFid *fid, const char *lnm, int llen, - const char *nm, int len, struct vattr *va, struct ucred *cred, - struct proc *p) -{ - DECL_NO_OUT(coda_symlink); /* sets Isize & Osize */ - coda_symlink_size += llen + 1 + len + 1; - ALLOC_NO_OUT(coda_symlink); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_SYMLINK, cred, p); - inp->Fid = *fid; - CNV_V2VV_ATTR(&inp->attr, va); - - inp->srcname = Isize; - STRCPY(srcname, lnm, llen); /* increments Isize */ - - inp->tname = Isize; - STRCPY(tname, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_symlink_size); - return (error); -} - -/* - * XXX: Unused. - */ -int -venus_readdir(void *mdp, struct CodaFid *fid, int count, int offset, - struct ucred *cred, struct proc *p, /*out*/ char *buffer, int *len) -{ - DECL(coda_readdir); /* sets Isize & Osize */ - coda_readdir_size = VC_MAXMSGSIZE; - ALLOC(coda_readdir); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_READDIR, cred, p); - inp->Fid = *fid; - inp->count = count; - inp->offset = offset; - - Osize = VC_MAXMSGSIZE; - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - bcopy((char *)outp + (long)outp->data, buffer, outp->size); - *len = outp->size; - } - - CODA_FREE(inp, coda_readdir_size); - return (error); -} - -int -venus_fhtovp(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ struct CodaFid *VFid, int *vtype) -{ - DECL(coda_vget); /* sets Isize & Osize */ - ALLOC(coda_vget); /* sets inp & outp */ - - /* - * Send the open to Venus. - */ - INIT_IN(&inp->ih, CODA_VGET, cred, p); - inp->Fid = *fid; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - *VFid = outp->Fid; - *vtype = outp->vtype; - } - - CODA_FREE(inp, coda_vget_size); - return (error); -} diff --git a/sys/fs/coda/coda_venus.h b/sys/fs/coda/coda_venus.h deleted file mode 100644 index 95f1c57..0000000 --- a/sys/fs/coda/coda_venus.h +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_venus.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -#ifndef _CODA_VENUS_H_ -#define _CODA_VENUS_H_ - -int venus_root(void *mdp, struct ucred *cred, struct proc *p, - /*out*/ struct CodaFid *VFid); -int venus_open(void *mdp, struct CodaFid *fid, int flag, - struct ucred *cred, struct proc *p, /*out*/ struct vnode **vp); -int venus_close(void *mdp, struct CodaFid *fid, int flag, - struct ucred *cred, struct proc *p); -void venus_read(void); -void venus_write(void); -int venus_ioctl(void *mdp, struct CodaFid *fid, int com, int flag, - caddr_t data, struct ucred *cred, struct proc *p); -int venus_getattr(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct vattr *vap); -int venus_setattr(void *mdp, struct CodaFid *fid, struct vattr *vap, - struct ucred *cred); -int venus_access(void *mdp, struct CodaFid *fid, int mode, - struct ucred *cred, struct proc *p); -int venus_readlink(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ char **str, int *len); -int venus_fsync(void *mdp, struct CodaFid *fid, struct proc *p); -int venus_lookup(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p, /*out*/ struct CodaFid *VFid, - int *vtype); -int venus_create(void *mdp, struct CodaFid *fid, const char *nm, int len, - int exclusive, int mode, struct vattr *va, struct ucred *cred, - struct proc *p, /*out*/ struct CodaFid *VFid, - struct vattr *attr); -int venus_remove(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p); -int venus_link(void *mdp, struct CodaFid *fid, struct CodaFid *tfid, - const char *nm, int len, struct ucred *cred, struct proc *p); -int venus_rename(void *mdp, struct CodaFid *fid, struct CodaFid *tfid, - const char *nm, int len, const char *tnm, int tlen, - struct ucred *cred, struct proc *p); -int venus_mkdir(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct vattr *va, struct ucred *cred, struct proc *p, - /*out*/ struct CodaFid *VFid, struct vattr *ova); -int venus_rmdir(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p); -int venus_symlink(void *mdp, struct CodaFid *fid, const char *lnm, - int llen, const char *nm, int len, struct vattr *va, - struct ucred *cred, struct proc *p); -int venus_readdir(void *mdp, struct CodaFid *fid, int count, int offset, - struct ucred *cred, struct proc *p, /*out*/ char *buffer, - int *len); -int venus_fhtovp(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ struct CodaFid *VFid, int *vtype); - -#endif /* !_CODA_VENUS_H_ */ diff --git a/sys/fs/coda/coda_vfsops.c b/sys/fs/coda/coda_vfsops.c deleted file mode 100644 index 90660c6..0000000 --- a/sys/fs/coda/coda_vfsops.c +++ /dev/null @@ -1,446 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/cfs/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ - -/*- - * Mach Operating System - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/proc.h> - -#include <fs/coda/coda.h> -#include <fs/coda/cnode.h> -#include <fs/coda/coda_vfsops.h> -#include <fs/coda/coda_venus.h> -#include <fs/coda/coda_subr.h> -#include <fs/coda/coda_opstats.h> - -MALLOC_DEFINE(M_CODA, "coda", "Various Coda Structures"); - -int codadebug = 0; -int coda_vfsop_print_entry = 0; -#define ENTRY do { \ - if (coda_vfsop_print_entry) \ - myprintf(("Entered %s\n", __func__)); \ -} while (0) - -struct vnode *coda_ctlvp; - -/* - * Structure to keep statistics of internally generated/satisfied calls. - */ -static struct coda_op_stats coda_vfsopstats[CODA_VFSOPS_SIZE]; - -#define MARK_ENTRY(op) (coda_vfsopstats[op].entries++) -#define MARK_INT_SAT(op) (coda_vfsopstats[op].sat_intrn++) -#define MARK_INT_FAIL(op) (coda_vfsopstats[op].unsat_intrn++) -#define MARK_INT_GEN(op) (coda_vfsopstats[op].gen_intrn++) - -int -coda_vfsopstats_init(void) -{ - int i; - - for (i=0; i<CODA_VFSOPS_SIZE;i++) { - coda_vfsopstats[i].opcode = i; - coda_vfsopstats[i].entries = 0; - coda_vfsopstats[i].sat_intrn = 0; - coda_vfsopstats[i].unsat_intrn = 0; - coda_vfsopstats[i].gen_intrn = 0; - } - return (0); -} - -static const char *coda_opts[] = { "from", NULL }; -/* - * cfs mount vfsop - * - * Set up mount info record and attach it to vfs struct. - */ -/*ARGSUSED*/ -int -coda_mount(struct mount *vfsp) -{ - struct vnode *dvp; - struct cnode *cp; - struct cdev *dev; - struct coda_mntinfo *mi; - struct vnode *rootvp; - struct CodaFid rootfid = INVAL_FID; - struct CodaFid ctlfid = CTL_FID; - int error; - struct nameidata ndp; - ENTRY; - char *from; - - if (vfs_filteropt(vfsp->mnt_optnew, coda_opts)) - return (EINVAL); - from = vfs_getopts(vfsp->mnt_optnew, "from", &error); - if (error) - return (error); - coda_vfsopstats_init(); - coda_vnodeopstats_init(); - MARK_ENTRY(CODA_MOUNT_STATS); - if (CODA_MOUNTED(vfsp)) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - return (EBUSY); - } - - /* - * Validate mount device. Similar to getmdev(). - */ - NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, from, curthread); - error = namei(&ndp); - dvp = ndp.ni_vp; - if (error) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - return (error); - } - if (dvp->v_type != VCHR) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - vrele(dvp); - NDFREE(&ndp, NDF_ONLY_PNBUF); - return (ENXIO); - } - dev = dvp->v_rdev; - vrele(dvp); - NDFREE(&ndp, NDF_ONLY_PNBUF); - - /* - * Initialize the mount record and link it to the vfs struct. - */ - mi = dev2coda_mntinfo(dev); - if (!mi) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - printf("Coda mount: %s is not a cfs device\n", from); - return (ENXIO); - } - if (!VC_OPEN(&mi->mi_vcomm)) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - return (ENODEV); - } - - /* - * No initialization (here) of mi_vcomm! - */ - vfsp->mnt_data = mi; - vfs_getnewfsid (vfsp); - mi->mi_vfsp = vfsp; - mi->mi_started = 0; /* XXX See coda_root() */ - - /* - * Make a root vnode to placate the Vnode interface, but don't - * actually make the CODA_ROOT call to venus until the first call to - * coda_root in case a server is down while venus is starting. - */ - cp = make_coda_node(&rootfid, vfsp, VDIR); - rootvp = CTOV(cp); - rootvp->v_vflag |= VV_ROOT; - cp = make_coda_node(&ctlfid, vfsp, VREG); - coda_ctlvp = CTOV(cp); - - /* - * Add vfs and rootvp to chain of vfs hanging off mntinfo. - */ - mi->mi_vfsp = vfsp; - mi->mi_rootvp = rootvp; - vfs_mountedfrom(vfsp, from); - - /* - * Error is currently guaranteed to be zero, but in case some code - * changes... - */ - CODADEBUG(1, myprintf(("coda_mount returned %d\n", error));); - if (error) - MARK_INT_FAIL(CODA_MOUNT_STATS); - else - MARK_INT_SAT(CODA_MOUNT_STATS); - return (error); -} - -int -coda_unmount(struct mount *vfsp, int mntflags) -{ - struct coda_mntinfo *mi = vftomi(vfsp); - int active, error = 0; - - ENTRY; - MARK_ENTRY(CODA_UMOUNT_STATS); - if (!CODA_MOUNTED(vfsp)) { - MARK_INT_FAIL(CODA_UMOUNT_STATS); - return (EINVAL); - } - if (mi->mi_vfsp == vfsp) { - /* - * We found the victim. - */ - if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp))) - return (EBUSY); /* Venus is still running */ -#ifdef DEBUG - printf("coda_unmount: ROOT: vp %p, cp %p\n", mi->mi_rootvp, - VTOC(mi->mi_rootvp)); -#endif - vrele(mi->mi_rootvp); - mi->mi_rootvp = NULL; - vrele(coda_ctlvp); - coda_ctlvp = NULL; - active = coda_kill(vfsp, NOT_DOWNCALL); - error = vflush(mi->mi_vfsp, 0, FORCECLOSE, curthread); -#ifdef CODA_VERBOSE - printf("coda_unmount: active = %d, vflush active %d\n", - active, error); -#endif - error = 0; - /* - * I'm going to take this out to allow lookups to go through. - * I'm not sure it's important anyway. -- DCS 2/2/94 - */ - /* vfsp->VFS_DATA = NULL; */ - - /* - * No more vfsp's to hold onto. - */ - mi->mi_vfsp = NULL; - - if (error) - MARK_INT_FAIL(CODA_UMOUNT_STATS); - else - MARK_INT_SAT(CODA_UMOUNT_STATS); - return (error); - } - return (EINVAL); -} - -/* - * Find root of cfs. - */ -int -coda_root(struct mount *vfsp, int flags, struct vnode **vpp) -{ - struct coda_mntinfo *mi = vftomi(vfsp); - int error; - struct proc *p; - struct thread *td; - struct CodaFid VFid; - static const struct CodaFid invalfid = INVAL_FID; - - td = curthread; - p = td->td_proc; - ENTRY; - MARK_ENTRY(CODA_ROOT_STATS); - if (vfsp == mi->mi_vfsp) { - /* - * Cache the root across calls. We only need to pass the - * request on to Venus if the root vnode is the dummy we - * installed in coda_mount() with all c_fid members zeroed. - * - * XXX In addition, we assume that the first call to - * coda_root() is from vfs_mount() (before the call to - * checkdirs()) and return the dummy root node to avoid a - * deadlock. This bug is fixed in the Coda CVS repository - * but not in any released versions as of 6 Mar 2003. - */ - if (memcmp(&VTOC(mi->mi_rootvp)->c_fid, &invalfid, - sizeof(struct CodaFid)) != 0 || mi->mi_started == 0) { - /* - * Found valid root. - */ - *vpp = mi->mi_rootvp; - mi->mi_started = 1; - - /* - * On Mach, this is vref. On FreeBSD, vref + - * vn_lock. - */ - vref(*vpp); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); - MARK_INT_SAT(CODA_ROOT_STATS); - return (0); - } - } - - error = venus_root(vftomi(vfsp), td->td_ucred, p, &VFid); - if (!error) { - /* - * Save the new rootfid in the cnode, and rehash the cnode - * into the cnode hash with the new fid key. - */ - coda_unsave(VTOC(mi->mi_rootvp)); - VTOC(mi->mi_rootvp)->c_fid = VFid; - coda_save(VTOC(mi->mi_rootvp)); - *vpp = mi->mi_rootvp; - vref(*vpp); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); - MARK_INT_SAT(CODA_ROOT_STATS); - } else if (error == ENODEV || error == EINTR) { - /* - * Gross hack here! - * - * If Venus fails to respond to the CODA_ROOT call, coda_call - * returns ENODEV. Return the uninitialized root vnode to - * allow vfs operations such as unmount to continue. Without - * this hack, there is no way to do an unmount if Venus dies - * before a successful CODA_ROOT call is done. All vnode - * operations will fail. - */ - *vpp = mi->mi_rootvp; - vref(*vpp); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); - MARK_INT_FAIL(CODA_ROOT_STATS); - error = 0; - } else { - CODADEBUG(CODA_ROOT, myprintf(("error %d in CODA_ROOT\n", - error));); - MARK_INT_FAIL(CODA_ROOT_STATS); - } - return (error); -} - -/* - * Get filesystem statistics. - */ -int -coda_statfs(struct mount *vfsp, struct statfs *sbp) -{ - - ENTRY; - MARK_ENTRY(CODA_STATFS_STATS); - if (!CODA_MOUNTED(vfsp)) { - MARK_INT_FAIL(CODA_STATFS_STATS); - return (EINVAL); - } - - /* - * XXX - what to do about f_flags, others? --bnoble - * - * We just make up free space counts that are sufficiently large. - */ - sbp->f_flags = 0; - sbp->f_bsize = 8192; /* XXX */ - sbp->f_iosize = 8192; /* XXX */ -#define CODA_SFS_SIZ 0x8AB75D - sbp->f_blocks = CODA_SFS_SIZ; - sbp->f_bfree = CODA_SFS_SIZ; - sbp->f_bavail = CODA_SFS_SIZ; - sbp->f_files = CODA_SFS_SIZ; - sbp->f_ffree = CODA_SFS_SIZ; - MARK_INT_SAT(CODA_STATFS_STATS); - return (0); -} - -/* - * Flush any pending I/O. - */ -int -coda_sync(struct mount *vfsp, int waitfor) -{ - - ENTRY; - MARK_ENTRY(CODA_SYNC_STATS); - MARK_INT_SAT(CODA_SYNC_STATS); - return (0); -} - -/* - * fhtovp is now what vget used to be in 4.3-derived systems. For some silly - * reason, vget is now keyed by a 32 bit ino_t, rather than a type-specific - * fid. - * - * XXX: coda_fhtovp is currently not hooked up, so no NFS export for Coda. - * We leave it here in the hopes that someone will find it someday and hook - * it up. Among other things, it will need some reworking to match the - * vfs_fhtovp_t prototype. - */ -int -coda_fhtovp(struct mount *vfsp, struct fid *fhp, struct mbuf *nam, - struct vnode **vpp, int *exflagsp, struct ucred **creadanonp) -{ - struct cfid *cfid = (struct cfid *)fhp; - struct cnode *cp = NULL; - int error; - struct thread *td = curthread; /* XXX -mach */ - struct proc *p = td->td_proc; - struct CodaFid VFid; - int vtype; - - ENTRY; - MARK_ENTRY(CODA_VGET_STATS); - - /* - * Check for vget of control object. - */ - if (IS_CTL_FID(&cfid->cfid_fid)) { - *vpp = coda_ctlvp; - vref(coda_ctlvp); - MARK_INT_SAT(CODA_VGET_STATS); - return (0); - } - error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, td->td_ucred, p, - &VFid, &vtype); - if (error) { - CODADEBUG(CODA_VGET, myprintf(("vget error %d\n",error));); - *vpp = NULL; - } else { - CODADEBUG(CODA_VGET, myprintf(("vget: %s type %d result " - "%d\n", coda_f2s(&VFid), vtype, error));); - cp = make_coda_node(&VFid, vfsp, vtype); - *vpp = CTOV(cp); - } - return (error); -} - -struct vfsops coda_vfsops = { - .vfs_mount = coda_mount, - .vfs_root = coda_root, - .vfs_statfs = coda_statfs, - .vfs_sync = coda_sync, - .vfs_unmount = coda_unmount, -}; -VFS_SET(coda_vfsops, coda, VFCF_NETWORK); diff --git a/sys/fs/coda/coda_vfsops.h b/sys/fs/coda/coda_vfsops.h deleted file mode 100644 index e5b3a11..0000000 --- a/sys/fs/coda/coda_vfsops.h +++ /dev/null @@ -1,60 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/cfs/coda_vfsops.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -#ifndef _CODA_VFSOPS_H_ -#define _CODA_VFSOPS_H_ - -/* - * cfid structure: - * - * This overlays the fid structure (see vfs.h); only used below and will - * probably go away. - */ -struct cfid { - u_short cfid_len; - u_short padding; - struct CodaFid cfid_fid; -}; - -struct mbuf; -struct mount; -int coda_vfsopstats_init(void); -int coda_fhtovp(struct mount *, struct fid *, struct mbuf *, - struct vnode **, int *, struct ucred **); - -vfs_mount_t coda_mount; -vfs_unmount_t coda_unmount; -vfs_root_t coda_root; -vfs_statfs_t coda_statfs; -vfs_sync_t coda_sync; - -#endif /* !_CODA_VFSOPS_H_ */ diff --git a/sys/fs/coda/coda_vnops.c b/sys/fs/coda/coda_vnops.c deleted file mode 100644 index 51fb307..0000000 --- a/sys/fs/coda/coda_vnops.c +++ /dev/null @@ -1,1738 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ -/* - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/acct.h> -#include <sys/errno.h> -#include <sys/fcntl.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/file.h> /* Must come after sys/malloc.h */ -#include <sys/mount.h> -#include <sys/mutex.h> -#include <sys/namei.h> -#include <sys/proc.h> -#include <sys/uio.h> -#include <sys/unistd.h> - -#include <vm/vm.h> -#include <vm/vm_object.h> -#include <vm/vm_extern.h> - -#include <fs/coda/coda.h> -#include <fs/coda/cnode.h> -#include <fs/coda/coda_vnops.h> -#include <fs/coda/coda_venus.h> -#include <fs/coda/coda_opstats.h> -#include <fs/coda/coda_subr.h> -#include <fs/coda/coda_pioctl.h> - -/* - * These flags select various performance enhancements. - */ -static int coda_attr_cache = 1; /* Set to cache attributes. */ -static int coda_symlink_cache = 1; /* Set to cache symbolic links. */ -static int coda_access_cache = 1; /* Set to cache some access checks. */ - -/* - * Structure to keep track of vfs calls. - */ -static struct coda_op_stats coda_vnodeopstats[CODA_VNODEOPS_SIZE]; - -#define MARK_ENTRY(op) (coda_vnodeopstats[op].entries++) -#define MARK_INT_SAT(op) (coda_vnodeopstats[op].sat_intrn++) -#define MARK_INT_FAIL(op) (coda_vnodeopstats[op].unsat_intrn++) -#define MARK_INT_GEN(op) (coda_vnodeopstats[op].gen_intrn++) - -/* - * What we are delaying for in printf. - */ -int coda_printf_delay = 0; /* In microseconds */ -int coda_vnop_print_entry = 0; -static int coda_lockdebug = 0; - -/* - * Some FreeBSD details: - * - * codadev_modevent is called at boot time or module load time. - */ -#define ENTRY do { \ - if (coda_vnop_print_entry) \ - myprintf(("Entered %s\n", __func__)); \ -} while (0) - -/* - * Definition of the vnode operation vector. - */ -struct vop_vector coda_vnodeops = { - .vop_default = &default_vnodeops, - .vop_cachedlookup = coda_lookup, /* uncached lookup */ - .vop_lookup = vfs_cache_lookup, /* namecache lookup */ - .vop_create = coda_create, /* create */ - .vop_open = coda_open, /* open */ - .vop_close = coda_close, /* close */ - .vop_access = coda_access, /* access */ - .vop_getattr = coda_getattr, /* getattr */ - .vop_setattr = coda_setattr, /* setattr */ - .vop_read = coda_read, /* read */ - .vop_write = coda_write, /* write */ - .vop_ioctl = coda_ioctl, /* ioctl */ - .vop_fsync = coda_fsync, /* fsync */ - .vop_remove = coda_remove, /* remove */ - .vop_link = coda_link, /* link */ - .vop_rename = coda_rename, /* rename */ - .vop_mkdir = coda_mkdir, /* mkdir */ - .vop_rmdir = coda_rmdir, /* rmdir */ - .vop_symlink = coda_symlink, /* symlink */ - .vop_readdir = coda_readdir, /* readdir */ - .vop_readlink = coda_readlink, /* readlink */ - .vop_inactive = coda_inactive, /* inactive */ - .vop_reclaim = coda_reclaim, /* reclaim */ - .vop_lock1 = coda_lock, /* lock */ - .vop_unlock = coda_unlock, /* unlock */ - .vop_bmap = VOP_EOPNOTSUPP, /* bmap */ - .vop_print = VOP_NULL, /* print */ - .vop_islocked = coda_islocked, /* islocked */ - .vop_pathconf = coda_pathconf, /* pathconf */ - .vop_poll = vop_stdpoll, - .vop_getpages = vop_stdgetpages, /* pager intf.*/ - .vop_putpages = vop_stdputpages, /* pager intf.*/ - .vop_getwritemount = vop_stdgetwritemount, -#if 0 - /* missing */ - .vop_cachedlookup = ufs_lookup, - .vop_whiteout = ufs_whiteout, -#endif - -}; - -static void coda_print_vattr(struct vattr *attr); - -int -coda_vnodeopstats_init(void) -{ - int i; - - for(i=0; i<CODA_VNODEOPS_SIZE; i++) { - coda_vnodeopstats[i].opcode = i; - coda_vnodeopstats[i].entries = 0; - coda_vnodeopstats[i].sat_intrn = 0; - coda_vnodeopstats[i].unsat_intrn = 0; - coda_vnodeopstats[i].gen_intrn = 0; - } - return (0); -} - -/* - * coda_open calls Venus which returns an open file descriptor the cache file - * holding the data. We get the vnode while we are still in the context of - * the venus process in coda_psdev.c. This vnode is then passed back to the - * caller and opened. - */ -int -coda_open(struct vop_open_args *ap) -{ - - /* - * FreeBSD can pass the O_EXCL flag in mode, even though the check - * has already happened. Venus defensively assumes that if open is - * passed the EXCL, it must be a bug. We strip the flag here. - */ - /* true args */ - struct vnode **vpp = &(ap->a_vp); - struct cnode *cp = VTOC(*vpp); - int flag = ap->a_mode & (~O_EXCL); - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_td; - /* locals */ - int error; - struct vnode *vp; - - MARK_ENTRY(CODA_OPEN_STATS); - - /* - * Check for open of control file. - */ - if (IS_CTL_VP(*vpp)) { - /* XXX */ - /* if (WRITEABLE(flag)) */ - if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) { - MARK_INT_FAIL(CODA_OPEN_STATS); - return (EACCES); - } - MARK_INT_SAT(CODA_OPEN_STATS); - return (0); - } - error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, - td->td_proc, &vp); - if (error) - return (error); - CODADEBUG(CODA_OPEN, myprintf(("open: vp %p result %d\n", vp, - error));); - - /* - * Save the vnode pointer for the cache file. - */ - if (cp->c_ovp == NULL) { - cp->c_ovp = vp; - } else { - if (cp->c_ovp != vp) - panic("coda_open: cp->c_ovp != ITOV(ip)"); - } - cp->c_ocount++; - - /* - * Flush the attribute cached if writing the file. - */ - if (flag & FWRITE) { - cp->c_owrite++; - cp->c_flags &= ~C_VATTR; - } - - /* - * Open the cache file. - */ - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - error = VOP_OPEN(vp, flag, cred, td, NULL); - if (error) { - VOP_UNLOCK(vp, 0); - printf("coda_open: VOP_OPEN on container failed %d\n", error); - return (error); - } - (*vpp)->v_object = vp->v_object; - VOP_UNLOCK(vp, 0); - return (0); -} - -/* - * Close the cache file used for I/O and notify Venus. - */ -int -coda_close(struct vop_close_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - int flag = ap->a_fflag; - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_td; - /* locals */ - int error; - - MARK_ENTRY(CODA_CLOSE_STATS); - - /* - * Check for close of control file. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_SAT(CODA_CLOSE_STATS); - return (0); - } - if (cp->c_ovp) { - vn_lock(cp->c_ovp, LK_EXCLUSIVE | LK_RETRY); - /* Do errors matter here? */ - VOP_CLOSE(cp->c_ovp, flag, cred, td); - vput(cp->c_ovp); - } -#ifdef CODA_VERBOSE - else - printf("coda_close: NO container vp %p/cp %p\n", vp, cp); -#endif - if (--cp->c_ocount == 0) - cp->c_ovp = NULL; - - /* - * File was opened for write. - */ - if (flag & FWRITE) - --cp->c_owrite; - if (!IS_UNMOUNTING(cp)) - error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, - td->td_proc); - else - error = ENODEV; - CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error));); - return (error); -} - -int -coda_read(struct vop_read_args *ap) -{ - - ENTRY; - return (coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ, ap->a_ioflag, - ap->a_cred, ap->a_uio->uio_td)); -} - -int -coda_write(struct vop_write_args *ap) -{ - - ENTRY; - return (coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE, ap->a_ioflag, - ap->a_cred, ap->a_uio->uio_td)); -} - -int -coda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, int ioflag, - struct ucred *cred, struct thread *td) -{ - /* upcall decl */ - /* NOTE: container file operation!!! */ - /* locals */ - struct cnode *cp = VTOC(vp); - struct vnode *cfvp = cp->c_ovp; - int opened_internally = 0; - int error = 0; - - MARK_ENTRY(CODA_RDWR_STATS); - CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %zd, %lld, %d)\n", - rw, (void *)uiop->uio_iov->iov_base, uiop->uio_resid, - (long long)uiop->uio_offset, uiop->uio_segflg));); - - /* - * Check for rdwr of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_RDWR_STATS); - return (EINVAL); - } - - /* - * If file is not already open this must be a page {read,write} - * request and we should open it internally. - */ - if (cfvp == NULL) { - opened_internally = 1; - MARK_INT_GEN(CODA_OPEN_STATS); - error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, - td, NULL); -#ifdef CODA_VERBOSE - printf("coda_rdwr: Internally Opening %p\n", vp); -#endif - if (error) { - printf("coda_rdwr: VOP_OPEN on container failed " - "%d\n", error); - return (error); - } - cfvp = cp->c_ovp; - } - - /* - * Have UFS handle the call. - */ - CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = %s, refcnt = " - "%d\n", coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount));); - vn_lock(cfvp, LK_EXCLUSIVE | LK_RETRY); - if (rw == UIO_READ) { - error = VOP_READ(cfvp, uiop, ioflag, cred); - } else { - error = VOP_WRITE(cfvp, uiop, ioflag, cred); - /* - * ufs_write updates the vnode_pager_setsize for the - * vnode/object. - * - * XXX: Since we now share vm objects between layers, this is - * probably unnecessary. - */ - { - struct vattr attr; - if (VOP_GETATTR(cfvp, &attr, cred) == 0) - vnode_pager_setsize(vp, attr.va_size); - } - } - VOP_UNLOCK(cfvp, 0); - if (error) - MARK_INT_FAIL(CODA_RDWR_STATS); - else - MARK_INT_SAT(CODA_RDWR_STATS); - - /* - * Do an internal close if necessary. - */ - if (opened_internally) { - MARK_INT_GEN(CODA_CLOSE_STATS); - (void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, - td); - } - - /* - * Invalidate cached attributes if writing. - */ - if (rw == UIO_WRITE) - cp->c_flags &= ~C_VATTR; - return (error); -} - -int -coda_ioctl(struct vop_ioctl_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - int com = ap->a_command; - caddr_t data = ap->a_data; - int flag = ap->a_fflag; - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_td; - /* locals */ - int error; - struct vnode *tvp; - struct nameidata ndp; - struct PioctlData *iap = (struct PioctlData *)data; - - MARK_ENTRY(CODA_IOCTL_STATS); - CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path));); - - /* - * Don't check for operation on a dying object, for ctlvp it - * shouldn't matter. - * - * Must be control object to succeed. - */ - if (!IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_IOCTL_STATS); - CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != " - "ctlvp"));); - return (EOPNOTSUPP); - } - - /* - * Look up the pathname. - * - * Should we use the name cache here? It would get it from lookupname - * sooner or later anyway, right? - */ - NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW), - UIO_USERSPACE, iap->path, td); - error = namei(&ndp); - tvp = ndp.ni_vp; - if (error) { - MARK_INT_FAIL(CODA_IOCTL_STATS); - CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup " - "returns %d\n", error));); - return (error); - } - - /* - * Make sure this is a coda style cnode, but it may be a different - * vfsp. - */ - if (tvp->v_op != &coda_vnodeops) { - vrele(tvp); - NDFREE(&ndp, NDF_ONLY_PNBUF); - MARK_INT_FAIL(CODA_IOCTL_STATS); - CODADEBUG(CODA_IOCTL, - myprintf(("coda_ioctl error: %s not a coda object\n", - iap->path));); - return (EINVAL); - } - if (iap->vi.in_size > VC_MAXDATASIZE || - iap->vi.out_size > VC_MAXDATASIZE) { - NDFREE(&ndp, 0); - return (EINVAL); - } - error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag, - data, cred, td->td_proc); - if (error) - MARK_INT_FAIL(CODA_IOCTL_STATS); - else - CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n", - error));); - vrele(tvp); - NDFREE(&ndp, NDF_ONLY_PNBUF); - return (error); -} - -/* - * To reduce the cost of a user-level venus;we cache attributes in the - * kernel. Each cnode has storage allocated for an attribute. If c_vattr is - * valid, return a reference to it. Otherwise, get the attributes from venus - * and store them in the cnode. There is some question if this method is a - * security leak. But I think that in order to make this call, the user must - * have done a lookup and opened the file, and therefore should already have - * access. - */ -int -coda_getattr(struct vop_getattr_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct vattr *vap = ap->a_vap; - struct ucred *cred = ap->a_cred; - /* locals */ - struct vnode *convp; - int error, size; - - MARK_ENTRY(CODA_GETATTR_STATS); - if (IS_UNMOUNTING(cp)) - return (ENODEV); - - /* - * Check for getattr of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_GETATTR_STATS); - return (ENOENT); - } - - /* - * Check to see if the attributes have already been cached. - */ - if (VALID_VATTR(cp)) { - CODADEBUG(CODA_GETATTR, myprintf(("attr cache hit: %s\n", - coda_f2s(&cp->c_fid)));); - CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) - coda_print_vattr(&cp->c_vattr);); - *vap = cp->c_vattr; - MARK_INT_SAT(CODA_GETATTR_STATS); - return (0); - } - error = venus_getattr(vtomi(vp), &cp->c_fid, cred, vap); - if (!error) { - CODADEBUG(CODA_GETATTR, myprintf(("getattr miss %s: result " - "%d\n", coda_f2s(&cp->c_fid), error));); - CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) - coda_print_vattr(vap);); - - /* - * XXX: Since we now share vm objects between layers, this is - * probably unnecessary. - */ - size = vap->va_size; - convp = cp->c_ovp; - if (convp != NULL) - vnode_pager_setsize(convp, size); - - /* - * If not open for write, store attributes in cnode. - */ - if ((cp->c_owrite == 0) && (coda_attr_cache)) { - cp->c_vattr = *vap; - cp->c_flags |= C_VATTR; - } - } - return (error); -} - -int -coda_setattr(struct vop_setattr_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct vattr *vap = ap->a_vap; - struct ucred *cred = ap->a_cred; - /* locals */ - struct vnode *convp; - int error, size; - - MARK_ENTRY(CODA_SETATTR_STATS); - - /* - * Check for setattr of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_SETATTR_STATS); - return (ENOENT); - } - if (codadebug & CODADBGMSK(CODA_SETATTR)) - coda_print_vattr(vap); - error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred); - if (!error) - cp->c_flags &= ~(C_VATTR | C_ACCCACHE); - - /* - * XXX: Since we now share vm objects between layers, this is - * probably unnecessary. - * - * XXX: Shouldn't we only be doing this "set" if C_VATTR remains - * valid after venus_setattr()? - */ - size = vap->va_size; - convp = cp->c_ovp; - if (size != VNOVAL && convp != NULL) - vnode_pager_setsize(convp, size); - CODADEBUG(CODA_SETATTR, myprintf(("setattr %d\n", error));); - return (error); -} - -int -coda_access(struct vop_access_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - accmode_t accmode = ap->a_accmode; - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_td; - /* locals */ - int error; - - MARK_ENTRY(CODA_ACCESS_STATS); - - /* - * Check for access of control object. Only read access is allowed - * on it. - */ - if (IS_CTL_VP(vp)) { - /* - * Bogus hack - all will be marked as successes. - */ - MARK_INT_SAT(CODA_ACCESS_STATS); - return (((accmode & VREAD) && !(accmode & (VWRITE | VEXEC))) - ? 0 : EACCES); - } - - /* - * We maintain a one-entry LRU positive access cache with each cnode. - * In principle we could also track negative results, and for more - * than one uid, but we don't yet. Venus is responsible for - * invalidating this cache as required. - */ - if (coda_access_cache && VALID_ACCCACHE(cp) && - (cred->cr_uid == cp->c_cached_uid) && - (accmode & cp->c_cached_mode) == accmode) { - MARK_INT_SAT(CODA_ACCESS_STATS); - return (0); - } - error = venus_access(vtomi(vp), &cp->c_fid, accmode, cred, td->td_proc); - if (error == 0 && coda_access_cache) { - /*- - * When we have a new successful request, we consider three - * cases: - * - * - No initialized access cache, in which case cache the - * result. - * - Cached result for a different user, in which case we - * replace the entry. - * - Cached result for the same user, in which case we add - * any newly granted rights to the cached mode. - * - * XXXRW: If we ever move to something more interesting than - * uid-based token lookup, we'll need to change this. - */ - cp->c_flags |= C_ACCCACHE; - if (cp->c_cached_uid != cred->cr_uid) { - cp->c_cached_mode = accmode; - cp->c_cached_uid = cred->cr_uid; - } else - cp->c_cached_mode |= accmode; - } - return (error); -} - -int -coda_readlink(struct vop_readlink_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct uio *uiop = ap->a_uio; - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_uio->uio_td; - /* locals */ - int error; - char *str; - int len; - - MARK_ENTRY(CODA_READLINK_STATS); - - /* - * Check for readlink of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_READLINK_STATS); - return (ENOENT); - } - if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { - /* - * Symlink was cached. - */ - uiop->uio_rw = UIO_READ; - error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop); - if (error) - MARK_INT_FAIL(CODA_READLINK_STATS); - else - MARK_INT_SAT(CODA_READLINK_STATS); - return (error); - } - error = venus_readlink(vtomi(vp), &cp->c_fid, cred, td != NULL ? - td->td_proc : NULL, &str, &len); - if (!error) { - uiop->uio_rw = UIO_READ; - error = uiomove(str, len, uiop); - if (coda_symlink_cache) { - cp->c_symlink = str; - cp->c_symlen = len; - cp->c_flags |= C_SYMLINK; - } else - CODA_FREE(str, len); - } - CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n", - error));); - return (error); -} - -int -coda_fsync(struct vop_fsync_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct thread *td = ap->a_td; - /* locals */ - struct vnode *convp = cp->c_ovp; - int error; - - MARK_ENTRY(CODA_FSYNC_STATS); - - /* - * Check for fsync on an unmounting object. - * - * XXX: Is this comment true on FreeBSD? It seems likely, since - * unmounting is fairly non-atomic. - * - * The NetBSD kernel, in it's infinite wisdom, can try to fsync after - * an unmount has been initiated. This is a Bad Thing, which we have - * to avoid. Not a legitimate failure for stats. - */ - if (IS_UNMOUNTING(cp)) - return (ENODEV); - - /* - * Check for fsync of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_SAT(CODA_FSYNC_STATS); - return (0); - } - if (convp != NULL) { - vn_lock(convp, LK_EXCLUSIVE | LK_RETRY); - VOP_FSYNC(convp, MNT_WAIT, td); - VOP_UNLOCK(convp, 0); - } - - /* - * We see fsyncs with usecount == 1 then usecount == 0. For now we - * ignore them. - */ -#if 0 - VI_LOCK(vp); - if (!vp->v_usecount) { - printf("coda_fsync on vnode %p with %d usecount. " - "c_flags = %x (%x)\n", vp, vp->v_usecount, cp->c_flags, - cp->c_flags&C_PURGING); - } - VI_UNLOCK(vp); -#endif - - /* - * We can expect fsync on any vnode at all if venus is purging it. - * Venus can't very well answer the fsync request, now can it? - * Hopefully, it won't have to, because hopefully, venus preserves - * the (possibly untrue) invariant that it never purges an open - * vnode. Hopefully. - */ - if (cp->c_flags & C_PURGING) - return (0); - - /* XXX: needs research */ - return (0); - error = venus_fsync(vtomi(vp), &cp->c_fid, td->td_proc); - CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n", error));); - return (error); -} - -int -coda_inactive(struct vop_inactive_args *ap) -{ - /* - * XXX - at the moment, inactive doesn't look at cred, and doesn't - * have a proc pointer. Oops. - */ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct ucred *cred __attribute__((unused)) = NULL; - struct thread *td __attribute__((unused)) = curthread; - /* upcall decl */ - /* locals */ - - /* - * We don't need to send inactive to venus - DCS. - */ - MARK_ENTRY(CODA_INACTIVE_STATS); - CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %s, vfsp %p\n", - coda_f2s(&cp->c_fid), vp->v_mount));); - vp->v_object = NULL; - - /* - * If an array has been allocated to hold the symlink, deallocate it. - */ - if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { - if (cp->c_symlink == NULL) - panic("coda_inactive: null symlink pointer in cnode"); - CODA_FREE(cp->c_symlink, cp->c_symlen); - cp->c_flags &= ~C_SYMLINK; - cp->c_symlen = 0; - } - - /* - * Remove it from the table so it can't be found. - */ - coda_unsave(cp); - if ((struct coda_mntinfo *)(vp->v_mount->mnt_data) == NULL) { - myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p " - "wasn't dying\n", vp)); - panic("badness in coda_inactive\n"); - } - if (IS_UNMOUNTING(cp)) { -#ifdef DEBUG - printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n", - vrefcnt(vp), vp, cp); - if (cp->c_ovp != NULL) - printf("coda_inactive: cp->ovp != NULL use %d: vp " - "%p, cp %p\n", vrefcnt(vp), vp, cp); -#endif - } else - vgone(vp); - MARK_INT_SAT(CODA_INACTIVE_STATS); - return (0); -} - -/* - * Remote filesystem operations having to do with directory manipulation. - */ - -/* - * In FreeBSD, lookup returns the vnode locked. - */ -int -coda_lookup(struct vop_cachedlookup_args *ap) -{ - /* true args */ - struct vnode *dvp = ap->a_dvp; - struct cnode *dcp = VTOC(dvp); - struct vnode **vpp = ap->a_vpp; - /* - * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest of - * the string to xlate, and that we must try to get at least - * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth. I - * could be wrong. - */ - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - struct cnode *cp; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - struct CodaFid VFid; - int vtype; - int error = 0; - - MARK_ENTRY(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %s\n", nm, - coda_f2s(&dcp->c_fid)));); - - /* - * Check for lookup of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - *vpp = coda_ctlvp; - vref(*vpp); - MARK_INT_SAT(CODA_LOOKUP_STATS); - goto exit; - } - if (len+1 > CODA_MAXNAMLEN) { - MARK_INT_FAIL(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, " - "%s (%s)\n", coda_f2s(&dcp->c_fid), nm));); - *vpp = NULL; - error = EINVAL; - goto exit; - } - - error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, - td->td_proc, &VFid, &vtype); - if (error) { - MARK_INT_FAIL(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %s " - "(%s)%d\n", coda_f2s(&dcp->c_fid), nm, error));); - *vpp = NULL; - } else { - MARK_INT_SAT(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s type %o " - "result %d\n", coda_f2s(&VFid), vtype, error));); - cp = make_coda_node(&VFid, dvp->v_mount, vtype); - *vpp = CTOV(cp); - - /* - * Enter the new vnode in the namecache only if the top bit - * isn't set. - * - * And don't enter a new vnode for an invalid one! - */ - if (!(vtype & CODA_NOCACHE) && (cnp->cn_flags & MAKEENTRY)) - cache_enter(dvp, *vpp, cnp); - } -exit: - /* - * If we are creating, and this was the last name to be looked up, - * and the error was ENOENT, then there really shouldn't be an error - * and we can make the leaf NULL and return success. Since this is - * supposed to work under Mach as well as FreeBSD, we're leaving this - * fn wrapped. We also must tell lookup/namei that we need to save - * the last component of the name. (Create will have to free the - * name buffer later...lucky us...). - */ - if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)) - && (cnp->cn_flags & ISLASTCN) && (error == ENOENT)) { - error = EJUSTRETURN; - cnp->cn_flags |= SAVENAME; - *ap->a_vpp = NULL; - } - - /* - * If we are removing, and we are at the last element, and we found - * it, then we need to keep the name around so that the removal will - * go ahead as planned. Unfortunately, this will probably also lock - * the to-be-removed vnode, which may or may not be a good idea. - * I'll have to look at the bits of coda_remove to make sure. We'll - * only save the name if we did in fact find the name, otherwise - * coda_remove won't have a chance to free the pathname. - */ - if ((cnp->cn_nameiop == DELETE) && (cnp->cn_flags & ISLASTCN) - && !error) - cnp->cn_flags |= SAVENAME; - - /* - * If the lookup went well, we need to (potentially?) unlock the - * parent, and lock the child. We are only responsible for checking - * to see if the parent is supposed to be unlocked before we return. - * We must always lock the child (provided there is one, and (the - * parent isn't locked or it isn't the same as the parent.) Simple, - * huh? We can never leave the parent locked unless we are ISLASTCN. - */ - if (!error || (error == EJUSTRETURN)) { - if (cnp->cn_flags & ISDOTDOT) { - VOP_UNLOCK(dvp, 0); - /* - * The parent is unlocked. As long as there is a - * child, lock it without bothering to check anything - * else. - */ - if (*ap->a_vpp) - vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); - vn_lock(dvp, LK_RETRY|LK_EXCLUSIVE); - } else { - /* - * The parent is locked, and may be the same as the - * child. If different, go ahead and lock it. - */ - if (*ap->a_vpp && (*ap->a_vpp != dvp)) - vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); - } - } else { - /* - * If the lookup failed, we need to ensure that the leaf is - * NULL. - * - * Don't change any locking? - */ - *ap->a_vpp = NULL; - } - return (error); -} - -/*ARGSUSED*/ -int -coda_create(struct vop_create_args *ap) -{ - /* true args */ - struct vnode *dvp = ap->a_dvp; - struct cnode *dcp = VTOC(dvp); - struct vattr *va = ap->a_vap; - int exclusive = 1; - int mode = ap->a_vap->va_mode; - struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - int error; - struct cnode *cp; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - struct CodaFid VFid; - struct vattr attr; - - MARK_ENTRY(CODA_CREATE_STATS); - - /* - * All creates are exclusive XXX. - * - * I'm assuming the 'mode' argument is the file mode bits XXX. - * - * Check for create of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - *vpp = (struct vnode *)0; - MARK_INT_FAIL(CODA_CREATE_STATS); - return (EACCES); - } - error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive, - mode, va, cred, td->td_proc, &VFid, &attr); - if (!error) { - /* - * If this is an exclusive create, panic if the file already - * exists. - * - * Venus should have detected the file and reported EEXIST. - */ - if ((exclusive == 1) && (coda_find(&VFid) != NULL)) - panic("cnode existed for newly created file!"); - cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type); - *vpp = CTOV(cp); - - /* - * Update va to reflect the new attributes. - */ - (*va) = attr; - - /* - * Update the attribute cache and mark it as valid. - */ - if (coda_attr_cache) { - VTOC(*vpp)->c_vattr = attr; - VTOC(*vpp)->c_flags |= C_VATTR; - } - - /* - * Invalidate the parent's attr cache, the modification time - * has changed. - */ - VTOC(dvp)->c_flags &= ~C_VATTR; - cache_enter(dvp, *vpp, cnp); - CODADEBUG(CODA_CREATE, myprintf(("create: %s, result %d\n", - coda_f2s(&VFid), error));); - } else { - *vpp = (struct vnode *)0; - CODADEBUG(CODA_CREATE, myprintf(("create error %d\n", - error));); - } - if (!error) { - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, *vpp, cnp); - if (cnp->cn_flags & LOCKLEAF) - vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); - } else if (error == ENOENT) { - /* - * XXXRW: We only enter a negative entry if ENOENT is - * returned, not other errors. But will Venus invalidate dvp - * properly in all cases when new files appear via the - * network rather than a local operation? - */ - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, NULL, cnp); - } - return (error); -} - -int -coda_remove(struct vop_remove_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct vnode *dvp = ap->a_dvp; - struct cnode *cp = VTOC(dvp); - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - int error; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; -#if 0 - struct cnode *tp; -#endif - - MARK_ENTRY(CODA_REMOVE_STATS); - CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %s\n", nm, - coda_f2s(&cp->c_fid)));); - - /* - * Check for remove of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - MARK_INT_FAIL(CODA_REMOVE_STATS); - return (ENOENT); - } - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. We don't yet know if the last reference to the file is - * being removed, but we do know the reference count on the child has - * changed, so invalidate its attr cache also. - */ - VTOC(dvp)->c_flags &= ~C_VATTR; - VTOC(vp)->c_flags &= ~(C_VATTR | C_ACCCACHE); - error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, - td->td_proc); - cache_purge(vp); - CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error));); - return (error); -} - -int -coda_link(struct vop_link_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct vnode *tdvp = ap->a_tdvp; - struct cnode *tdcp = VTOC(tdvp); - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - int error; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - - MARK_ENTRY(CODA_LINK_STATS); - - if (codadebug & CODADBGMSK(CODA_LINK)) { - myprintf(("nb_link: vp fid: %s\n", coda_f2s(&cp->c_fid))); - myprintf(("nb_link: tdvp fid: %s)\n", - coda_f2s(&tdcp->c_fid))); - } - if (codadebug & CODADBGMSK(CODA_LINK)) { - myprintf(("link: vp fid: %s\n", coda_f2s(&cp->c_fid))); - myprintf(("link: tdvp fid: %s\n", coda_f2s(&tdcp->c_fid))); - } - - /* - * Check for link to/from control object. - */ - if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_LINK_STATS); - return (EACCES); - } - error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len, - cred, td->td_proc); - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. - */ - VTOC(tdvp)->c_flags &= ~C_VATTR; - VTOC(vp)->c_flags &= ~C_VATTR; - CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error));); - return (error); -} - -int -coda_rename(struct vop_rename_args *ap) -{ - /* true args */ - struct vnode *fvp = ap->a_fvp; - struct vnode *tvp = ap->a_tvp; - struct vnode *odvp = ap->a_fdvp; - struct cnode *odcp = VTOC(odvp); - struct componentname *fcnp = ap->a_fcnp; - struct vnode *ndvp = ap->a_tdvp; - struct cnode *ndcp = VTOC(ndvp); - struct componentname *tcnp = ap->a_tcnp; - struct ucred *cred = fcnp->cn_cred; - struct thread *td = fcnp->cn_thread; - /* true args */ - int error; - const char *fnm = fcnp->cn_nameptr; - int flen = fcnp->cn_namelen; - const char *tnm = tcnp->cn_nameptr; - int tlen = tcnp->cn_namelen; - - MARK_ENTRY(CODA_RENAME_STATS); - - /* - * Check for rename involving control object. - */ - if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) { - MARK_INT_FAIL(CODA_RENAME_STATS); - return (EACCES); - } - - /* - * Remove the entries for both source and target directories, which - * should catch references to the children. Perhaps we could purge - * less? - */ - cache_purge(odvp); - cache_purge(ndvp); - - /* - * Invalidate parent directories as modification times have changed. - * Invalidate access cache on renamed file as rights may have - * changed. - */ - VTOC(odvp)->c_flags &= ~C_VATTR; - VTOC(ndvp)->c_flags &= ~C_VATTR; - VTOC(fvp)->c_flags &= ~C_ACCCACHE; - if (flen+1 > CODA_MAXNAMLEN) { - MARK_INT_FAIL(CODA_RENAME_STATS); - error = EINVAL; - goto exit; - } - if (tlen+1 > CODA_MAXNAMLEN) { - MARK_INT_FAIL(CODA_RENAME_STATS); - error = EINVAL; - goto exit; - } - error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm, - flen, tnm, tlen, cred, td->td_proc); -exit: - CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error));); - - /* - * Update namecache to reflect that the names of various objects may - * have changed (or gone away entirely). - */ - cache_purge(fvp); - cache_purge(tvp); - - /* - * Release parents first, then children. - */ - vrele(odvp); - if (tvp) { - if (tvp == ndvp) - vrele(ndvp); - else - vput(ndvp); - vput(tvp); - } else - vput(ndvp); - vrele(fvp); - return (error); -} - -int -coda_mkdir(struct vop_mkdir_args *ap) -{ - /* true args */ - struct vnode *dvp = ap->a_dvp; - struct cnode *dcp = VTOC(dvp); - struct componentname *cnp = ap->a_cnp; - struct vattr *va = ap->a_vap; - struct vnode **vpp = ap->a_vpp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - int error; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - struct cnode *cp; - struct CodaFid VFid; - struct vattr ova; - - MARK_ENTRY(CODA_MKDIR_STATS); - - /* - * Check for mkdir of target object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - *vpp = (struct vnode *)0; - MARK_INT_FAIL(CODA_MKDIR_STATS); - return (EACCES); - } - if (len+1 > CODA_MAXNAMLEN) { - *vpp = (struct vnode *)0; - MARK_INT_FAIL(CODA_MKDIR_STATS); - return (EACCES); - } - error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred, - td->td_proc, &VFid, &ova); - if (!error) { - if (coda_find(&VFid) != NULL) - panic("cnode existed for newly created directory!"); - cp = make_coda_node(&VFid, dvp->v_mount, va->va_type); - *vpp = CTOV(cp); - - /* - * Enter the new vnode in the Name Cache. - */ - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, *vpp, cnp); - - /* - * Update the attr cache and mark as valid. - */ - if (coda_attr_cache) { - VTOC(*vpp)->c_vattr = ova; - VTOC(*vpp)->c_flags |= C_VATTR; - } - - /* - * Invalidate the parent's attr cache, the modification time - * has changed. - */ - VTOC(dvp)->c_flags &= ~C_VATTR; - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); - CODADEBUG( CODA_MKDIR, myprintf(("mkdir: %s result %d\n", - coda_f2s(&VFid), error));); - } else { - *vpp = NULL; - CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error));); - } - return (error); -} - -int -coda_rmdir(struct vop_rmdir_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct vnode *dvp = ap->a_dvp; - struct cnode *dcp = VTOC(dvp); - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* true args */ - int error; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; -#if 0 - struct cnode *cp; -#endif - - MARK_ENTRY(CODA_RMDIR_STATS); - - /* - * Check for rmdir of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - MARK_INT_FAIL(CODA_RMDIR_STATS); - return (ENOENT); - } - - /* - * Possibly somewhat conservative purging, perhaps we just need to - * purge vp? - */ - cache_purge(dvp); - cache_purge(vp); - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. - */ - dcp->c_flags &= ~C_VATTR; - error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred, - td->td_proc); - CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error));); - return (error); -} - -int -coda_symlink(struct vop_symlink_args *ap) -{ - /* true args */ - struct vnode *tdvp = ap->a_dvp; - struct cnode *tdcp = VTOC(tdvp); - struct componentname *cnp = ap->a_cnp; - struct vattr *tva = ap->a_vap; - char *path = ap->a_target; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - struct vnode **vpp = ap->a_vpp; - /* locals */ - int error; - - /*- - * XXX I'm assuming the following things about coda_symlink's - * arguments: - * t(foo) is the new name/parent/etc being created. - * lname is the contents of the new symlink. - */ - char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - int plen = strlen(path); - - /* - * Here's the strategy for the moment: perform the symlink, then do a - * lookup to grab the resulting vnode. I know this requires two - * communications with Venus for a new sybolic link, but that's the - * way the ball bounces. I don't yet want to change the way the Mach - * symlink works. When Mach support is deprecated, we should change - * symlink so that the common case returns the resultant vnode in a - * vpp argument. - */ - MARK_ENTRY(CODA_SYMLINK_STATS); - - /* - * Check for symlink of control object. - */ - if (IS_CTL_NAME(tdvp, nm, len)) { - MARK_INT_FAIL(CODA_SYMLINK_STATS); - return (EACCES); - } - if (plen+1 > CODA_MAXPATHLEN) { - MARK_INT_FAIL(CODA_SYMLINK_STATS); - return (EINVAL); - } - if (len+1 > CODA_MAXNAMLEN) { - MARK_INT_FAIL(CODA_SYMLINK_STATS); - error = EINVAL; - goto exit; - } - error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len, - tva, cred, td->td_proc); - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. - */ - tdcp->c_flags &= ~C_VATTR; - if (error == 0) - error = VOP_LOOKUP(tdvp, vpp, cnp); -exit: - CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error));); - return (error); -} - -/* - * Read directory entries. - * - * XXX: This forwards the operator straight to the cache vnode using - * VOP_READDIR(), rather than calling venus_readdir(). Why? - */ -int -coda_readdir(struct vop_readdir_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct uio *uiop = ap->a_uio; - struct ucred *cred = ap->a_cred; - int *eofflag = ap->a_eofflag; - u_long **cookies = ap->a_cookies; - int *ncookies = ap->a_ncookies; - struct thread *td = ap->a_uio->uio_td; - /* upcall decl */ - /* locals */ - int error = 0; - int opened_internally = 0; - - MARK_ENTRY(CODA_READDIR_STATS); - CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %zd, %lld, %d)\n", - (void *)uiop->uio_iov->iov_base, uiop->uio_resid, - (long long)uiop->uio_offset, uiop->uio_segflg));); - - /* - * Check for readdir of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_READDIR_STATS); - return (ENOENT); - } - - /* - * If directory is not already open do an "internal open" on it. - * - * XXX: Why would this happen? For files, there's memory mapping, - * execution, and other kernel access paths such as ktrace. For - * directories, it is less clear. - */ - if (cp->c_ovp == NULL) { - opened_internally = 1; - MARK_INT_GEN(CODA_OPEN_STATS); - error = VOP_OPEN(vp, FREAD, cred, td, NULL); - printf("coda_readdir: Internally Opening %p\n", vp); - if (error) { - printf("coda_readdir: VOP_OPEN on container failed " - "%d\n", error); - return (error); - } - } - - /* - * Have UFS handle the call. - */ - CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = %s, " - "refcnt = %d\n", coda_f2s(&cp->c_fid), vp->v_usecount));); - vn_lock(cp->c_ovp, LK_SHARED | LK_RETRY); - error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, ncookies, - cookies); - VOP_UNLOCK(cp->c_ovp, 0); - if (error) - MARK_INT_FAIL(CODA_READDIR_STATS); - else - MARK_INT_SAT(CODA_READDIR_STATS); - - /* - * Do an "internal close" if necessary. - */ - if (opened_internally) { - MARK_INT_GEN(CODA_CLOSE_STATS); - (void)VOP_CLOSE(vp, FREAD, cred, td); - } - return (error); -} - -int -coda_reclaim(struct vop_reclaim_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - /* upcall decl */ - /* locals */ - - /* - * Forced unmount/flush will let vnodes with non-zero use be - * destroyed! - */ - ENTRY; - - if (IS_UNMOUNTING(cp)) { -#ifdef DEBUG - if (VTOC(vp)->c_ovp) { - if (IS_UNMOUNTING(cp)) - printf("coda_reclaim: c_ovp not void: vp " - "%p, cp %p\n", vp, cp); - } -#endif - } - cache_purge(vp); - coda_free(VTOC(vp)); - vp->v_data = NULL; - vp->v_object = NULL; - return (0); -} - -int -coda_lock(struct vop_lock1_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - /* upcall decl */ - /* locals */ - - ENTRY; - if ((ap->a_flags & LK_INTERLOCK) == 0) { - VI_LOCK(vp); - ap->a_flags |= LK_INTERLOCK; - } - if (coda_lockdebug) - myprintf(("Attempting lock on %s\n", coda_f2s(&cp->c_fid))); - return (vop_stdlock(ap)); -} - -int -coda_unlock(struct vop_unlock_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - /* upcall decl */ - /* locals */ - - ENTRY; - if (coda_lockdebug) - myprintf(("Attempting unlock on %s\n", - coda_f2s(&cp->c_fid))); - return (vop_stdunlock(ap)); -} - -int -coda_islocked(struct vop_islocked_args *ap) -{ - /* true args */ - - ENTRY; - return (vop_stdislocked(ap)); -} - -static void -coda_print_vattr(struct vattr *attr) -{ - char *typestr; - - switch (attr->va_type) { - case VNON: - typestr = "VNON"; - break; - - case VREG: - typestr = "VREG"; - break; - - case VDIR: - typestr = "VDIR"; - break; - - case VBLK: - typestr = "VBLK"; - break; - - case VCHR: - typestr = "VCHR"; - break; - - case VLNK: - typestr = "VLNK"; - break; - - case VSOCK: - typestr = "VSCK"; - break; - - case VFIFO: - typestr = "VFFO"; - break; - - case VBAD: - typestr = "VBAD"; - break; - - default: - typestr = "????"; - break; - } - myprintf(("attr: type %s mode %d uid %d gid %d fsid %d rdev %d\n", - typestr, (int)attr->va_mode, (int)attr->va_uid, - (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev)); - myprintf((" fileid %d nlink %d size %d blocksize %d bytes %d\n", - (int)attr->va_fileid, (int)attr->va_nlink, (int)attr->va_size, - (int)attr->va_blocksize,(int)attr->va_bytes)); - myprintf((" gen %ld flags %ld vaflags %d\n", attr->va_gen, - attr->va_flags, attr->va_vaflags)); - myprintf((" atime sec %d nsec %d\n", (int)attr->va_atime.tv_sec, - (int)attr->va_atime.tv_nsec)); - myprintf((" mtime sec %d nsec %d\n", (int)attr->va_mtime.tv_sec, - (int)attr->va_mtime.tv_nsec)); - myprintf((" ctime sec %d nsec %d\n", (int)attr->va_ctime.tv_sec, - (int)attr->va_ctime.tv_nsec)); -} - -/* - * How to print a ucred. - */ -void -coda_print_cred(struct ucred *cred) -{ - int i; - - myprintf(("ref %d\tuid %d\n",cred->cr_ref,cred->cr_uid)); - for (i=0; i < cred->cr_ngroups; i++) - myprintf(("\tgroup %d: (%d)\n",i,cred->cr_groups[i])); - myprintf(("\n")); -} - -/* - * Return a vnode for the given fid. If no cnode exists for this fid create - * one and put it in a table hashed by coda_f2i(). If the cnode for this fid - * is already in the table return it (ref count is incremented by coda_find. - * The cnode will be flushed from the table when coda_inactive calls - * coda_unsave. - */ -struct cnode * -make_coda_node(struct CodaFid *fid, struct mount *vfsp, short type) -{ - struct cnode *cp; - struct vnode *vp; - int err; - - /* - * XXXRW: This really needs a moderate amount of reworking. We need - * to properly tolerate failures of getnewvnode() and insmntque(), - * and callers need to be able to accept an error back from - * make_coda_node. There may also be more general issues in how we - * handle forced unmount. Finally, if/when Coda loses its dependency - * on Giant, the ordering of this needs rethinking. - */ - cp = coda_find(fid); - if (cp != NULL) { - vref(CTOV(cp)); - return (cp); - } - cp = coda_alloc(); - cp->c_fid = *fid; - err = getnewvnode("coda", vfsp, &coda_vnodeops, &vp); - if (err) - panic("coda: getnewvnode returned error %d\n", err); - vp->v_data = cp; - vp->v_type = type; - cp->c_vnode = vp; - coda_save(cp); - err = insmntque(vp, vfsp); - if (err != 0) - printf("coda: insmntque failed: error %d", err); - return (cp); -} - -int -coda_pathconf(struct vop_pathconf_args *ap) -{ - - switch (ap->a_name) { - case _PC_NAME_MAX: - *ap->a_retval = CODA_MAXNAMLEN; - return (0); - - case _PC_PATH_MAX: - *ap->a_retval = CODA_MAXPATHLEN; - return (0); - - default: - return (vop_stdpathconf(ap)); - } -} diff --git a/sys/fs/coda/coda_vnops.h b/sys/fs/coda/coda_vnops.h deleted file mode 100644 index e43b09f..0000000 --- a/sys/fs/coda/coda_vnops.h +++ /dev/null @@ -1,84 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_vnops.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -/* - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. - */ - -#ifndef _CODA_VNOPS_H_ -#define _CODA_VNOPS_H_ - -/* - * FreeBSD interfaces to the vnodeops. - */ -vop_open_t coda_open; -vop_close_t coda_close; -vop_read_t coda_read; -vop_write_t coda_write; -vop_ioctl_t coda_ioctl; -vop_getattr_t coda_getattr; -vop_setattr_t coda_setattr; -vop_access_t coda_access; -vop_readlink_t coda_readlink; -vop_fsync_t coda_fsync; -vop_inactive_t coda_inactive; -vop_cachedlookup_t coda_lookup; -vop_create_t coda_create; -vop_remove_t coda_remove; -vop_link_t coda_link; -vop_rename_t coda_rename; -vop_mkdir_t coda_mkdir; -vop_rmdir_t coda_rmdir; -vop_symlink_t coda_symlink; -vop_readdir_t coda_readdir; -vop_strategy_t coda_strategy; -vop_reclaim_t coda_reclaim; -vop_lock1_t coda_lock; -vop_unlock_t coda_unlock; -vop_islocked_t coda_islocked; -vop_pathconf_t coda_pathconf; - -int coda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, - int ioflag, struct ucred *cred, struct thread *td); -void coda_print_cred(struct ucred *cred); - -#endif /* !_CODA_VNOPS_H_ */ diff --git a/sys/fs/hpfs/hpfs.h b/sys/fs/hpfs/hpfs.h deleted file mode 100644 index fba0c45..0000000 --- a/sys/fs/hpfs/hpfs.h +++ /dev/null @@ -1,387 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -/*#define HPFS_DEBUG 10*/ -typedef u_int32_t lsn_t; /* Logical Sector Number */ -typedef struct { - lsn_t lsn1; - lsn_t lsn2; -} rsp_t; /* Redundant Sector Pointer */ -typedef struct { - u_int32_t cnt; - lsn_t lsn; -} sptr_t; /* Storage Pointer */ - -#define SUBLOCK 0x10 -#define SUSIZE DEV_BSIZE -#define SPBLOCK 0x11 -#define SPSIZE DEV_BSIZE -#define BMSIZE (4 * DEV_BSIZE) -#define HPFS_MAXFILENAME 255 - -#define SU_MAGIC ((u_int64_t)0xFA53E9C5F995E849) -struct sublock { - u_int64_t su_magic; - u_int8_t su_hpfsver; - u_int8_t su_fnctver; - u_int16_t unused; - lsn_t su_rootfno; /* Root Fnode */ - u_int32_t su_btotal; /* Total blocks */ - u_int32_t su_badbtotal; /* Bad Sectors total */ - rsp_t su_bitmap; - rsp_t su_badbl; - u_long su_chkdskdate; - u_long su_dskoptdate; - u_int32_t su_dbbsz; /* Sectors in DirBlock Band */ - lsn_t su_dbbstart; - lsn_t su_dbbend; - lsn_t su_dbbbitmap; - char su_volname[0x20]; - lsn_t su_uidt; /* Ptr to User ID Table (8 sect) */ -}; - -#define SP_MAGIC ((u_int64_t)0xFA5229C5F9911849) -#define SP_DIRTY 0x0001 -#define SP_SPDBINUSE 0x0002 -#define SP_HFINUSE 0x0004 -#define SP_BADSECT 0x0008 -#define SP_BADBMBL 0x0010 -#define SP_FASTFRMT 0x0020 -#define SP_OLDHPFS 0x0080 -#define SP_IDASD 0x0100 -#define SP_RDASD 0x0200 -#define SP_DASD 0x0400 -#define SP_MMACTIVE 0x0800 -#define SP_DCEACLS 0x1000 -#define SP_DSADDIRTY 0x2000 -struct spblock { - u_int64_t sp_magic; - u_int16_t sp_flag; - u_int8_t sp_mmcontf; - u_int8_t unused; - lsn_t sp_hf; /* HotFix list */ - u_int32_t sp_hfinuse; /* HotFixes in use */ - u_int32_t sp_hfavail; /* HotFixes available */ - u_int32_t sp_spdbavail; /* Spare DirBlocks available */ - u_int32_t sp_spdbmax; /* Spare DirBlocks maximum */ - lsn_t sp_cpi; - u_int32_t sp_cpinum; - u_int32_t sp_suchecksum; - u_int32_t sp_spchecksum; - u_int8_t reserved[0x3C]; - lsn_t sp_spdb[0x65]; -}; - -#define DE_SPECIAL 0x0001 -#define DE_ACL 0x0002 -#define DE_DOWN 0x0004 -#define DE_END 0x0008 -#define DE_EALIST 0x0010 -#define DE_EPERM 0x0020 -#define DE_EXPLACL 0x0040 -#define DE_NEEDEA 0x0080 -#define DE_RONLY 0x0100 -#define DE_HIDDEN 0x0200 -#define DE_SYSTEM 0x0400 -#define DE_VOLLABEL 0x0800 -#define DE_DIR 0x1000 -#define DE_ARCHIV 0x2000 -#define DE_DOWNLSN(dep) (*(lsn_t *)((caddr_t)(dep) + (dep)->de_reclen - sizeof(lsn_t))) -#define DE_NEXTDE(dep) ((struct hpfsdirent *)((caddr_t)(dep) + (dep)->de_reclen)) -typedef struct hpfsdirent { - u_int16_t de_reclen; - u_int16_t de_flag; - lsn_t de_fnode; - u_long de_mtime; - u_int32_t de_size; - u_long de_atime; - u_long de_ctime; - u_int32_t de_ealen; - u_int8_t de_flexflag; - u_int8_t de_cpid; - u_int8_t de_namelen; - char de_name[1]; -/* ... de_flex; */ -/* lsn_t de_down; */ -} hpfsdirent_t; - -#define D_BSIZE (DEV_BSIZE*4) -#define D_MAGIC 0x77E40AAE -#define D_DIRENT(dbp) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t))) -#define D_DE(dbp, deoff) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t) + (deoff))) -typedef struct dirblk { - u_int32_t d_magic; - u_int32_t d_freeoff; /* Offset of first free byte */ - u_int32_t d_chcnt; /* Change count */ - lsn_t d_parent; - lsn_t d_self; -} dirblk_t; - -/* - * Allocation Block (ALBLK) - */ -#define AB_HBOFFEO 0x01 -#define AB_FNPARENT 0x20 -#define AB_SUGGBSCH 0x40 -#define AB_NODES 0x80 -#define AB_ALLEAF(abp) ((alleaf_t *)((caddr_t)(abp) + sizeof(alblk_t))) -#define AB_ALNODE(abp) ((alnode_t *)((caddr_t)(abp) + sizeof(alblk_t))) -#define AB_FREEALP(abp) ((alleaf_t *)((caddr_t)(abp) + (abp)->ab_freeoff)) -#define AB_FREEANP(abp) ((alnode_t *)((caddr_t)(abp) + (abp)->ab_freeoff)) -#define AB_LASTALP(abp) (AB_ALLEAF(abp) + (abp)->ab_busycnt - 1) -#define AB_LASTANP(abp) (AB_ALNODE(abp) + (abp)->ab_busycnt - 1) -#define AB_ADDNREC(abp, sz, n) { \ - (abp)->ab_busycnt += (n); \ - (abp)->ab_freecnt -= (n); \ - (abp)->ab_freeoff += (n) * (sz); \ -} -#define AB_RMNREC(abp, sz, n) { \ - (abp)->ab_busycnt -= (n); \ - (abp)->ab_freecnt += (n); \ - (abp)->ab_freeoff -= (n) * (sz);\ -} -#define AB_ADDAL(abp) AB_ADDNREC(abp,sizeof(alleaf_t), 1) -#define AB_ADDAN(abp) AB_ADDNREC(abp,sizeof(alnode_t), 1) -#define AB_RMAL(abp) AB_RMNREC(abp,sizeof(alleaf_t), 1) -#define AB_RMAN(abp) AB_RMNREC(abp,sizeof(alnode_t), 1) -typedef struct alblk { - u_int8_t ab_flag; - u_int8_t ab_res[3]; - u_int8_t ab_freecnt; - u_int8_t ab_busycnt; - u_int16_t ab_freeoff; -} alblk_t; - -/* - * FNode - */ -#define FNODESIZE DEV_BSIZE -#define FN_MAGIC 0xF7E40AAE -struct fnode { - u_int32_t fn_magic; - u_int64_t fn_readhist; - u_int8_t fn_namelen; - char fn_name[0xF]; /* First 15 symbols or less */ - lsn_t fn_parent; - sptr_t fn_extacl; - u_int16_t fn_acllen; - u_int8_t fn_extaclflag; - u_int8_t fn_histbitcount; - sptr_t fn_extea; - u_int16_t fn_ealen; /* Len of EAs in Fnode */ - u_int8_t fn_exteaflag; /* EAs in exteas */ - u_int8_t fn_flag; - alblk_t fn_ab; - u_int8_t fn_abd[0x60]; - u_int32_t fn_size; - u_int32_t fn_reqea; - u_int8_t fn_uid[0x10]; - u_int16_t fn_intoff; - u_int8_t fn_1dasdthr; - u_int8_t fn_dasdthr; - u_int32_t fn_dasdlim; - u_int32_t fn_dasdusage; - u_int8_t fn_int[0x13c]; -}; - -#define EA_NAME(eap) ((char *)(((caddr_t)(eap)) + sizeof(struct ea))) -struct ea { - u_int8_t ea_type; /* 0 - plain val */ - /* 1 - sptr to val */ - /* 3 - lsn point to AlSec, cont. val */ - u_int8_t ea_namelen; - u_int16_t ea_vallen; - /*u_int8_t ea_name[]; */ - /*u_int8_t ea_val[]; */ -}; - -/* - * Allocation Block Data (ALNODE) - * - * NOTE: AlNodes are used when there are too many fragments - * to represent the data in the AlBlk - */ -#define AN_SET(anp,nextoff,lsn) { \ - (anp)->an_nextoff = (nextoff); \ - (anp)->an_lsn = (lsn); \ -} -typedef struct alnode { - u_int32_t an_nextoff; /* next node offset in blocks */ - lsn_t an_lsn; /* position of AlSec structure */ -} alnode_t; - -/* - * Allocaion Block Data (ALLEAF) - * - * NOTE: Leaves are used to point at contiguous block of data - * (a fragment or an "extent"); - */ -#define AL_SET(alp,off,len,lsn) { \ - (alp)->al_off = (off); \ - (alp)->al_len = (len); \ - (alp)->al_lsn = (lsn); \ -} -typedef struct alleaf { - u_int32_t al_off; /* offset in blocks */ - u_int32_t al_len; /* len in blocks */ - lsn_t al_lsn; /* phys position */ -} alleaf_t; - -/* - * Allocation Sector - * - * NOTE: AlSecs are not initialized before use, so they ussually - * look full of junk. Use the AlBlk tto validate the data. - */ -#define AS_MAGIC 0x37E40AAE -typedef struct alsec { - u_int32_t as_magic; - lsn_t as_self; - lsn_t as_parent; - alblk_t as_ab; - u_int8_t as_abd[0x1E0]; -} alsec_t; - -/* - * Code Page structures - */ -struct cpdblk { - u_int16_t b_country; /* Country code */ - u_int16_t b_cpid; /* CP ID */ - u_int16_t b_dbcscnt; /* Count of DBCS ranges in CP */ - char b_upcase[0x80]; /* Case conversion table */ - u_int16_t b_dbcsrange; /* Start/End DBCS range pairs */ - -}; - -#define CPD_MAGIC ((u_int32_t)0x894521F7) -struct cpdsec { - u_int32_t d_magic; - u_int16_t d_cpcnt; /* CP Data count */ - u_int16_t d_cpfirst; /* Index of first CP Data */ - u_int32_t d_checksum[3]; /* CP Data checksumms */ - u_int16_t d_offset[3]; /* Offsets of CP Data blocks */ - struct cpdblk d_cpdblk[3]; /* Array of CP Data Blocks */ -}; - -struct cpiblk { - u_int16_t b_country; /* Country code */ - u_int16_t b_cpid; /* CP ID */ - u_int32_t b_checksum; - lsn_t b_cpdsec; /* Pointer to CP Data Sector */ - u_int16_t b_vcpid; /* Volume spec. CP ID */ - u_int16_t b_dbcscnt; /* Count of DBCS ranges in CP */ -}; - -#define CPI_MAGIC ((u_int32_t)0x494521F7) -struct cpisec { - u_int32_t s_magic; - u_int32_t s_cpicnt; /* Count of CPI's in this sector */ - u_int32_t s_cpifirst; /* Index of first CPI in this sector */ - lsn_t s_next; /* Pointer to next CPI Sector */ - struct cpiblk s_cpi[0x1F]; /* Array of CPI blocks */ -}; - -struct hpfsmount { - struct sublock hpm_su; - struct spblock hpm_sp; - struct mount * hpm_mp; - struct vnode * hpm_devvp; /* XXX: lose this, it's in hpfsmount */ - struct g_consumer *hpm_cp; - struct bufobj *hpm_bo; - struct cdev *hpm_dev; - uid_t hpm_uid; - gid_t hpm_gid; - mode_t hpm_mode; - - lsn_t * hpm_bmind; - struct cpdblk * hpm_cpdblk; /* Array of CP Data Blocks */ - u_char hpm_u2d[0x80]; /* Unix to DOS Table*/ - u_char hpm_d2u[0x80]; /* DOS to Unix Table*/ - - u_long hpm_bavail; /* Blocks available */ - u_long hpm_dbnum; /* Data Band number */ - u_int8_t * hpm_bitmap; -}; - -#define H_PARVALID 0x0002 /* parent info is valid */ -#define H_CHANGE 0x0004 /* node date was changed */ -#define H_PARCHANGE 0x0008 /* parent node date was changed */ -#define H_INVAL 0x0010 /* Invalid node */ -struct hpfsnode { - struct mtx h_interlock; - - struct hpfsmount *h_hpmp; - struct fnode h_fn; - struct vnode * h_vp; - struct vnode * h_devvp; /* XXX: remove, hpfsmount has it */ - struct cdev *h_dev; - lsn_t h_no; - uid_t h_uid; - gid_t h_gid; - mode_t h_mode; - u_int32_t h_flag; - - /* parent dir information */ - u_long h_mtime; - u_long h_atime; - u_long h_ctime; - char h_name[HPFS_MAXFILENAME+1]; /* Used to speedup dirent */ - int h_namelen; /* lookup */ -}; - -/* This overlays the fid structure (see <sys/mount.h>) */ -struct hpfid { - u_int16_t hpfid_len; /* Length of structure. */ - u_int16_t hpfid_pad; /* Force 32-bit alignment. */ - lsn_t hpfid_ino; /* File number (ino). */ - int32_t hpfid_gen; /* Generation number. */ -}; - -#if defined(HPFS_DEBUG) -#define dprintf(a) printf a -#if HPFS_DEBUG > 1 -#define ddprintf(a) printf a -#else -#define ddprintf(a) -#endif -#else -#define dprintf(a) -#define ddprintf(a) -#endif - -#if __FreeBSD_version >= 300000 -MALLOC_DECLARE(M_HPFSMNT); -MALLOC_DECLARE(M_HPFSNO); -#endif -#define VFSTOHPFS(mp) ((struct hpfsmount *)((mp)->mnt_data)) -#define VTOHP(v) ((struct hpfsnode *)((v)->v_data)) -#define HPTOV(h) ((struct vnode *)((h)->h_vp)) -#define FID(f) (*((lsn_t *)(f)->fid_data)) - -extern struct vop_vector hpfs_vnodeops; diff --git a/sys/fs/hpfs/hpfs_alsubr.c b/sys/fs/hpfs/hpfs_alsubr.c deleted file mode 100644 index 226865f..0000000 --- a/sys/fs/hpfs/hpfs_alsubr.c +++ /dev/null @@ -1,907 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/malloc.h> -#include <sys/bio.h> -#include <sys/buf.h> - -#include <fs/hpfs/hpfs.h> -#include <fs/hpfs/hpfs_subr.h> - -#define AE_DONE 0 /* Nothing to change */ -#define AE_SPLIT 2 /* Split was done, ranp is valid */ - -int hpfs_addextentr (struct hpfsmount *, lsn_t, alleaf_t *, - alnode_t *, u_long *); -int hpfs_allocalsec (struct hpfsmount *, lsn_t, struct buf **); -int hpfs_alblk2alsec (struct hpfsmount *, alblk_t *, alsec_t **, - struct buf **); -int hpfs_splitalsec (struct hpfsmount *, alsec_t *, alsec_t **, - struct buf **); -int hpfs_concatalsec (struct hpfsmount *, alsec_t *, alsec_t *, - alnode_t *); - -/* - * Map file offset to disk offset. hpfsnode have to be locked. - */ -int -hpfs_hpbmap(hp, bn, bnp, runp) - struct hpfsnode *hp; - daddr_t bn; - daddr_t *bnp; - int *runp; -{ - struct buf *bp; - alblk_t * abp; - alleaf_t *alp; - alnode_t *anp; - int error, i; - - dprintf(("hpfs_hpbmap(0x%x, 0x%x): ",hp->h_no, bn)); - - bp = NULL; - abp = &hp->h_fn.fn_ab; - alp = (alleaf_t *)&hp->h_fn.fn_abd; - anp = (alnode_t *)&hp->h_fn.fn_abd; - -dive: - if (abp->ab_flag & AB_NODES) { - for (i=0; i<abp->ab_busycnt; i++, anp++) { - dprintf(("[0x%x,0x%x] ",anp->an_nextoff,anp->an_lsn)); - if (bn < anp->an_nextoff) { - alsec_t *asp; - - dprintf(("< found | ")); - - if (bp) - brelse(bp); - error = bread(hp->h_devvp, anp->an_lsn, - DEV_BSIZE, NOCRED, &bp); - if (error) { - printf("hpfs_hpbmap: bread error\n"); - brelse(bp); - return (error); - } - - asp = (alsec_t *) bp->b_data; - if (asp->as_magic != AS_MAGIC) { - brelse(bp); - printf("hpfs_hpbmap: " - "MAGIC DOESN'T MATCH"); - return (EINVAL); - } - - abp = &asp->as_ab; - alp = (alleaf_t *)&asp->as_abd; - anp = (alnode_t *)&asp->as_abd; - - goto dive; - } - } - } else { - for (i=0; i<abp->ab_busycnt; i++, alp++) { - dprintf(("[0x%x,0x%x,0x%x] ", - alp->al_off,alp->al_len,alp->al_lsn)); - - if ((bn >= alp->al_off) && - (!alp->al_len || (bn < alp->al_off + alp->al_len))) { - dprintf(("found, ")); - - *bnp = bn - alp->al_off + alp->al_lsn; - - dprintf((" 0x%x ", *bnp)); - - if (runp != NULL) { - if (alp->al_len) - *runp = alp->al_off - 1 + - alp->al_len - bn; - else - *runp = 3; /* XXX */ - - dprintf((" 0x%x cont", *runp)); - } - - if (bp) - brelse(bp); - - dprintf(("\n")); - return (0); - } - } - } - - dprintf(("END, notfound\n")); - if (bp) - brelse(bp); - - dprintf(("hpfs_hpbmap: offset too big\n")); - - return (EFBIG); -} - -/* - * Find place and preinitialize AlSec structure - * AlBlk is initialized to contain AlLeafs. - */ -int -hpfs_allocalsec ( - struct hpfsmount *hpmp, - lsn_t parlsn, - struct buf **bpp) -{ - alsec_t * asp; - struct buf * bp; - lsn_t lsn; - int error; - - *bpp = NULL; - - error = hpfs_bmfblookup(hpmp, &lsn); - if (error) { - printf("hpfs_allocalsec: CAN'T ALLOC SPACE FOR AlSec\n"); - return (error); - } - - error = hpfs_bmmarkbusy(hpmp, lsn, 1); - if (error) - return (error); - - bp = getblk(hpmp->hpm_devvp, lsn, DEV_BSIZE, 0, 0, 0); - clrbuf(bp); - - /* Fill AlSec info */ - asp = (alsec_t *) bp->b_data; - asp->as_magic = AS_MAGIC; - asp->as_self = lsn; - asp->as_parent = parlsn; - - /* Fill AlBlk */ - asp->as_ab.ab_flag = 0; - asp->as_ab.ab_busycnt = 0; - asp->as_ab.ab_freecnt = 0x28; - asp->as_ab.ab_freeoff = sizeof(alblk_t); - - *bpp = bp; - - return (0); -} - -/* - * Split AlSec structure into new allocated: - * allocate new AlSec; then move second half of asp's entries in - * into it; set proper flags. - * - * IF AlSec CONTAINS AlNodes, THEN YOU ALMOST EVERYTIME HAVE TO - * FIX LAST AlNode in OLD AlSec (NEXTOFF TO BE 0xFFFFFFFF). - * TOGETHER WITH FIXING ALL CHILDREN'S AlSecs (THEY HAVE GOT NEW PARENT). - */ -int -hpfs_splitalsec ( - struct hpfsmount *hpmp, - alsec_t *asp, - alsec_t **naspp, - struct buf **nbpp) -{ - alsec_t *nasp; - struct buf *nbp; - alblk_t *abp; - alblk_t *nabp; - int error, n1, n2, sz; - - error = hpfs_allocalsec(hpmp, asp->as_parent, &nbp); - if (error) - return (error); - - nasp = (alsec_t *)nbp->b_data; - nabp = &nasp->as_ab; - abp = &asp->as_ab; - - n1 = (abp->ab_busycnt + 1) / 2; - n2 = (abp->ab_busycnt - n1); - sz = (abp->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t); - - bcopy((caddr_t)abp + sizeof(alblk_t) + n1 * sz, - (caddr_t)nabp + sizeof(alblk_t), n2 * sz); - - nabp->ab_flag = abp->ab_flag; - nabp->ab_busycnt = n2; - nabp->ab_freecnt = (0x1e0 / sz - n2); - nabp->ab_freeoff += n2 * sz; - - abp->ab_busycnt -= n1; - abp->ab_freecnt += n1; - abp->ab_freeoff -= n1 * sz; - - *naspp = nasp; - *nbpp = nbp; - - return (0); -} - -/* - * Try to concatenate two AlSec's - * - * Moves all entries from AlSec corresponding (as1p, aanp[1]) into - * corresponding aanp[0] one. If not enought space, then return ENOSPC. - * - * WARNING! YOU HAVE TO FIX aanp VALUES YOURSELF LATER: - * aanp[0].an_nextoff = aanp[1].an_nextoff; - */ -int -hpfs_concatalsec ( - struct hpfsmount *hpmp, - alsec_t *as0p, - alsec_t *as1p, - alnode_t *aanp) -{ - alblk_t *ab0p; - alblk_t *ab1p; - int sz; - - dprintf(("hpfs_concatalsec: AlSecs at 0x%x and 0x%x \n", - as0p->as_self,as1p->as_self)); - - ab0p = &as0p->as_ab; - ab1p = &as1p->as_ab; - sz = (ab0p->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t); - - if (ab0p->ab_freecnt > ab1p->ab_busycnt) { - /* - * Concatenate AlSecs - */ - if (ab0p->ab_flag & AB_NODES) - AB_LASTANP(ab0p)->an_nextoff = aanp[0].an_nextoff; - - bcopy (AB_ALNODE(ab1p), AB_FREEANP(ab0p), - ab1p->ab_busycnt * sz); - - AB_ADDNREC(ab0p, sz, ab1p->ab_busycnt); - - return (0); - } else { - /* Not enought space to concatenate */ - return (ENOSPC); - } -} - -/* - * Transform AlBlk structure into new allocated - * AlSec. - * - * DOESN'T SET AlSec'S PARENT LSN. - */ -int -hpfs_alblk2alsec ( - struct hpfsmount *hpmp, - alblk_t *abp, - alsec_t **naspp, - struct buf **nbpp) -{ - alsec_t *nasp; - alblk_t *nabp; - struct buf *nbp; - int error, sz; - - error = hpfs_allocalsec(hpmp, 0, &nbp); - if (error) - return (error); - - nasp = (alsec_t *)nbp->b_data; - nabp = &nasp->as_ab; - - sz = (abp->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t); - - bcopy (abp, nabp, sizeof(alblk_t) + sz * abp->ab_busycnt); - - nabp->ab_freecnt = 0x1e0 / sz - nabp->ab_busycnt; - - *naspp = nasp; - *nbpp = nbp; - - return (0); -} - -/* - * Allocate len blocks and concatenate them to file. - * If we hadn't found contignous run of len blocks, concatenate - * as much as we can, and return. - * - */ -int -hpfs_addextent ( - struct hpfsmount *hpmp, - struct hpfsnode *hp, - u_long len) -{ - alblk_t *rabp; - alnode_t ranp[2]; - alleaf_t al; - int error; - u_long pf; - - /* - * We don't know for now start lsn of block - */ - al.al_lsn = ~0; - al.al_len = len; - al.al_off = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT; - - rabp = &hp->h_fn.fn_ab; - - /* Init AlBlk if this is first extent */ - if (al.al_off == 0) { - lsn_t nlsn; - u_long nlen; - - dprintf(("hpfs_addextent: init AlBlk in root\n")); - - rabp->ab_busycnt = 0; - rabp->ab_freecnt = 0x8; - rabp->ab_freeoff = sizeof(alblk_t); - rabp->ab_flag = 0; - - error = hpfs_bmlookup (hpmp, 0, hp->h_no + 1, al.al_len, &nlsn, &nlen); - if (error) - return (error); - - error = hpfs_bmmarkbusy(hpmp, nlsn, nlen); - if (error) - return (error); - - dprintf(("hpfs_addextent: new: 0x%x 0x%lx, ", nlsn, nlen)); - - AL_SET(AB_FREEALP(rabp), al.al_off, nlen, nlsn); - AB_ADDAL(rabp); - - al.al_off += nlen; - al.al_len -= nlen; - } - -retry: - dprintf(("hpfs_addextent: AlBlk: [0x%x, 0x%x, 0x%x] need: 0x%x\n", - rabp->ab_freecnt, rabp->ab_busycnt, rabp->ab_flag, al.al_len)); - - while ((al.al_len) && (rabp->ab_freecnt > 0)) { - if (rabp->ab_flag & AB_NODES) { - alnode_t *anp; - /* - * This is level containing AlNodes, so try to - * insert recursively into last entry. - */ - anp = AB_LASTANP(rabp); - dprintf(("hpfs_addextent: AlNode: [0x%x,0x%x] \n", - anp->an_nextoff,anp->an_lsn)); - - /* - * Try to insert... - */ - error = hpfs_addextentr (hpmp, anp->an_lsn, &al, ranp, &pf); - if (error) { - printf("hpfs_addextent: FAILED %d\n",error); - return (error); - } - - switch (pf) { - case AE_SPLIT: - dprintf(("hpfs_addextent: successful (split)\n")); - /* - * Then hpfs_addextentr has split tree below, now - * we need to fix this level. Particulary: - * fix last AlNode and add another one. - */ - - bcopy(ranp, AB_LASTANP(rabp), sizeof(alnode_t) * 2); - AB_ADDAN(rabp); - break; - - default: - case AE_DONE: - dprintf(("hpfs_addextent: successful\n")); - break; - } - } else { - alleaf_t *alp; - - alp = AB_LASTALP(rabp); - dprintf(("hpfs_addextent: AlLeaf: [0x%x,0x%x,0x%x] \n", - alp->al_off,alp->al_len,alp->al_lsn)); - - /* Check if we trying to add in right place */ - if (alp->al_off + alp->al_len == al.al_off) { - lsn_t nlsn; - u_long nlen; - - /* - * Search bitmap for block begining from - * alp->al_lsn + alp->al_len and long of ralp->al_len - */ - error = hpfs_bmlookup (hpmp, 0, - alp->al_lsn + alp->al_len, al.al_len, &nlsn, &nlen); - if (error) - return (error); - - error = hpfs_bmmarkbusy(hpmp, nlsn, nlen); - if (error) - return (error); - - dprintf(("hpfs_addextent: new: 0x%x 0x%lx, ", nlsn, nlen)); - - if (alp->al_lsn + alp->al_len == nlsn) { - dprintf(("extended existed leaf\n")); - - alp->al_len += nlen; - } else { - dprintf(("created new leaf\n")); - AL_SET(AB_FREEALP(rabp), al.al_off, nlen, nlsn); - AB_ADDAL(rabp); - } - al.al_off += nlen; - al.al_len -= nlen; - } else { - printf("hpfs_addextent: INTERNAL INCONSISTENCE\n"); - return (EINVAL); - } - } - } - - /* - * Move AlBlk contain to new AlSec (it will fit more - * entries) if overflowed (no more free entries). - */ - if (rabp->ab_freecnt <= 0) { - struct buf *nbp; - alsec_t * nrasp; - - dprintf(("hpfs_addextent: overflow, convt\n")); - - /* - * Convert AlBlk to new AlSec, it will set - * AB_FNPARENT also. - */ - rabp->ab_flag |= AB_FNPARENT; - error = hpfs_alblk2alsec (hpmp, rabp, &nrasp, &nbp); - if (error) { - printf("hpfs_addextent: CAN'T CONVT\n"); - return (error); - } - nrasp->as_parent = hp->h_no; - - /* - * Scan all childrens (if exist), set new parent and - * clean their AB_FNPARENT flag. - */ - if (rabp->ab_flag & AB_NODES) { - int i; - alsec_t * asp; - alnode_t * anp; - struct buf * bp; - - anp = AB_ALNODE(rabp); - for (i=0; i<rabp->ab_busycnt; i++) { - error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp); - if (error) - return (error); - - asp = (alsec_t *)bp->b_data; - asp->as_ab.ab_flag &= ~AB_FNPARENT; - asp->as_parent = nrasp->as_self; - - bdwrite(bp); - anp ++; - } - } - - /* Convert AlBlk to contain AlNodes */ - rabp->ab_flag = AB_NODES; - rabp->ab_busycnt = 0; - rabp->ab_freecnt = 0xC; - rabp->ab_freeoff = sizeof(alblk_t); - - /* Add AlNode for new allocated AlSec */ - AN_SET(AB_FREEANP(rabp), ~0, nrasp->as_self); - AB_ADDAN(rabp); - - bdwrite(nbp); - } - - if (al.al_len) { - dprintf(("hpfs_addextent: root retry\n")); - goto retry; - } - - return (0); -} - -/* - * Descent down to the end of tree, then search for - * ralp->len contignous run begining from last run's end and - * concatenate new block! If we can't find one, then... - */ -int -hpfs_addextentr ( - struct hpfsmount *hpmp, /* Mix info */ - lsn_t rlsn, /* LSN containing AlSec */ - alleaf_t *ralp, /* AlLeaf to insert */ - alnode_t *ranp, /* New AlNodes' values */ - u_long *resp) /* Mix returning info */ -{ - struct buf *rbp; - alsec_t *rasp; - alblk_t *rabp; - alleaf_t *alp; - alnode_t *anp; - int error; - u_long pf; - u_long wb; - - *resp = 0; - - dprintf(("hpfs_addextentr: AlSec at 0x%x\n", rlsn)); - - error = hpfs_breadalsec(hpmp, rlsn, &rbp); - if (error) - return (error); - - rasp = (alsec_t *)rbp->b_data; - rabp = &rasp->as_ab; - wb = 0; - - dprintf(("hpfs_addextentr: AlBlk: [0x%x, 0x%x, 0x%x]\n", - rabp->ab_freecnt, rabp->ab_busycnt, rabp->ab_flag)); - - while ((ralp->al_len) && (rabp->ab_freecnt > 0)) { - if (rabp->ab_flag & AB_NODES) { - /* - * This is level containing AlNodes, so try to - * insert recursively into last entry. - */ - anp = AB_LASTANP(rabp); - dprintf(("hpfs_addextentr: AlNode: [0x%x,0x%x] \n", - anp->an_nextoff,anp->an_lsn)); - - /* - * Try to insert... - */ - error = hpfs_addextentr (hpmp, anp->an_lsn, ralp, ranp, &pf); - if (error) { - printf("hpfs_addextentr: FAILED %d\n",error); - goto fail; - } - - switch (pf) { - case AE_SPLIT: - dprintf(("hpfs_addextentr: successful (split)\n")); - /* - * Then hpfs_addextentr has split tree below, now - * we need to fix this level. Particulary: - * fix last AlNode and add another one. - */ - bcopy(ranp, AB_LASTANP(rabp), sizeof(alnode_t) * 2); - AB_ADDAN(rabp); - wb = 1; - break; - - default: - case AE_DONE: - dprintf(("hpfs_addextentr: successful\n")); - break; - } - } else { - alp = AB_LASTALP(rabp); - dprintf(("hpfs_addextentr: AlLeaf: [0x%x,0x%x,0x%x] \n", - alp->al_off,alp->al_len,alp->al_lsn)); - - /* Check if we trying to add in right place */ - if (alp->al_off + alp->al_len == ralp->al_off) { - lsn_t nlsn; - u_long nlen; - /* - * Search bitmap for block begining from - * alp->al_lsn + alp->al_len and long of ralp->al_len - */ - error = hpfs_bmlookup (hpmp, 0, - alp->al_lsn + alp->al_len, ralp->al_len, &nlsn, &nlen); - if (error) - goto fail; - - error = hpfs_bmmarkbusy(hpmp, nlsn, nlen); - if (error) - goto fail; - - dprintf(("hpfs_addextentr: new: 0x%x 0x%lx, ", nlsn, nlen)); - - /* - * If ending of existed entry fits the - * begining of the extent being added, - * then we add concatenate two extents. - */ - if (alp->al_lsn + alp->al_len == nlsn) { - dprintf(("concat\n")); - alp->al_len += nlen; - } else { - dprintf(("created new leaf\n")); - AL_SET(AB_FREEALP(rabp), ralp->al_off, nlen, nlsn); - AB_ADDAL(rabp); - } - - ralp->al_len -= nlen; - ralp->al_off += nlen; - } else { - printf("hpfs_addextentr: INTERNAL INCONSISTENCE\n"); - error = (EINVAL); - goto fail; - } - } - } - - /* - * Split AlBlk if overflowed. - */ - if (rabp->ab_freecnt <= 0) { - struct buf *nbp; - alsec_t * nrasp; - - dprintf(("hpfs_addextentr: overflow, split\n")); - - error = hpfs_splitalsec (hpmp, rasp, &nrasp, &nbp); - if (error) { - printf("hpfs_addextent: CAN'T SPLIT\n"); - goto fail; - } - - if (rabp->ab_flag & AB_NODES) { - int i; - alsec_t * asp; - alnode_t * anp; - struct buf * bp; - - ranp[0].an_nextoff = - AB_LASTANP(&rasp->as_ab)->an_nextoff; - - /* We need to set left subtree's last entry - * offset to 0xFFFFFFFF for OS/2 to be able - * to read our files. It treats absence of - * 0xFFFFFFFF as error. - */ - AB_LASTANP(&rasp->as_ab)->an_nextoff = ~0; - - /* We need to fix new allocated AlSec's - * children, becouse their parent has changed. - */ - anp = AB_ALNODE(&nrasp->as_ab); - for (i=0; i<nrasp->as_ab.ab_busycnt; i++) { - error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp); - if (error) { - brelse(nbp); - goto fail; - } - - asp = (alsec_t *)bp->b_data; - asp->as_parent = nrasp->as_self; - - bdwrite(bp); - anp ++; - } - } else { - ranp[0].an_nextoff = - AB_ALLEAF(&nrasp->as_ab)->al_off; - } - - ranp[0].an_lsn = rasp->as_self; - ranp[1].an_nextoff = ~0; - ranp[1].an_lsn = nrasp->as_self; - - bdwrite(nbp); - - *resp = AE_SPLIT; - wb = 1; - } - - if (wb) - bdwrite (rbp); - else - brelse(rbp); - - return (0); - -fail: - brelse(rbp); - - return (error); -} - -/* - * Recursive routine walking down the b-tree and deallocating all - * extents above bn. Returns *resp != 0 if alblk was totally - * deallocated and may be freed. Tries to keep b-tree. - * - * (XXXX) NOTE! THIS ROUTINE WILL NEVER DECREMENT DEPTH OF - * THE TREE. - */ -int -hpfs_truncatealblk ( - struct hpfsmount *hpmp, - alblk_t *abp, - lsn_t bn, - int *resp) -{ - int error; - alleaf_t *alp; - alnode_t *anp; - alsec_t *asp; - struct buf *bp; - - dprintf(("hpfs_truncatealblk: AlBlk: [0x%x,0x%x, 0x%x]\n", - abp->ab_freecnt, abp->ab_busycnt, abp->ab_flag)); - - if (abp->ab_flag & AB_NODES) { - /* - * Scan array of AlNodes backward, - * diving in recursion if needed - */ - anp = AB_LASTANP(abp); - - while (abp->ab_busycnt && (bn <= anp->an_nextoff)) { - dprintf(("hpfs_truncatealblk: AlNode: [0x%x,0x%x] \n", - anp->an_nextoff,anp->an_lsn)); - - error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp); - if (error) - return (error); - - asp = (alsec_t *)bp->b_data; - - error = hpfs_truncatealblk (hpmp, - &asp->as_ab, bn, resp); - if (error) { - brelse(bp); - return (error); - } - - if (*resp) { - brelse (bp); - - error = hpfs_bmmarkfree(hpmp, - anp->an_lsn, 1); - if (error) - return (error); - - AB_RMAN(abp); - anp --; - } else { - /* - * We have deallocated some entries, some space - * migth been freed, then try to concat two - * last AlSec. - */ - anp->an_nextoff = ~0; - if (abp->ab_busycnt >= 2) { - alsec_t *as0p; - struct buf *b0p; - - error = hpfs_breadalsec(hpmp, - (anp-1)->an_lsn, &b0p); - if (error) - return (error); - - as0p = (alsec_t *)b0p->b_data; - error = hpfs_concatalsec(hpmp, - as0p, asp, anp - 1); - if (error == ENOSPC) { - /* Not enought space */ - brelse (b0p); - bdwrite (bp); - } else if (error == 0) { - /* All OK */ - (anp-1)->an_nextoff = anp->an_nextoff; - - bdwrite (b0p); - brelse (bp); - - error = hpfs_bmmarkfree(hpmp, - anp->an_lsn, 1); - if (error) - return (error); - - AB_RMAN(abp); - } else { - /* True error */ - brelse (b0p); - brelse (bp); - return (error); - } - } else { - /* Nowhere to concatenate */ - bdwrite (bp); - } - - /* There can not be any more entries - * over greater bn, becouse last AlSec - * wasn't freed totally. So go out. - */ - break; - } - } - - if (abp->ab_busycnt == 0) - *resp = 1; - else - *resp = 0; - } else { - /* - * Scan array of AlLeafs backward, - * free all above bn. - */ - alp = AB_LASTALP(abp); - - while (abp->ab_busycnt && (bn < alp->al_off + alp->al_len)){ - dprintf(("hpfs_truncatealblk: AlLeaf: [0x%x,0x%x,0x%x] \n", - alp->al_off,alp->al_len,alp->al_lsn)); - - if (bn <= alp->al_off) { - error = hpfs_bmmarkfree(hpmp, alp->al_lsn, - alp->al_len); - if (error) - return (error); - - AB_RMAL(abp); - alp --; - } else if ((bn > alp->al_off) && - (bn < alp->al_off + alp->al_len)){ - error = hpfs_bmmarkfree(hpmp, - alp->al_lsn + bn - alp->al_off, - alp->al_len - bn + alp->al_off); - if (error) - return (error); - - alp->al_len = bn - alp->al_off; - - break; - } else - break; - } - } - - /* Signal parent deallocation, if need */ - if (abp->ab_busycnt == 0) - *resp = 1; - else - *resp = 0; - - return (0); -} diff --git a/sys/fs/hpfs/hpfs_ioctl.h b/sys/fs/hpfs/hpfs_ioctl.h deleted file mode 100644 index 7f60729..0000000 --- a/sys/fs/hpfs/hpfs_ioctl.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#ifndef _HPFS_IOCTL_H_ -#define _HPFS_IOCTL_H_ -#include <sys/ioccom.h> - -struct hpfs_rdea { - u_long ea_no; - u_long ea_sz; - void * ea_data; -}; - -#define HPFSIOCGEANUM _IOR('H', 0, u_long) /* Get EA number */ -#define HPFSIOCGEASZ _IOWR('H', 1, u_long) /* Get EA size */ -#define HPFSIOCRDEA _IOWR('H', 2, struct hpfs_rdea) /* Read EA */ - -#endif diff --git a/sys/fs/hpfs/hpfs_lookup.c b/sys/fs/hpfs/hpfs_lookup.c deleted file mode 100644 index 88542cb..0000000 --- a/sys/fs/hpfs/hpfs_lookup.c +++ /dev/null @@ -1,213 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/malloc.h> -#include <sys/bio.h> -#include <sys/buf.h> - -#include <fs/hpfs/hpfs.h> -#include <fs/hpfs/hpfsmount.h> -#include <fs/hpfs/hpfs_subr.h> - -int hpfs_removedirent (struct hpfsmount *, lsn_t, char *, int, int *); - -/* - * This routine traverse the b+ tree representing directory - * looking for file named 'name'. Returns buf struct and hpfsdirent - * pointer. Calling routine is supposed to brelse buffer. - * name is supposed in Unix encodeing. - */ -int -hpfs_genlookupbyname ( - struct hpfsnode *dhp, - char *name, - int namelen, - struct buf **bpp, - struct hpfsdirent **depp) -{ - struct hpfsmount *hpmp = dhp->h_hpmp; - struct buf *bp; - struct dirblk *dp; - struct hpfsdirent *dep; - lsn_t lsn; - int error, res; - - dprintf(("hpfs_genlookupbyname(0x%x, %s (%d)): \n", - dhp->h_no, name, namelen)); - - lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn; -dive: - error = hpfs_breaddirblk (hpmp, lsn, &bp); - if (error) - return (error); - - dp = (struct dirblk *) bp->b_data; - dep = D_DIRENT(dp); - - while(!(dep->de_flag & DE_END)) { - dprintf(("no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x\n", - dep->de_fnode, dep->de_size, dep->de_namelen, - dep->de_namelen, dep->de_name, dep->de_flag)); - - res = hpfs_cmpfname(hpmp, name, namelen, - dep->de_name, dep->de_namelen, dep->de_cpid); - if (res == 0) { - *bpp = bp; - *depp = dep; - return (0); - } else if (res < 0) - break; - - dep = (hpfsdirent_t *)(((caddr_t)dep) + dep->de_reclen); - } - - if (dep->de_flag & DE_DOWN) { - lsn = DE_DOWNLSN(dep); - brelse(bp); - goto dive; - } - - brelse(bp); - - return (ENOENT); -} - -int -hpfs_makefnode ( - struct vnode * dvp, - struct vnode ** vpp, - struct componentname *cnp, - struct vattr *vap) -{ -#ifdef HPFS_DEBUG - register struct hpfsnode *dhp = VTOHP(dvp); - dprintf(("hpfs_makefnode(0x%x, %s, %ld): \n", - dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen)); -#endif - - return (EOPNOTSUPP); -} - -int -hpfs_removedirent ( - struct hpfsmount *hpmp, - lsn_t lsn, - char *name, - int namelen, - int *retp) -{ -#if 0 - struct buf *bp; - dirblk_t *dbp; - struct hpfsdirent *dep; - int deoff; - int error, ret; - - dprintf(("hpfs_removedirent(0x%x, %.*s, %d): \n", - lsn, namelen, name, namelen)); - - error = hpfs_breaddirblk (hpmp, lsn, &bp); - if (error) - return (error); - - dbp = (dirblk_t *) bp->b_data; - deoff = sizeof(dirblk_t); - dep = DB_DIRENT(dbp); - - while(!(dep->de_flag & DE_END)) { - dprintf(("no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x\n", - dep->de_fnode, dep->de_size, dep->de_namelen, - dep->de_namelen, dep->de_name, dep->de_flag)); - - res = hpfs_cmpfname(hpmp, name, namelen, - dep->de_name, dep->de_namelen, dep->de_cpid); - if (res == 0) { - if (dep->de_flag & DE_DOWN) { - /*XXXXXX*/ - } else { - /* XXX we can copy less */ - bcopy (DE_NEXTDE(dep), dep, DB_BSIZE - deoff - dep->de_reclen); - dbp->d_freeoff -= dep->de_reclen; - *retp = 0; - } - bdwrite (bp); - return (0); - } else if (res < 0) - break; - - deoff += dep->de_reclen; - dep = DB_NEXTDE(dep); - } - - if (dep->de_flag & DE_DOWN) { - error = hpfs_removede (hpmp, DE_DOWNLSN(dep), name, namelen, &ret); - if (error) { - brelse (bp); - return (error); - } - if (ret == 0) { - if (deoff > sizeof (dirblk_t)) { - } else if (deoff + dep->de_reclen < dbp->db_freeoff) { - } - } - } else { - error = ENOENT; - } - - brelse (bp); - return (error); -#endif - return (EOPNOTSUPP); -} - -int -hpfs_removefnode ( - struct vnode * dvp, - struct vnode * vp, - struct componentname *cnp) -{ -#ifdef HPFS_DEBUG - register struct hpfsnode *dhp = VTOHP(dvp); - register struct hpfsnode *hp = VTOHP(vp); - dprintf(("hpfs_removefnode(0x%x, 0x%x, %s, %ld): \n", - dhp->h_no, hp->h_no, cnp->cn_nameptr, cnp->cn_namelen)); -#endif - - - return (EOPNOTSUPP); -} diff --git a/sys/fs/hpfs/hpfs_subr.c b/sys/fs/hpfs/hpfs_subr.c deleted file mode 100644 index c7fe94f..0000000 --- a/sys/fs/hpfs/hpfs_subr.c +++ /dev/null @@ -1,869 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/malloc.h> -#include <sys/bio.h> -#include <sys/buf.h> - -#include <fs/hpfs/hpfs.h> -#include <fs/hpfs/hpfsmount.h> -#include <fs/hpfs/hpfs_subr.h> - -u_long -hpfs_checksum( - u_int8_t *object, - int size) -{ - register int i; - u_long csum=0L; - for (i=0; i < size; i++) { - csum += (u_long) *object++; - csum = (csum << 7) + (csum >> (25)); - } - return (csum); -} - -void -hpfs_bmdeinit( - struct hpfsmount *hpmp) -{ - struct buf *bp; - int i; - - dprintf(("hpmp_bmdeinit: ")); - - if (!(hpmp->hpm_mp->mnt_flag & MNT_RDONLY)) { - /* - * Write down BitMap. - */ - for (i=0; i<hpmp->hpm_dbnum; i++) { - dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i])); - - bp = getblk(hpmp->hpm_devvp, hpmp->hpm_bmind[i], - BMSIZE, 0, 0, 0); - clrbuf(bp); - - bcopy(hpmp->hpm_bitmap + BMSIZE * i, bp->b_data, - BMSIZE); - - bwrite(bp); - } - } - - free(hpmp->hpm_bitmap,M_HPFSMNT); - free(hpmp->hpm_bmind,M_HPFSMNT); - - dprintf(("\n")); -} - -/* - * Initialize BitMap management, includes calculation of - * available blocks number. - */ -int -hpfs_bminit( - struct hpfsmount *hpmp) -{ - struct buf *bp; - int error, i, k; - u_long dbavail; - - dprintf(("hpfs_bminit: ")); - - hpmp->hpm_dbnum = (hpmp->hpm_su.su_btotal + 0x3FFF) / 0x4000; - - dprintf(("0x%lx data bands, ", hpmp->hpm_dbnum)); - - hpmp->hpm_bmind = malloc(hpmp->hpm_dbnum * sizeof(lsn_t), - M_HPFSMNT, M_WAITOK); - - hpmp->hpm_bitmap = malloc(hpmp->hpm_dbnum * BMSIZE, - M_HPFSMNT, M_WAITOK); - - error = bread(hpmp->hpm_devvp, hpmp->hpm_su.su_bitmap.lsn1, - ((hpmp->hpm_dbnum + 0x7F) & ~(0x7F)) << 2, NOCRED, &bp); - if (error) { - brelse(bp); - free(hpmp->hpm_bitmap, M_HPFSMNT); - free(hpmp->hpm_bmind, M_HPFSMNT); - dprintf((" error %d\n", error)); - return (error); - } - bcopy(bp->b_data, hpmp->hpm_bmind, hpmp->hpm_dbnum * sizeof(lsn_t)); - - brelse(bp); - - /* - * Read in all BitMap - */ - for (i=0; i<hpmp->hpm_dbnum; i++) { - dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i])); - - error = bread(hpmp->hpm_devvp, hpmp->hpm_bmind[i], - BMSIZE, NOCRED, &bp); - if (error) { - brelse(bp); - free(hpmp->hpm_bitmap, M_HPFSMNT); - free(hpmp->hpm_bmind, M_HPFSMNT); - dprintf((" error %d\n", error)); - return (error); - } - bcopy(bp->b_data, hpmp->hpm_bitmap + BMSIZE * i, BMSIZE); - - brelse(bp); - } - - /* - * Look througth BitMap and count free bits - */ - dbavail = 0; - for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++) { - register u_int32_t mask; - for (k=0, mask=1; k < 32; k++, mask<<=1) - if(((u_int32_t *)hpmp->hpm_bitmap)[i] & mask) - dbavail ++; - - } - hpmp->hpm_bavail = dbavail; - - return (0); -} - -int -hpfs_cmpfname ( - struct hpfsmount *hpmp, - char * uname, - int ulen, - char * dname, - int dlen, - u_int16_t cp) -{ - register int i, res; - - for (i = 0; i < ulen && i < dlen; i++) { - res = hpfs_toupper(hpmp, hpfs_u2d(hpmp, uname[i]), cp) - - hpfs_toupper(hpmp, dname[i], cp); - if (res) - return res; - } - return (ulen - dlen); -} - -int -hpfs_cpstrnnicmp ( - struct hpfsmount *hpmp, - char * str1, - int str1len, - u_int16_t str1cp, - char * str2, - int str2len, - u_int16_t str2cp) -{ - int i, res; - - for (i = 0; i < str1len && i < str2len; i++) { - res = (int)hpfs_toupper(hpmp, ((u_char *)str1)[i], str1cp) - - (int)hpfs_toupper(hpmp, ((u_char *)str2)[i], str2cp); - if (res) - return res; - } - return (str1len - str2len); -} - - -int -hpfs_cpload ( - struct hpfsmount *hpmp, - struct cpiblk *cpibp, - struct cpdblk *cpdbp) -{ - struct buf *bp; - struct cpdsec * cpdsp; - int error, i; - - error = bread(hpmp->hpm_devvp, cpibp->b_cpdsec, DEV_BSIZE, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - - cpdsp = (struct cpdsec *)bp->b_data; - - for (i=cpdsp->d_cpfirst; i<cpdsp->d_cpcnt; i++) { - if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) { - bcopy(cpdsp->d_cpdblk + i, cpdbp, - sizeof(struct cpdblk)); - - brelse(bp); - - return (0); - } - } - - brelse(bp); - - return (ENOENT); -} - - -/* - * Initialize Code Page information management. - * Load all copdepages in memory. - */ -int -hpfs_cpinit ( - struct mount *mp, - struct hpfsmount *hpmp) -{ - struct buf *bp; - int error, i; - lsn_t lsn; - int cpicnt; - struct cpisec * cpisp; - struct cpiblk * cpibp; - struct cpdblk * cpdbp; - - dprintf(("hpfs_cpinit: \n")); - - error = vfs_copyopt(mp->mnt_optnew, "d2u", hpmp->hpm_d2u, - sizeof hpmp->hpm_d2u); - if (error == ENOENT) - for (i=0x0; i<0x80;i++) - hpmp->hpm_d2u[i] = i + 0x80; - else if (error) - return (error); - - error = vfs_copyopt(mp->mnt_optnew, "u2d", hpmp->hpm_u2d, - sizeof hpmp->hpm_u2d); - if (error == ENOENT) - for (i=0x0; i<0x80;i++) - hpmp->hpm_u2d[i] = i + 0x80; - else if (error) - return (error); - - cpicnt = hpmp->hpm_sp.sp_cpinum; - - hpmp->hpm_cpdblk = malloc(cpicnt * sizeof(struct cpdblk), - M_HPFSMNT, M_WAITOK); - - cpdbp = hpmp->hpm_cpdblk; - lsn = hpmp->hpm_sp.sp_cpi; - - while (cpicnt > 0) { - error = bread(hpmp->hpm_devvp, lsn, DEV_BSIZE, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - - cpisp = (struct cpisec *)bp->b_data; - - cpibp = cpisp->s_cpi; - for (i=0; i<cpisp->s_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) { - dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n", - cpibp->b_country, cpibp->b_cpid, - cpibp->b_vcpid)); - - error = hpfs_cpload(hpmp, cpibp, cpdbp); - if (error) { - brelse(bp); - return (error); - } - } - lsn = cpisp->s_next; - brelse(bp); - } - - return (0); -} - -int -hpfs_cpdeinit ( - struct hpfsmount *hpmp) -{ - dprintf(("hpmp_cpdeinit: ")); - free(hpmp->hpm_cpdblk,M_HPFSMNT); - return (0); -} - -/* - * Lookup for a run of blocks. - */ -int -hpfs_bmlookup ( - struct hpfsmount *hpmp, - u_long flags, /* 1 means we want right len blocks in run, not less */ - lsn_t lsn, /* We want near this one */ - u_long len, /* We want such long */ - lsn_t *lsnp, /* We got here */ - u_long *lenp) /* We got this long */ -{ - u_int32_t * bitmap; - register u_int32_t mask; - int i,k; - int cband, vcband; - u_int bandsz; - int count; - - dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len)); - - if (lsn > hpmp->hpm_su.su_btotal) { - printf("hpfs_bmlookup: OUT OF VOLUME\n"); - return ENOSPC; - } - if (len > hpmp->hpm_bavail) { - printf("hpfs_bmlookup: OUT OF SPACE\n"); - return ENOSPC; - } - i = lsn >> 5; - k = lsn & 0x1F; - mask = 1 << k; - bitmap = (u_int32_t *)hpmp->hpm_bitmap + i; - - if (*bitmap & mask) { - *lsnp = lsn; - *lenp = 0; - for (; k < 32; k++, mask<<=1) { - if (*bitmap & mask) - (*lenp) ++; - else { - if (flags & 1) - goto step2; - else - return (0); - } - - if (*lenp == len) - return (0); - } - - bitmap++; - i++; - for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) { - for (k=0, mask=1; k < 32; k++, mask<<=1) { - if (*bitmap & mask) - (*lenp) ++; - else { - if (flags & 1) - goto step2; - else - return (0); - } - - if (*lenp == len) - return (0); - } - } - return (0); - } - -step2: - /* - * Lookup all bands begining from cband, lookup for first block - */ - cband = (lsn >> 14); - dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n", - cband, hpmp->hpm_dbnum)); - for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) { - cband = cband % hpmp->hpm_dbnum; - bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000); - dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz)); - - bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9); - *lsnp = cband << 14; - *lenp = 0; - count = 0; - for (i=0; i < bandsz >> 5; i++, bitmap++) { - for (k=0, mask=1; k < 32; k++, mask<<=1) { - if (*bitmap & mask) { - if (count) { - (*lenp) ++; - } else { - count = 1; - *lsnp = (cband << 14) + (i << 5) + k; - *lenp = 1; - } - } else { - if ((*lenp) && !(flags & 1)) { - return (0); - } else { - count = 0; - } - } - - if (*lenp == len) - return (0); - } - } - if (cband == hpmp->hpm_dbnum - 1) { - if ((*lenp) && !(flags & 1)) { - return (0); - } else { - count = 0; - } - } - } - - return (ENOSPC); -} - -/* - * Lookup a single free block. XXX Need locking on BitMap operations - * VERY STUPID ROUTINE!!! - */ -int -hpfs_bmfblookup ( - struct hpfsmount *hpmp, - lsn_t *lp) -{ - u_int32_t * bitmap; - int i,k; - - dprintf(("hpfs_bmfblookup: ")); - - bitmap = (u_int32_t *)hpmp->hpm_bitmap; - for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) { - k = ffs(*bitmap); - if (k) { - *lp = (i << 5) + k - 1; - dprintf((" found: 0x%x\n",*lp)); - return (0); - } - } - - return (ENOSPC); -} - -/* - * Mark contignous block of blocks. - */ -int -hpfs_bmmark ( - struct hpfsmount *hpmp, - lsn_t bn, - u_long bl, - int state) -{ - u_int32_t * bitmap; - int i, didprint = 0; - - dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state)); - - if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) { - printf("hpfs_bmmark: MARKING OUT OF VOLUME\n"); - return 0; - } - bitmap = (u_int32_t *)hpmp->hpm_bitmap; - bitmap += bn >> 5; - - while (bl > 0) { - for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) { - if (state) { - if ( *bitmap & (1 << i)) { - if (!didprint) { - printf("hpfs_bmmark: ALREADY FREE\n"); - didprint = 1; - } - } else - hpmp->hpm_bavail++; - - *bitmap |= (1 << i); - } else { - if ((~(*bitmap)) & (1 << i)) { - if (!didprint) { - printf("hpfs_bmmark: ALREADY BUSY\n"); - didprint = 1; - } - } else - hpmp->hpm_bavail--; - - *bitmap &= ~(1 << i); - } - } - bn = 0; - bitmap++; - } - - return (0); -} - - -int -hpfs_validateparent ( - struct hpfsnode *hp) -{ - struct hpfsnode *dhp; - struct vnode *dvp; - struct hpfsmount *hpmp = hp->h_hpmp; - struct buf *bp; - struct dirblk *dp; - struct hpfsdirent *dep; - lsn_t lsn, olsn; - int level, error; - - dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ", - hp->h_no, hp->h_fn.fn_parent)); - - if (hp->h_no == hp->h_fn.fn_parent) { - dhp = hp; - } else { - error = VFS_VGET(hpmp->hpm_mp, hp->h_fn.fn_parent, - LK_EXCLUSIVE, &dvp); - if (error) - return (error); - dhp = VTOHP(dvp); - } - - lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn; - - olsn = 0; - level = 1; - bp = NULL; - -dive: - dprintf(("[dive 0x%x] ", lsn)); - if (bp != NULL) - brelse(bp); - error = bread(dhp->h_devvp, lsn, D_BSIZE, NOCRED, &bp); - if (error) - goto failed; - - dp = (struct dirblk *) bp->b_data; - if (dp->d_magic != D_MAGIC) { - printf("hpfs_validatetimes: magic doesn't match\n"); - error = EINVAL; - goto failed; - } - - dep = D_DIRENT(dp); - - if (olsn) { - dprintf(("[restore 0x%x] ", olsn)); - - while(!(dep->de_flag & DE_END) ) { - if((dep->de_flag & DE_DOWN) && - (olsn == DE_DOWNLSN(dep))) - break; - dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); - } - - if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) { - if (dep->de_flag & DE_END) - goto blockdone; - - if (hp->h_no == dep->de_fnode) { - dprintf(("[found] ")); - goto readdone; - } - - dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); - } else { - printf("hpfs_validatetimes: ERROR! oLSN not found\n"); - error = EINVAL; - goto failed; - } - } - - olsn = 0; - - while(!(dep->de_flag & DE_END)) { - if(dep->de_flag & DE_DOWN) { - lsn = DE_DOWNLSN(dep); - level++; - goto dive; - } - - if (hp->h_no == dep->de_fnode) { - dprintf(("[found] ")); - goto readdone; - } - - dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); - } - - if(dep->de_flag & DE_DOWN) { - dprintf(("[enddive] ")); - lsn = DE_DOWNLSN(dep); - level++; - goto dive; - } - -blockdone: - dprintf(("[EOB] ")); - olsn = lsn; - lsn = dp->d_parent; - level--; - dprintf(("[level %d] ", level)); - if (level > 0) - goto dive; /* undive really */ - - goto failed; - -readdone: - bcopy(dep->de_name,hp->h_name,dep->de_namelen); - hp->h_name[dep->de_namelen] = '\0'; - hp->h_namelen = dep->de_namelen; - hp->h_ctime = dep->de_ctime; - hp->h_atime = dep->de_atime; - hp->h_mtime = dep->de_mtime; - hp->h_flag |= H_PARVALID; - - dprintf(("[readdone]")); - -failed: - dprintf(("\n")); - if (bp != NULL) - brelse(bp); - if (hp != dhp) - vput(dvp); - - return (error); -} - -struct timespec -hpfstimetounix ( - u_long hptime) -{ - struct timespec t; - - t.tv_nsec = 0; - t.tv_sec = hptime; - - return t; -} - -/* - * Write down changes done to parent dir, these are only times for now. - * hpfsnode have to be locked. - */ -int -hpfs_updateparent ( - struct hpfsnode *hp) -{ - struct hpfsnode *dhp; - struct vnode *dvp; - struct hpfsdirent *dep; - struct buf * bp; - int error; - - dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no)); - - if (!(hp->h_flag & H_PARCHANGE)) - return (0); - - if (!(hp->h_flag & H_PARVALID)) { - error = hpfs_validateparent (hp); - if (error) - return (error); - } - - if (hp->h_no == hp->h_fn.fn_parent) { - dhp = hp; - } else { - error = VFS_VGET(hp->h_hpmp->hpm_mp, hp->h_fn.fn_parent, - LK_EXCLUSIVE, &dvp); - if (error) - return (error); - dhp = VTOHP(dvp); - } - - error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen, - &bp, &dep); - if (error) { - goto failed; - } - - dep->de_atime = hp->h_atime; - dep->de_mtime = hp->h_mtime; - dep->de_size = hp->h_fn.fn_size; - - bdwrite (bp); - - hp->h_flag &= ~H_PARCHANGE; - - error = 0; -failed: - if (hp != dhp) - vput(dvp); - - return (0); -} - -/* - * Write down on disk changes done to fnode. hpfsnode have to be locked. - */ -int -hpfs_update ( - struct hpfsnode *hp) -{ - struct buf * bp; - - dprintf(("hpfs_update(0x%x): \n", hp->h_no)); - - if (!(hp->h_flag & H_CHANGE)) - return (0); - - bp = getblk(hp->h_devvp, hp->h_no, FNODESIZE, 0, 0, 0); - clrbuf(bp); - - bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode)); - bdwrite (bp); - - hp->h_flag &= ~H_CHANGE; - - if (hp->h_flag & H_PARCHANGE) - return (hpfs_updateparent(hp)); - - return (0); -} - -/* - * Truncate file to specifed size. hpfsnode have to be locked. - */ -int -hpfs_truncate ( - struct hpfsnode *hp, - u_long size) -{ - struct hpfsmount *hpmp = hp->h_hpmp; - lsn_t newblen, oldblen; - int error, pf; - - dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ", - hp->h_no, hp->h_fn.fn_size, size)); - - newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT; - oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT; - - dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen)); - - error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf); - if (error) - return (error); - if (pf) { - hp->h_fn.fn_ab.ab_flag = 0; - hp->h_fn.fn_ab.ab_freecnt = 0x8; - hp->h_fn.fn_ab.ab_busycnt = 0x0; - hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t); - } - - hp->h_fn.fn_size = size; - - hp->h_flag |= (H_CHANGE | H_PARCHANGE); - - dprintf(("hpfs_truncate: successful\n")); - - return (0); -} - -/* - * Enlarge file to specifed size. hpfsnode have to be locked. - */ -int -hpfs_extend ( - struct hpfsnode *hp, - u_long size) -{ - struct hpfsmount *hpmp = hp->h_hpmp; - lsn_t newblen, oldblen; - int error; - - dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ", - hp->h_no, hp->h_fn.fn_size, size)); - - if (hpmp->hpm_bavail < 0x10) - return (ENOSPC); - - newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT; - oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT; - - dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen)); - - error = hpfs_addextent(hpmp, hp, newblen - oldblen); - if (error) { - printf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error); - return (error); - } - - hp->h_fn.fn_size = size; - - hp->h_flag |= (H_CHANGE | H_PARCHANGE); - - dprintf(("hpfs_extend: successful\n")); - - return (0); -} - -/* - * Read AlSec structure, and check if magic is valid. - * You don't need to brelse buf on error. - */ -int -hpfs_breadstruct ( - struct hpfsmount *hpmp, - lsn_t lsn, - u_int len, - u_int32_t magic, - struct buf **bpp) -{ - struct buf *bp; - u_int32_t *mp; - int error; - - dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn)); - - *bpp = NULL; - - error = bread(hpmp->hpm_devvp, lsn, len, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - mp = (u_int32_t *) bp->b_data; - if (*mp != magic) { - brelse(bp); - printf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n", - *mp, magic); - return (EINVAL); - } - - *bpp = bp; - - return (0); -} - diff --git a/sys/fs/hpfs/hpfs_subr.h b/sys/fs/hpfs/hpfs_subr.h deleted file mode 100644 index e8a24b4..0000000 --- a/sys/fs/hpfs/hpfs_subr.h +++ /dev/null @@ -1,89 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#define hpfs_bmmarkfree(hpmp, bn,bl) hpfs_bmmark(hpmp, bn, bl, 1) -#define hpfs_bmmarkbusy(hpmp, bn,bl) hpfs_bmmark(hpmp, bn, bl, 0) - -u_long hpfs_checksum (u_int8_t *, int); - -int hpfs_bminit (struct hpfsmount *); -void hpfs_bmdeinit (struct hpfsmount *); -int hpfs_bmfblookup (struct hpfsmount *, lsn_t *); -int hpfs_bmmark (struct hpfsmount *, lsn_t, u_long, int); -int hpfs_bmlookup (struct hpfsmount *, u_long, lsn_t, u_long, - lsn_t *, u_long *); - -struct hpfs_args; -int hpfs_cpinit (struct mount *, struct hpfsmount *); -int hpfs_cpdeinit (struct hpfsmount *); -int hpfs_cpload (struct hpfsmount *, struct cpiblk *, - struct cpdblk *); -int hpfs_cpstrnnicmp (struct hpfsmount *, char *, int, u_int16_t, - char *, int, u_int16_t); -int hpfs_cmpfname (struct hpfsmount *, char *, int, - char *, int, u_int16_t); - -/* XXX Need unsigned conversion? */ -#define hpfs_u2d(hpmp, c) ((((u_char)(c))&0x80)?(hpmp->hpm_u2d[((u_char)(c))&0x7F]):((u_char)(c))) -#define hpfs_d2u(hpmp, c) ((((u_char)(c))&0x80)?(hpmp->hpm_d2u[((u_char)(c))&0x7F]):((u_char)(c))) -#define hpfs_toupper(hpmp, c, cp) ((((u_char)(c))&0x80) ? ((u_char)((hpmp)->hpm_cpdblk[(cp)].b_upcase[((u_char)(c))&0x7F])) : ((((u_char)(c)) >= 'a' && ((u_char)(c)) <='z')?(((u_char)(c))-'a'+'A'):((u_char)(c)))) - - -int hpfs_truncate (struct hpfsnode *, u_long); -int hpfs_extend (struct hpfsnode *, u_long); - -int hpfs_updateparent (struct hpfsnode *); -int hpfs_update (struct hpfsnode *); - -int hpfs_validateparent (struct hpfsnode *); -struct timespec hpfstimetounix (u_long); -int hpfs_genlookupbyname (struct hpfsnode *, char *, int, - struct buf **, struct hpfsdirent **); - -int hpfs_makefnode (struct vnode *, struct vnode **, - struct componentname *, struct vattr *); -int hpfs_removefnode (struct vnode *, struct vnode *, - struct componentname *); - -int hpfs_breadstruct (struct hpfsmount *, lsn_t, u_int, u_int32_t, - struct buf **); -#define hpfs_breadalsec(hpmp, lsn, bpp) \ - hpfs_breadstruct(hpmp, lsn, DEV_BSIZE, AS_MAGIC, bpp) -#define hpfs_breaddirblk(hpmp, lsn, bpp) \ - hpfs_breadstruct(hpmp, lsn, D_BSIZE, D_MAGIC, bpp) - -#if 0 -#define hpfs_hplock(hp, p) \ - lockmgr(&(hp)->h_intlock, LK_EXCLUSIVE, (p)) -#define hpfs_hpunlock(hp, p) \ - lockmgr(&(hp)->h_intlock, LK_RELEASE, (p)) -#endif - -int hpfs_hpbmap (struct hpfsnode *, daddr_t, daddr_t *, int *); -int hpfs_truncatealblk (struct hpfsmount *, alblk_t *, lsn_t,int *); -int hpfs_addextent (struct hpfsmount *, struct hpfsnode *, u_long); diff --git a/sys/fs/hpfs/hpfs_vfsops.c b/sys/fs/hpfs/hpfs_vfsops.c deleted file mode 100644 index edc37b2..0000000 --- a/sys/fs/hpfs/hpfs_vfsops.c +++ /dev/null @@ -1,545 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/namei.h> -#include <sys/conf.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> - -#include <geom/geom.h> -#include <geom/geom_vfs.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/vm_page.h> -#include <vm/vm_object.h> -#include <vm/vm_extern.h> - -#include <fs/hpfs/hpfs.h> -#include <fs/hpfs/hpfsmount.h> -#include <fs/hpfs/hpfs_subr.h> - -MALLOC_DEFINE(M_HPFSMNT, "hpfs_mount", "HPFS mount structure"); -MALLOC_DEFINE(M_HPFSNO, "hpfs_node", "HPFS node structure"); - -struct sockaddr; - -static int hpfs_mountfs(register struct vnode *, struct mount *, - struct thread *); - -static vfs_fhtovp_t hpfs_fhtovp; -static vfs_vget_t hpfs_vget; -static vfs_cmount_t hpfs_cmount; -static vfs_mount_t hpfs_mount; -static vfs_root_t hpfs_root; -static vfs_statfs_t hpfs_statfs; -static vfs_unmount_t hpfs_unmount; - -static int -hpfs_cmount ( - struct mntarg *ma, - void *data, - uint64_t flags) -{ - struct hpfs_args args; - struct export_args exp; - int error; - - error = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args)); - if (error) - return (error); - vfs_oexport_conv(&args.export, &exp); - - ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); - ma = mount_arg(ma, "export", &exp, sizeof(exp)); - ma = mount_argf(ma, "uid", "%d", args.uid); - ma = mount_argf(ma, "gid", "%d", args.gid); - ma = mount_argf(ma, "mode", "%d", args.mode); - if (args.flags & HPFSMNT_TABLES) { - ma = mount_arg(ma, "d2u", args.d2u, sizeof args.d2u); - ma = mount_arg(ma, "u2d", args.u2d, sizeof args.u2d); - } - - error = kernel_mount(ma, flags); - - return (error); -} - -static const char *hpfs_opts[] = { - "from", "export", "uid", "gid", "mode", "d2u", "u2d", NULL -}; - -static int -hpfs_mount (struct mount *mp) -{ - int err = 0, error; - struct vnode *devvp; - struct thread *td; - struct nameidata ndp; - struct export_args export; - char *from; - - td = curthread; - dprintf(("hpfs_omount():\n")); - /* - *** - * Mounting non-root filesystem or updating a filesystem - *** - */ - if (vfs_filteropt(mp->mnt_optnew, hpfs_opts)) - return (EINVAL); - - from = vfs_getopts(mp->mnt_optnew, "from", &error); - if (error) - return (error); - - /* - * If updating, check whether changing from read-only to - * read/write; if there is no device name, that's all we do. - */ - if (mp->mnt_flag & MNT_UPDATE) { - dprintf(("hpfs_omount: MNT_UPDATE: ")); - - if (from == NULL) { - error = vfs_copyopt(mp->mnt_optnew, "export", - &export, sizeof export); - if (error) - return (error); - dprintf(("export 0x%x\n",args.export.ex_flags)); - err = vfs_export(mp, &export); - if (err) { - printf("hpfs_omount: vfs_export failed %d\n", - err); - } - goto success; - } else { - dprintf(("name [FAILED]\n")); - err = EINVAL; - goto success; - } - dprintf(("\n")); - } - - /* - * Not an update, or updating the name: look up the name - * and verify that it refers to a sensible block device. - */ - NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td); - err = namei(&ndp); - if (err) { - /* can't get devvp!*/ - goto error_1; - } - - devvp = ndp.ni_vp; - - if (!vn_isdisk(devvp, &err)) { - vput(devvp); - return (err); - } - - /* - ******************** - * NEW MOUNT - ******************** - */ - - /* - * Since this is a new mount, we want the names for - * the device and the mount point copied in. If an - * error occurs, the mountpoint is discarded by the - * upper level code. Note that vfs_omount() handles - * copying the mountpoint f_mntonname for us, so we - * don't have to do it here unless we want to set it - * to something other than "path" for some rason. - */ - /* Save "mounted from" info for mount point (NULL pad)*/ - vfs_mountedfrom(mp, from); - - err = hpfs_mountfs(devvp, mp, td); - if (err) { - vrele(devvp); - goto error_1; - } - - goto success; - -error_1: /* no state to back out*/ - /* XXX: Missing NDFREE(&ndp, ...) */ - -success: - return( err); -} - -/* - * Common code for mount and mountroot - */ -int -hpfs_mountfs(devvp, mp, td) - register struct vnode *devvp; - struct mount *mp; - struct thread *td; -{ - int error, ronly, v; - struct sublock *sup; - struct spblock *spp; - struct hpfsmount *hpmp; - struct buf *bp = NULL; - struct vnode *vp; - struct cdev *dev = devvp->v_rdev; - struct g_consumer *cp; - struct bufobj *bo; - - if (mp->mnt_flag & MNT_ROOTFS) - return (EOPNOTSUPP); - dprintf(("hpfs_mountfs():\n")); - ronly = (mp->mnt_flag & MNT_RDONLY) != 0; - /* XXX: use VOP_ACCESS to check FS perms */ - DROP_GIANT(); - g_topology_lock(); - error = g_vfs_open(devvp, &cp, "hpfs", ronly ? 0 : 1); - g_topology_unlock(); - PICKUP_GIANT(); - VOP_UNLOCK(devvp, 0); - if (error) - return (error); - - bo = &devvp->v_bufobj; - bo->bo_private = cp; - bo->bo_ops = g_vfs_bufops; - - /* - * Do actual mount - */ - hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK | M_ZERO); - - hpmp->hpm_cp = cp; - hpmp->hpm_bo = bo; - - /* Read in SuperBlock */ - error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp); - if (error) - goto failed; - bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock)); - brelse(bp); bp = NULL; - - /* Read in SpareBlock */ - error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp); - if (error) - goto failed; - bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock)); - brelse(bp); bp = NULL; - - sup = &hpmp->hpm_su; - spp = &hpmp->hpm_sp; - - /* Check magic */ - if (sup->su_magic != SU_MAGIC) { - printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n"); - error = EINVAL; - goto failed; - } - if (spp->sp_magic != SP_MAGIC) { - printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n"); - error = EINVAL; - goto failed; - } - - mp->mnt_data = hpmp; - hpmp->hpm_devvp = devvp; - hpmp->hpm_dev = devvp->v_rdev; - hpmp->hpm_mp = mp; - if (vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v) == 1) - hpmp->hpm_uid = v; - if (vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v) == 1) - hpmp->hpm_gid = v; - if (vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v) == 1) - hpmp->hpm_mode = v; - - error = hpfs_bminit(hpmp); - if (error) - goto failed; - - error = hpfs_cpinit(mp, hpmp); - if (error) { - hpfs_bmdeinit(hpmp); - goto failed; - } - - error = hpfs_root(mp, LK_EXCLUSIVE, &vp); - if (error) { - hpfs_cpdeinit(hpmp); - hpfs_bmdeinit(hpmp); - goto failed; - } - - vput(vp); - - mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev); - mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; - mp->mnt_maxsymlinklen = 0; - MNT_ILOCK(mp); - mp->mnt_flag |= MNT_LOCAL; - MNT_IUNLOCK(mp); - return (0); - -failed: - if (bp) - brelse (bp); - mp->mnt_data = NULL; - DROP_GIANT(); - g_topology_lock(); - g_vfs_close(cp); - g_topology_unlock(); - PICKUP_GIANT(); - return (error); -} - -static int -hpfs_unmount( - struct mount *mp, - int mntflags) -{ - int error, flags; - register struct hpfsmount *hpmp = VFSTOHPFS(mp); - - dprintf(("hpfs_unmount():\n")); - - flags = 0; - if(mntflags & MNT_FORCE) - flags |= FORCECLOSE; - - dprintf(("hpfs_unmount: vflushing...\n")); - - error = vflush(mp, 0, flags, curthread); - if (error) { - printf("hpfs_unmount: vflush failed: %d\n",error); - return (error); - } - - vinvalbuf(hpmp->hpm_devvp, V_SAVE, 0, 0); - DROP_GIANT(); - g_topology_lock(); - g_vfs_close(hpmp->hpm_cp); - g_topology_unlock(); - PICKUP_GIANT(); - vrele(hpmp->hpm_devvp); - - dprintf(("hpfs_umount: freeing memory...\n")); - hpfs_cpdeinit(hpmp); - hpfs_bmdeinit(hpmp); - mp->mnt_data = NULL; - MNT_ILOCK(mp); - mp->mnt_flag &= ~MNT_LOCAL; - MNT_IUNLOCK(mp); - free(hpmp, M_HPFSMNT); - - return (0); -} - -static int -hpfs_root( - struct mount *mp, - int flags, - struct vnode **vpp) -{ - int error = 0; - struct hpfsmount *hpmp = VFSTOHPFS(mp); - - dprintf(("hpfs_root():\n")); - error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, LK_EXCLUSIVE, vpp); - if(error) { - printf("hpfs_root: VFS_VGET failed: %d\n",error); - return (error); - } - - return (error); -} - -static int -hpfs_statfs( - struct mount *mp, - struct statfs *sbp) -{ - struct hpfsmount *hpmp = VFSTOHPFS(mp); - - dprintf(("hpfs_statfs(): HPFS%d.%d\n", - hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver)); - - sbp->f_type = mp->mnt_vfc->vfc_typenum; - sbp->f_bsize = DEV_BSIZE; - sbp->f_iosize = DEV_BSIZE; - sbp->f_blocks = hpmp->hpm_su.su_btotal; - sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail; - sbp->f_ffree = 0; - sbp->f_files = 0; - sbp->f_flags = mp->mnt_flag; - - return (0); -} - -/*ARGSUSED*/ -static int -hpfs_fhtovp( - struct mount *mp, - struct fid *fhp, - int flags, - struct vnode **vpp) -{ - struct vnode *nvp; - struct hpfid *hpfhp = (struct hpfid *)fhp; - int error; - - if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, LK_EXCLUSIVE, &nvp)) != 0) { - *vpp = NULLVP; - return (error); - } - /* XXX as unlink/rmdir/mkdir/creat are not currently possible - * with HPFS, we don't need to check anything else for now */ - *vpp = nvp; - - return (0); -} - -static int -hpfs_vget( - struct mount *mp, - ino_t ino, - int flags, - struct vnode **vpp) -{ - struct hpfsmount *hpmp = VFSTOHPFS(mp); - struct vnode *vp; - struct hpfsnode *hp; - struct buf *bp; - int error; - - dprintf(("hpfs_vget(0x%x): ",ino)); - - error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL); - if (error || *vpp != NULL) - return (error); - - *vpp = NULL; - hp = NULL; - vp = NULL; - - /* - * We have to lock node creation for a while, - * but then we have to call getnewvnode(), - * this may cause hpfs_reclaim() to be called, - * this may need to VOP_VGET() parent dir for - * update reasons, and if parent is not in - * hash, we have to lock node creation... - * To solve this, we MALLOC, getnewvnode and init while - * not locked (probability of node appearence - * at that time is little, and anyway - we'll - * check for it). - */ - hp = malloc(sizeof(struct hpfsnode), - M_HPFSNO, M_WAITOK); - - error = getnewvnode("hpfs", mp, &hpfs_vnodeops, &vp); - if (error) { - printf("hpfs_vget: can't get new vnode\n"); - free(hp, M_HPFSNO); - return (error); - } - - dprintf(("prenew ")); - - vp->v_data = hp; - - if (ino == (ino_t)hpmp->hpm_su.su_rootfno) - vp->v_vflag |= VV_ROOT; - - - mtx_init(&hp->h_interlock, "hpfsnode interlock", NULL, MTX_DEF); - - hp->h_flag = H_INVAL; - hp->h_vp = vp; - hp->h_hpmp = hpmp; - hp->h_no = ino; - hp->h_dev = hpmp->hpm_dev; - hp->h_uid = hpmp->hpm_uid; - hp->h_gid = hpmp->hpm_uid; - hp->h_mode = hpmp->hpm_mode; - hp->h_devvp = hpmp->hpm_devvp; - - lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL); - error = insmntque(vp, mp); - if (error != 0) { - free(hp, M_HPFSNO); - return (error); - } - error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL); - if (error || *vpp != NULL) - return (error); - - error = bread(hpmp->hpm_devvp, ino, FNODESIZE, NOCRED, &bp); - if (error) { - printf("hpfs_vget: can't read ino %ju\n", (uintmax_t)ino); - vput(vp); - return (error); - } - bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode)); - brelse(bp); - - if (hp->h_fn.fn_magic != FN_MAGIC) { - printf("hpfs_vget: MAGIC DOESN'T MATCH\n"); - vput(vp); - return (EINVAL); - } - - vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG; - hp->h_flag &= ~H_INVAL; - - *vpp = vp; - - return (0); -} - -static struct vfsops hpfs_vfsops = { - .vfs_fhtovp = hpfs_fhtovp, - .vfs_cmount = hpfs_cmount, - .vfs_mount = hpfs_mount, - .vfs_root = hpfs_root, - .vfs_statfs = hpfs_statfs, - .vfs_unmount = hpfs_unmount, - .vfs_vget = hpfs_vget, -}; -VFS_SET(hpfs_vfsops, hpfs, 0); diff --git a/sys/fs/hpfs/hpfs_vnops.c b/sys/fs/hpfs/hpfs_vnops.c deleted file mode 100644 index 9abe77c..0000000 --- a/sys/fs/hpfs/hpfs_vnops.c +++ /dev/null @@ -1,1264 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/conf.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/malloc.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/dirent.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/vm_page.h> -#include <vm/vm_object.h> -#include <vm/vm_pager.h> -#include <vm/vnode_pager.h> -#include <vm/vm_extern.h> - -#include <sys/unistd.h> /* for pathconf(2) constants */ - -#include <fs/hpfs/hpfs.h> -#include <fs/hpfs/hpfsmount.h> -#include <fs/hpfs/hpfs_subr.h> -#include <fs/hpfs/hpfs_ioctl.h> - -static int hpfs_de_uiomove(struct hpfsmount *, struct hpfsdirent *, - struct uio *); -static vop_ioctl_t hpfs_ioctl; -static vop_read_t hpfs_read; -static vop_write_t hpfs_write; -static vop_getattr_t hpfs_getattr; -static vop_setattr_t hpfs_setattr; -static vop_inactive_t hpfs_inactive; -static vop_print_t hpfs_print; -static vop_reclaim_t hpfs_reclaim; -static vop_strategy_t hpfs_strategy; -static vop_access_t hpfs_access; -static vop_open_t hpfs_open; -static vop_close_t hpfs_close; -static vop_readdir_t hpfs_readdir; -static vop_cachedlookup_t hpfs_lookup; -static vop_create_t hpfs_create; -static vop_remove_t hpfs_remove; -static vop_bmap_t hpfs_bmap; -static vop_fsync_t hpfs_fsync; -static vop_pathconf_t hpfs_pathconf; -static vop_vptofh_t hpfs_vptofh; - -static int -hpfs_fsync(ap) - struct vop_fsync_args /* { - struct vnode *a_vp; - struct ucred *a_cred; - int a_waitfor; - struct thread *a_td; - } */ *ap; -{ - /* - * Flush our dirty buffers. - */ - vop_stdfsync(ap); - - /* - * Write out the on-disc version of the vnode. - */ - return hpfs_update(VTOHP(ap->a_vp)); -} - -static int -hpfs_ioctl ( - struct vop_ioctl_args /* { - struct vnode *a_vp; - u_long a_command; - caddr_t a_data; - int a_fflag; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap) -{ - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - int error; - - printf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ", - hp->h_no, ap->a_command, ap->a_data, ap->a_fflag); - - switch (ap->a_command) { - case HPFSIOCGEANUM: { - u_long eanum; - u_long passed; - struct ea *eap; - - eanum = 0; - - if (hp->h_fn.fn_ealen > 0) { - eap = (struct ea *)&(hp->h_fn.fn_int); - passed = 0; - - while (passed < hp->h_fn.fn_ealen) { - - printf("EAname: %s\n", EA_NAME(eap)); - - eanum++; - passed += sizeof(struct ea) + - eap->ea_namelen + 1 + eap->ea_vallen; - eap = (struct ea *)((caddr_t)hp->h_fn.fn_int + - passed); - } - error = 0; - } else { - error = ENOENT; - } - - printf("%lu eas\n", eanum); - - *(u_long *)ap->a_data = eanum; - - break; - } - case HPFSIOCGEASZ: { - u_long eanum; - u_long passed; - struct ea *eap; - - printf("EA%ld\n", *(u_long *)ap->a_data); - - eanum = 0; - if (hp->h_fn.fn_ealen > 0) { - eap = (struct ea *)&(hp->h_fn.fn_int); - passed = 0; - - error = ENOENT; - while (passed < hp->h_fn.fn_ealen) { - printf("EAname: %s\n", EA_NAME(eap)); - - if (eanum == *(u_long *)ap->a_data) { - *(u_long *)ap->a_data = - eap->ea_namelen + 1 + - eap->ea_vallen; - - error = 0; - break; - } - - eanum++; - passed += sizeof(struct ea) + - eap->ea_namelen + 1 + eap->ea_vallen; - eap = (struct ea *)((caddr_t)hp->h_fn.fn_int + - passed); - } - } else { - error = ENOENT; - } - - break; - } - case HPFSIOCRDEA: { - u_long eanum; - u_long passed; - struct hpfs_rdea *rdeap; - struct ea *eap; - - rdeap = (struct hpfs_rdea *)ap->a_data; - printf("EA%ld\n", rdeap->ea_no); - - eanum = 0; - if (hp->h_fn.fn_ealen > 0) { - eap = (struct ea *)&(hp->h_fn.fn_int); - passed = 0; - - error = ENOENT; - while (passed < hp->h_fn.fn_ealen) { - printf("EAname: %s\n", EA_NAME(eap)); - - if (eanum == rdeap->ea_no) { - rdeap->ea_sz = eap->ea_namelen + 1 + - eap->ea_vallen; - copyout(EA_NAME(eap),rdeap->ea_data, - rdeap->ea_sz); - error = 0; - break; - } - - eanum++; - passed += sizeof(struct ea) + - eap->ea_namelen + 1 + eap->ea_vallen; - eap = (struct ea *)((caddr_t)hp->h_fn.fn_int + - passed); - } - } else { - error = ENOENT; - } - - break; - } - default: - error = ENOTTY; - break; - } - return (error); -} - -/* - * Map file offset to disk offset. - */ -int -hpfs_bmap(ap) - struct vop_bmap_args /* { - struct vnode *a_vp; - daddr_t a_bn; - struct bufobj **a_bop; - daddr_t *a_bnp; - int *a_runp; - int *a_runb; - } */ *ap; -{ - register struct hpfsnode *hp = VTOHP(ap->a_vp); - daddr_t blkno; - int error; - - if (ap->a_bop != NULL) - *ap->a_bop = &hp->h_devvp->v_bufobj; - if (ap->a_runb != NULL) - *ap->a_runb = 0; - if (ap->a_bnp == NULL) - return (0); - - dprintf(("hpfs_bmap(0x%x, 0x%x): ",hp->h_no, ap->a_bn)); - - error = hpfs_hpbmap (hp, ap->a_bn, &blkno, ap->a_runp); - *ap->a_bnp = blkno; - - return (error); -} - -static int -hpfs_read(ap) - struct vop_read_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - struct uio *uio = ap->a_uio; - struct buf *bp; - u_int xfersz, toread; - u_int off; - daddr_t lbn, bn; - int resid; - int runl; - int error = 0; - - resid = min (uio->uio_resid, hp->h_fn.fn_size - uio->uio_offset); - - dprintf(("hpfs_read(0x%x, off: %d resid: %d, segflg: %d): [resid: 0x%x]\n",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg, resid)); - - while (resid) { - lbn = uio->uio_offset >> DEV_BSHIFT; - off = uio->uio_offset & (DEV_BSIZE - 1); - dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n", - uio->uio_resid, lbn, off)); - error = hpfs_hpbmap(hp, lbn, &bn, &runl); - if (error) - return (error); - - toread = min(off + resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE)); - xfersz = (toread + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); - dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n", - bn, runl, toread, xfersz)); - - if (toread == 0) - break; - - error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp); - if (error) { - brelse(bp); - break; - } - - error = uiomove(bp->b_data + off, toread - off, uio); - if(error) { - brelse(bp); - break; - } - brelse(bp); - resid -= toread; - } - dprintf(("hpfs_read: successful\n")); - return (error); -} - -static int -hpfs_write(ap) - struct vop_write_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - struct uio *uio = ap->a_uio; - struct buf *bp; - u_int xfersz, towrite; - u_int off; - daddr_t lbn, bn; - int runl; - int error = 0; - - dprintf(("hpfs_write(0x%x, off: %d resid: %d, segflg: %d):\n",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg)); - - if (ap->a_ioflag & IO_APPEND) { - dprintf(("hpfs_write: APPEND mode\n")); - uio->uio_offset = hp->h_fn.fn_size; - } - if (uio->uio_offset + uio->uio_resid > hp->h_fn.fn_size) { - error = hpfs_extend (hp, uio->uio_offset + uio->uio_resid); - if (error) { - printf("hpfs_write: hpfs_extend FAILED %d\n", error); - return (error); - } - } - - while (uio->uio_resid) { - lbn = uio->uio_offset >> DEV_BSHIFT; - off = uio->uio_offset & (DEV_BSIZE - 1); - dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n", - uio->uio_resid, lbn, off)); - error = hpfs_hpbmap(hp, lbn, &bn, &runl); - if (error) - return (error); - - towrite = min(off + uio->uio_resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE)); - xfersz = (towrite + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); - dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n", - bn, runl, towrite, xfersz)); - - if ((off == 0) && (towrite == xfersz)) { - bp = getblk(hp->h_devvp, bn, xfersz, 0, 0, 0); - clrbuf(bp); - } else { - error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - } - - error = uiomove(bp->b_data + off, towrite - off, uio); - if(error) { - brelse(bp); - return (error); - } - - if (ap->a_ioflag & IO_SYNC) - bwrite(bp); - else - bawrite(bp); - } - - dprintf(("hpfs_write: successful\n")); - return (0); -} - -/* - * XXXXX do we need hpfsnode locking inside? - */ -static int -hpfs_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - register struct vattr *vap = ap->a_vap; - int error; - - dprintf(("hpfs_getattr(0x%x):\n", hp->h_no)); - - vap->va_fsid = dev2udev(hp->h_dev); - vap->va_fileid = hp->h_no; - vap->va_mode = hp->h_mode; - vap->va_nlink = 1; - vap->va_uid = hp->h_uid; - vap->va_gid = hp->h_gid; - vap->va_rdev = NODEV; - vap->va_size = hp->h_fn.fn_size; - vap->va_bytes = ((hp->h_fn.fn_size + DEV_BSIZE-1) & ~(DEV_BSIZE-1)) + - DEV_BSIZE; - - if (!(hp->h_flag & H_PARVALID)) { - error = hpfs_validateparent(hp); - if (error) - return (error); - } - vap->va_atime = hpfstimetounix(hp->h_atime); - vap->va_mtime = hpfstimetounix(hp->h_mtime); - vap->va_ctime = hpfstimetounix(hp->h_ctime); - - vap->va_flags = 0; - vap->va_gen = 0; - vap->va_blocksize = DEV_BSIZE; - vap->va_type = vp->v_type; - vap->va_filerev = 0; - - return (0); -} - -/* - * XXXXX do we need hpfsnode locking inside? - */ -static int -hpfs_setattr(ap) - struct vop_setattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct hpfsnode *hp = VTOHP(vp); - struct vattr *vap = ap->a_vap; - struct ucred *cred = ap->a_cred; - struct thread *td = curthread; - int error; - - dprintf(("hpfs_setattr(0x%x):\n", hp->h_no)); - - /* - * Check for unsettable attributes. - */ - if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || - (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || - (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || - (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { - dprintf(("hpfs_setattr: changing nonsettable attr\n")); - return (EINVAL); - } - - /* Can't change flags XXX Could be implemented */ - if (vap->va_flags != VNOVAL) { - printf("hpfs_setattr: FLAGS CANNOT BE SET\n"); - return (EINVAL); - } - - /* Can't change uid/gid XXX Could be implemented */ - if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { - printf("hpfs_setattr: UID/GID CANNOT BE SET\n"); - return (EINVAL); - } - - /* Can't change mode XXX Could be implemented */ - if (vap->va_mode != (mode_t)VNOVAL) { - printf("hpfs_setattr: MODE CANNOT BE SET\n"); - return (EINVAL); - } - - /* Update times */ - if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - if (vap->va_vaflags & VA_UTIMES_NULL) { - error = VOP_ACCESS(vp, VADMIN, cred, td); - if (error) - error = VOP_ACCESS(vp, VWRITE, cred, td); - } else - error = VOP_ACCESS(vp, VADMIN, cred, td); - if (vap->va_atime.tv_sec != VNOVAL) - hp->h_atime = vap->va_atime.tv_sec; - if (vap->va_mtime.tv_sec != VNOVAL) - hp->h_mtime = vap->va_mtime.tv_sec; - - hp->h_flag |= H_PARCHANGE; - } - - if (vap->va_size != VNOVAL) { - switch (vp->v_type) { - case VDIR: - return (EISDIR); - case VREG: - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - break; - default: - printf("hpfs_setattr: WRONG v_type\n"); - return (EINVAL); - } - - if (vap->va_size < hp->h_fn.fn_size) { - error = vtruncbuf(vp, cred, vap->va_size, DEV_BSIZE); - if (error) - return (error); - error = hpfs_truncate(hp, vap->va_size); - if (error) - return (error); - - } else if (vap->va_size > hp->h_fn.fn_size) { - vnode_pager_setsize(vp, vap->va_size); - error = hpfs_extend(hp, vap->va_size); - if (error) - return (error); - } - } - - return (0); -} - -/* - * Last reference to a node. If necessary, write or delete it. - */ -int -hpfs_inactive(ap) - struct vop_inactive_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - int error; - - dprintf(("hpfs_inactive(0x%x): \n", hp->h_no)); - - if (hp->h_flag & H_CHANGE) { - dprintf(("hpfs_inactive: node changed, update\n")); - error = hpfs_update (hp); - if (error) - return (error); - } - - if (hp->h_flag & H_PARCHANGE) { - dprintf(("hpfs_inactive: parent node changed, update\n")); - error = hpfs_updateparent (hp); - if (error) - return (error); - } - - if (hp->h_flag & H_INVAL) { - vrecycle(vp); - return (0); - } - - return (0); -} - -/* - * Reclaim an inode so that it can be used for other purposes. - */ -int -hpfs_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - - dprintf(("hpfs_reclaim(0x%x0): \n", hp->h_no)); - - /* - * Destroy the vm object and flush associated pages. - */ - vnode_destroy_vobject(vp); - - vfs_hash_remove(vp); - - mtx_destroy(&hp->h_interlock); - - vp->v_data = NULL; - - free(hp, M_HPFSNO); - - return (0); -} - -static int -hpfs_print(ap) - struct vop_print_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - - printf("\tino 0x%x\n", hp->h_no); - return (0); -} - -/* - * Calculate the logical to physical mapping if not done already, - * then call the device strategy routine. - * - * In order to be able to swap to a file, the hpfs_hpbmap operation may not - * deadlock on memory. See hpfs_bmap() for details. XXXXXXX (not impl) - */ -int -hpfs_strategy(ap) - struct vop_strategy_args /* { - struct buf *a_bp; - } */ *ap; -{ - register struct buf *bp = ap->a_bp; - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(ap->a_vp); - daddr_t blkno; - struct bufobj *bo; - int error; - - dprintf(("hpfs_strategy(): \n")); - - if (vp->v_type == VBLK || vp->v_type == VCHR) - panic("hpfs_strategy: spec"); - if (bp->b_blkno == bp->b_lblkno) { - error = hpfs_hpbmap (hp, bp->b_lblkno, &blkno, NULL); - bp->b_blkno = blkno; - if (error) { - printf("hpfs_strategy: hpfs_bpbmap FAILED %d\n", error); - bp->b_error = error; - bp->b_ioflags |= BIO_ERROR; - bufdone(bp); - return (0); - } - if ((long)bp->b_blkno == -1) - vfs_bio_clrbuf(bp); - } - if ((long)bp->b_blkno == -1) { - bufdone(bp); - return (0); - } - bp->b_iooffset = dbtob(bp->b_blkno); - bo = hp->h_hpmp->hpm_bo; - BO_STRATEGY(bo, bp); - return (0); -} - -/* - * XXXXX do we need hpfsnode locking inside? - */ -int -hpfs_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - accmode_t a_accmode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct hpfsnode *hp = VTOHP(vp); - accmode_t accmode = ap->a_accmode; - - dprintf(("hpfs_access(0x%x):\n", hp->h_no)); - - /* - * Disallow write attempts on read-only filesystems; - * unless the file is a socket, fifo, or a block or - * character device resident on the filesystem. - */ - if (accmode & VWRITE) { - switch ((int)vp->v_type) { - case VDIR: - case VLNK: - case VREG: - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - break; - } - } - - return (vaccess(vp->v_type, hp->h_mode, hp->h_uid, hp->h_gid, - ap->a_accmode, ap->a_cred, NULL)); -} - -/* - * Open called. - * - * Nothing to do. - */ -/* ARGSUSED */ -static int -hpfs_open(ap) - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ -#ifdef HPFS_DEBUG - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - - printf("hpfs_open(0x%x):\n",hp->h_no); -#endif - - /* - * Files marked append-only must be opened for appending. - */ - - return (0); -} - -/* - * Close called. - * - * Update the times on the inode. - */ -/* ARGSUSED */ -static int -hpfs_close(ap) - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ -#ifdef HPFS_DEBUG - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - - printf("hpfs_close: %d\n",hp->h_no); -#endif - - return (0); -} - -static int -hpfs_de_uiomove ( - struct hpfsmount *hpmp, - struct hpfsdirent *dep, - struct uio *uio) -{ - struct dirent cde; - int i, error; - - dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ", - dep->de_fnode, dep->de_size, dep->de_namelen, - dep->de_namelen, dep->de_name, dep->de_flag)); - - /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/ - for (i=0; i<dep->de_namelen; i++) - cde.d_name[i] = hpfs_d2u(hpmp, dep->de_name[i]); - - cde.d_name[dep->de_namelen] = '\0'; - cde.d_namlen = dep->de_namelen; - cde.d_fileno = dep->de_fnode; - cde.d_type = (dep->de_flag & DE_DIR) ? DT_DIR : DT_REG; - cde.d_reclen = sizeof(struct dirent); - - error = uiomove((char *)&cde, sizeof(struct dirent), uio); - if (error) - return (error); - - dprintf(("[0x%x] ", uio->uio_resid)); - return (error); -} - - -static struct dirent hpfs_de_dot = { - .d_fileno = 0, - .d_reclen = sizeof(struct dirent), - .d_type = DT_DIR, - .d_namlen = 1, - .d_name = "." -}; -static struct dirent hpfs_de_dotdot = { - .d_fileno = 0, - .d_reclen = sizeof(struct dirent), - .d_type = DT_DIR, - .d_namlen = 2, - .d_name = ".." -}; - -int -hpfs_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_ncookies; - u_int **cookies; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct hpfsnode *hp = VTOHP(vp); - struct hpfsmount *hpmp = hp->h_hpmp; - struct uio *uio = ap->a_uio; - int ncookies = 0, i, num, cnum; - int error = 0; - off_t off; - struct buf *bp; - struct dirblk *dp; - struct hpfsdirent *dep; - lsn_t olsn; - lsn_t lsn; - int level; - - dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid)); - - off = uio->uio_offset; - - if( uio->uio_offset < sizeof(struct dirent) ) { - dprintf((". faked, ")); - hpfs_de_dot.d_fileno = hp->h_no; - error = uiomove((char *)&hpfs_de_dot,sizeof(struct dirent),uio); - if(error) { - return (error); - } - - ncookies ++; - } - - if( uio->uio_offset < 2 * sizeof(struct dirent) ) { - dprintf((".. faked, ")); - hpfs_de_dotdot.d_fileno = hp->h_fn.fn_parent; - - error = uiomove((char *)&hpfs_de_dotdot, sizeof(struct dirent), - uio); - if(error) { - return (error); - } - - ncookies ++; - } - - num = uio->uio_offset / sizeof(struct dirent) - 2; - cnum = 0; - - lsn = ((alleaf_t *)hp->h_fn.fn_abd)->al_lsn; - - olsn = 0; - level = 1; - -dive: - dprintf(("[dive 0x%x] ", lsn)); - error = bread(hp->h_devvp, lsn, D_BSIZE, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - - dp = (struct dirblk *) bp->b_data; - if (dp->d_magic != D_MAGIC) { - printf("hpfs_readdir: MAGIC DOESN'T MATCH\n"); - brelse(bp); - return (EINVAL); - } - - dep = D_DIRENT(dp); - - if (olsn) { - dprintf(("[restore 0x%x] ", olsn)); - - while(!(dep->de_flag & DE_END) ) { - if((dep->de_flag & DE_DOWN) && - (olsn == DE_DOWNLSN(dep))) - break; - dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); - } - - if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) { - if (dep->de_flag & DE_END) - goto blockdone; - - if (!(dep->de_flag & DE_SPECIAL)) { - if (num <= cnum) { - if (uio->uio_resid < sizeof(struct dirent)) { - brelse(bp); - dprintf(("[resid] ")); - goto readdone; - } - - error = hpfs_de_uiomove(hpmp, dep, uio); - if (error) { - brelse (bp); - return (error); - } - ncookies++; - - if (uio->uio_resid < sizeof(struct dirent)) { - brelse(bp); - dprintf(("[resid] ")); - goto readdone; - } - } - cnum++; - } - - dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); - } else { - printf("hpfs_readdir: ERROR! oLSN not found\n"); - brelse(bp); - return (EINVAL); - } - } - - olsn = 0; - - while(!(dep->de_flag & DE_END)) { - if(dep->de_flag & DE_DOWN) { - lsn = DE_DOWNLSN(dep); - brelse(bp); - level++; - goto dive; - } - - if (!(dep->de_flag & DE_SPECIAL)) { - if (num <= cnum) { - if (uio->uio_resid < sizeof(struct dirent)) { - brelse(bp); - dprintf(("[resid] ")); - goto readdone; - } - - error = hpfs_de_uiomove(hpmp, dep, uio); - if (error) { - brelse (bp); - return (error); - } - ncookies++; - - if (uio->uio_resid < sizeof(struct dirent)) { - brelse(bp); - dprintf(("[resid] ")); - goto readdone; - } - } - cnum++; - } - - dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); - } - - if(dep->de_flag & DE_DOWN) { - dprintf(("[enddive] ")); - lsn = DE_DOWNLSN(dep); - brelse(bp); - level++; - goto dive; - } - -blockdone: - dprintf(("[EOB] ")); - olsn = lsn; - lsn = dp->d_parent; - brelse(bp); - level--; - - dprintf(("[level %d] ", level)); - - if (level > 0) - goto dive; /* undive really */ - - if (ap->a_eofflag) { - dprintf(("[EOF] ")); - *ap->a_eofflag = 1; - } - -readdone: - dprintf(("[readdone]\n")); - if (!error && ap->a_ncookies != NULL) { - struct dirent* dpStart; - struct dirent* dp; - u_long *cookies; - u_long *cookiep; - - dprintf(("%d cookies, ",ncookies)); - if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) - panic("hpfs_readdir: unexpected uio from NFS server"); - dpStart = (struct dirent *) - ((caddr_t)uio->uio_iov->iov_base - - (uio->uio_offset - off)); - cookies = malloc(ncookies * sizeof(u_long), - M_TEMP, M_WAITOK); - for (dp = dpStart, cookiep = cookies, i=0; - i < ncookies; - dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) { - off += dp->d_reclen; - *cookiep++ = (u_int) off; - } - *ap->a_ncookies = ncookies; - *ap->a_cookies = cookies; - } - - return (0); -} - -int -hpfs_lookup(ap) - struct vop_cachedlookup_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - } */ *ap; -{ - register struct vnode *dvp = ap->a_dvp; - register struct hpfsnode *dhp = VTOHP(dvp); - struct hpfsmount *hpmp = dhp->h_hpmp; - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - int error; - int nameiop = cnp->cn_nameiop; - int flags = cnp->cn_flags; - dprintf(("hpfs_lookup(0x%x, %s, %ld):\n", - dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen)); - - if (nameiop != CREATE && nameiop != DELETE && nameiop != LOOKUP) { - printf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n"); - return (EOPNOTSUPP); - } - - error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread); - if(error) - return (error); - - if( (cnp->cn_namelen == 1) && - !strncmp(cnp->cn_nameptr,".",1) ) { - dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp->h_no)); - - VREF(dvp); - *ap->a_vpp = dvp; - - return (0); - } else if( (cnp->cn_namelen == 2) && - !strncmp(cnp->cn_nameptr,"..",2) && (flags & ISDOTDOT) ) { - dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n", - dhp->h_no, dhp->h_fn.fn_parent)); - - if (VFS_VGET(hpmp->hpm_mp, dhp->h_fn.fn_parent, - LK_NOWAIT | LK_EXCLUSIVE, ap->a_vpp)) { - VOP_UNLOCK(dvp,0); - error = VFS_VGET(hpmp->hpm_mp, - dhp->h_fn.fn_parent, LK_EXCLUSIVE, ap->a_vpp); - vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY); - if (error) - return(error); - } - return (0); - } else { - struct buf *bp; - struct hpfsdirent *dep; - struct hpfsnode *hp; - - error = hpfs_genlookupbyname(dhp, - cnp->cn_nameptr, cnp->cn_namelen, &bp, &dep); - if (error) { - if ((error == ENOENT) && (flags & ISLASTCN) && - (nameiop == CREATE || nameiop == RENAME)) { - cnp->cn_flags |= SAVENAME; - return (EJUSTRETURN); - } - - return (error); - } - - dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n", - dep->de_fnode, dep->de_cpid)); - - if (nameiop == DELETE && (flags & ISLASTCN)) { - error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_thread); - if (error) { - brelse(bp); - return (error); - } - } - - if (dhp->h_no == dep->de_fnode) { - brelse(bp); - VREF(dvp); - *ap->a_vpp = dvp; - return (0); - } - - error = VFS_VGET(hpmp->hpm_mp, dep->de_fnode, LK_EXCLUSIVE, - ap->a_vpp); - if (error) { - printf("hpfs_lookup: VFS_VGET FAILED %d\n", error); - brelse(bp); - return(error); - } - - hp = VTOHP(*ap->a_vpp); - - hp->h_mtime = dep->de_mtime; - hp->h_ctime = dep->de_ctime; - hp->h_atime = dep->de_atime; - bcopy(dep->de_name, hp->h_name, dep->de_namelen); - hp->h_name[dep->de_namelen] = '\0'; - hp->h_namelen = dep->de_namelen; - hp->h_flag |= H_PARVALID; - - brelse(bp); - - if ((flags & MAKEENTRY) && - (!(flags & ISLASTCN) || - (nameiop != DELETE && nameiop != CREATE))) - cache_enter(dvp, *ap->a_vpp, cnp); - } - return (error); -} - -int -hpfs_remove(ap) - struct vop_remove_args /* { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap; -{ - int error; - - dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap->a_vp)->h_no, - ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen)); - - if (ap->a_vp->v_type == VDIR) - return (EPERM); - - error = hpfs_removefnode (ap->a_dvp, ap->a_vp, ap->a_cnp); - return (error); -} - -int -hpfs_create(ap) - struct vop_create_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - } */ *ap; -{ - int error; - - dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap->a_dvp)->h_no, - ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen)); - - if (!(ap->a_cnp->cn_flags & HASBUF)) - panic ("hpfs_create: no name\n"); - - error = hpfs_makefnode (ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap); - - return (error); -} - -/* - * Return POSIX pathconf information applicable to NTFS filesystem - */ -int -hpfs_pathconf(ap) - struct vop_pathconf_args /* { - struct vnode *a_vp; - int a_name; - register_t *a_retval; - } */ *ap; -{ - switch (ap->a_name) { - case _PC_LINK_MAX: - *ap->a_retval = 1; - return (0); - case _PC_NAME_MAX: - *ap->a_retval = HPFS_MAXFILENAME; - return (0); - case _PC_PATH_MAX: - *ap->a_retval = PATH_MAX; - return (0); - case _PC_CHOWN_RESTRICTED: - *ap->a_retval = 1; - return (0); - case _PC_NO_TRUNC: - *ap->a_retval = 0; - return (0); - default: - return (EINVAL); - } - /* NOTREACHED */ -} - -int -hpfs_vptofh(ap) - struct vop_vptofh_args /* { - struct vnode *a_vp; - struct fid *a_fhp; - } */ *ap; -{ - register struct hpfsnode *hpp; - register struct hpfid *hpfhp; - - hpp = VTOHP(ap->a_vp); - hpfhp = (struct hpfid *)ap->a_fhp; - hpfhp->hpfid_len = sizeof(struct hpfid); - hpfhp->hpfid_ino = hpp->h_no; - /* hpfhp->hpfid_gen = hpp->h_gen; */ - return (0); -} - - -/* - * Global vfs data structures - */ -struct vop_vector hpfs_vnodeops = { - .vop_default = &default_vnodeops, - - .vop_access = hpfs_access, - .vop_bmap = hpfs_bmap, - .vop_cachedlookup = hpfs_lookup, - .vop_close = hpfs_close, - .vop_create = hpfs_create, - .vop_fsync = hpfs_fsync, - .vop_getattr = hpfs_getattr, - .vop_inactive = hpfs_inactive, - .vop_ioctl = hpfs_ioctl, - .vop_lookup = vfs_cache_lookup, - .vop_open = hpfs_open, - .vop_pathconf = hpfs_pathconf, - .vop_print = hpfs_print, - .vop_read = hpfs_read, - .vop_readdir = hpfs_readdir, - .vop_reclaim = hpfs_reclaim, - .vop_remove = hpfs_remove, - .vop_setattr = hpfs_setattr, - .vop_strategy = hpfs_strategy, - .vop_write = hpfs_write, - .vop_vptofh = hpfs_vptofh, -}; diff --git a/sys/fs/hpfs/hpfsmount.h b/sys/fs/hpfs/hpfsmount.h deleted file mode 100644 index 5ca42b3..0000000 --- a/sys/fs/hpfs/hpfsmount.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#define HPFSMNT_TABLES 0x0001 -struct hpfs_args { - char *fspec; /* block special device to mount */ - struct oexport_args export; /* network export information */ - uid_t uid; /* uid that owns hpfs files */ - gid_t gid; /* gid that owns hpfs files */ - mode_t mode; /* mask to be applied for hpfs perms */ - u_long flags; /* additional flags */ - u_char d2u[0x80]; - u_char u2d[0x80]; -}; diff --git a/sys/fs/ntfs/ntfs.h b/sys/fs/ntfs/ntfs.h deleted file mode 100644 index 26e86a9..0000000 --- a/sys/fs/ntfs/ntfs.h +++ /dev/null @@ -1,308 +0,0 @@ -/* $NetBSD: ntfs.h,v 1.9 1999/10/31 19:45:26 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -/*#define NTFS_DEBUG 1*/ - -typedef uint64_t cn_t; -typedef uint16_t wchar; - -#pragma pack(1) -#define BBSIZE 1024 -#define BBOFF ((off_t)(0)) -#define BBLOCK 0 -#define NTFS_MFTINO 0 -#define NTFS_VOLUMEINO 3 -#define NTFS_ATTRDEFINO 4 -#define NTFS_ROOTINO 5 -#define NTFS_BITMAPINO 6 -#define NTFS_BOOTINO 7 -#define NTFS_BADCLUSINO 8 -#define NTFS_UPCASEINO 10 -#define NTFS_MAXFILENAME 255 - -struct fixuphdr { - uint32_t fh_magic; - uint16_t fh_foff; - uint16_t fh_fnum; -}; - -#define NTFS_AF_INRUN 0x00000001 -struct attrhdr { - uint32_t a_type; - uint32_t reclen; - uint8_t a_flag; - uint8_t a_namelen; - uint8_t a_nameoff; - uint8_t reserved1; - uint8_t a_compression; - uint8_t reserved2; - uint16_t a_index; -}; -#define NTFS_A_STD 0x10 -#define NTFS_A_ATTRLIST 0x20 -#define NTFS_A_NAME 0x30 -#define NTFS_A_VOLUMENAME 0x60 -#define NTFS_A_DATA 0x80 -#define NTFS_A_INDXROOT 0x90 -#define NTFS_A_INDX 0xA0 -#define NTFS_A_INDXBITMAP 0xB0 - -#define NTFS_MAXATTRNAME 255 -struct attr { - struct attrhdr a_hdr; - union { - struct { - uint16_t a_datalen; - uint16_t reserved1; - uint16_t a_dataoff; - uint16_t a_indexed; - } a_S_r; - struct { - cn_t a_vcnstart; - cn_t a_vcnend; - uint16_t a_dataoff; - uint16_t a_compressalg; - uint32_t reserved1; - uint64_t a_allocated; - uint64_t a_datalen; - uint64_t a_initialized; - } a_S_nr; - } a_S; -}; -#define a_r a_S.a_S_r -#define a_nr a_S.a_S_nr - -typedef struct { - uint64_t t_create; - uint64_t t_write; - uint64_t t_mftwrite; - uint64_t t_access; -} ntfs_times_t; - -#define NTFS_FFLAG_RDONLY 0x01LL -#define NTFS_FFLAG_HIDDEN 0x02LL -#define NTFS_FFLAG_SYSTEM 0x04LL -#define NTFS_FFLAG_ARCHIVE 0x20LL -#define NTFS_FFLAG_COMPRESSED 0x0800LL -#define NTFS_FFLAG_DIR 0x10000000LL - -struct attr_name { - uint32_t n_pnumber; /* Parent ntnode */ - uint32_t reserved; - ntfs_times_t n_times; - uint64_t n_size; - uint64_t n_attrsz; - uint64_t n_flag; - uint8_t n_namelen; - uint8_t n_nametype; - uint16_t n_name[1]; -}; - -#define NTFS_IRFLAG_INDXALLOC 0x00000001 -struct attr_indexroot { - uint32_t ir_unkn1; /* always 0x30 */ - uint32_t ir_unkn2; /* always 0x1 */ - uint32_t ir_size;/* ??? */ - uint32_t ir_unkn3; /* number of cluster */ - uint32_t ir_unkn4; /* always 0x10 */ - uint32_t ir_datalen; /* sizeof simething */ - uint32_t ir_allocated; /* same as above */ - uint16_t ir_flag;/* ?? always 1 */ - uint16_t ir_unkn7; -}; - -struct attr_attrlist { - uint32_t al_type; /* Attribute type */ - uint16_t reclen; /* length of this entry */ - uint8_t al_namelen; /* Attribute name len */ - uint8_t al_nameoff; /* Name offset from entry start */ - uint64_t al_vcnstart; /* VCN number */ - uint32_t al_inumber; /* Parent ntnode */ - uint32_t reserved; - uint16_t al_index; /* Attribute index in MFT record */ - uint16_t al_name[1]; /* Name */ -}; - -#define NTFS_INDXMAGIC (uint32_t)(0x58444E49) -struct attr_indexalloc { - struct fixuphdr ia_fixup; - uint64_t unknown1; - cn_t ia_bufcn; - uint16_t ia_hdrsize; - uint16_t unknown2; - uint32_t ia_inuse; - uint32_t ia_allocated; -}; - -#define NTFS_IEFLAG_SUBNODE 0x00000001 -#define NTFS_IEFLAG_LAST 0x00000002 - -struct attr_indexentry { - uint32_t ie_number; - uint32_t unknown1; - uint16_t reclen; - uint16_t ie_size; - uint32_t ie_flag; /* 1 - has subnodes, 2 - last */ - uint32_t ie_fpnumber; - uint32_t unknown2; - ntfs_times_t ie_ftimes; - uint64_t ie_fallocated; - uint64_t ie_fsize; - uint64_t ie_fflag; - uint8_t ie_fnamelen; - uint8_t ie_fnametype; - wchar ie_fname[NTFS_MAXFILENAME]; - /* cn_t ie_bufcn; buffer with subnodes */ -}; - -#define NTFS_FILEMAGIC (uint32_t)(0x454C4946) -#define NTFS_BLOCK_SIZE 512 -#define NTFS_FRFLAG_DIR 0x0002 -struct filerec { - struct fixuphdr fr_fixup; - uint8_t reserved[8]; - uint16_t fr_seqnum; /* Sequence number */ - uint16_t fr_nlink; - uint16_t fr_attroff; /* offset to attributes */ - uint16_t fr_flags; /* 1-nonresident attr, 2-directory */ - uint32_t fr_size;/* hdr + attributes */ - uint32_t fr_allocated; /* allocated length of record */ - uint64_t fr_mainrec; /* main record */ - uint16_t fr_attrnum; /* maximum attr number + 1 ??? */ -}; - -#define NTFS_ATTRNAME_MAXLEN 0x40 -#define NTFS_ADFLAG_NONRES 0x0080 /* Attrib can be non resident */ -#define NTFS_ADFLAG_INDEX 0x0002 /* Attrib can be indexed */ -struct attrdef { - wchar ad_name[NTFS_ATTRNAME_MAXLEN]; - uint32_t ad_type; - uint32_t reserved1[2]; - uint32_t ad_flag; - uint64_t ad_minlen; - uint64_t ad_maxlen; /* -1 for nonlimited */ -}; - -struct ntvattrdef { - char ad_name[0x40]; - int ad_namelen; - uint32_t ad_type; -}; - -#define NTFS_BBID "NTFS " -#define NTFS_BBIDLEN 8 -struct bootfile { - uint8_t reserved1[3]; /* asm jmp near ... */ - uint8_t bf_sysid[8]; /* 'NTFS ' */ - uint16_t bf_bps; /* bytes per sector */ - uint8_t bf_spc; /* sectors per cluster */ - uint8_t reserved2[7]; /* unused (zeroed) */ - uint8_t bf_media; /* media desc. (0xF8) */ - uint8_t reserved3[2]; - uint16_t bf_spt; /* sectors per track */ - uint16_t bf_heads; /* number of heads */ - uint8_t reserver4[12]; - uint64_t bf_spv; /* sectors per volume */ - cn_t bf_mftcn; /* $MFT cluster number */ - cn_t bf_mftmirrcn; /* $MFTMirr cn */ - uint8_t bf_mftrecsz; /* MFT record size (clust) */ - /* 0xF6 inducates 1/4 */ - uint32_t bf_ibsz; /* index buffer size */ - uint32_t bf_volsn; /* volume ser. num. */ -}; - -#define NTFS_SYSNODESNUM 0x0B -struct ntfsmount { - struct mount *ntm_mountp; /* filesystem vfs structure */ - struct bootfile ntm_bootfile; - struct g_consumer *ntm_cp; - struct bufobj *ntm_bo; - struct vnode *ntm_devvp; /* block device mounted vnode */ - struct vnode *ntm_sysvn[NTFS_SYSNODESNUM]; - uint32_t ntm_bpmftrec; - uid_t ntm_uid; - gid_t ntm_gid; - mode_t ntm_mode; - uint64_t ntm_flag; - cn_t ntm_cfree; - struct ntvattrdef *ntm_ad; - int ntm_adnum; - wchar * ntm_82u; /* 8bit to Unicode */ - char ** ntm_u28; /* Unicode to 8 bit */ - void * ntm_ic_l2u; /* Local to Unicode (iconv) */ - void * ntm_ic_u2l; /* Unicode to Local (iconv) */ - uint8_t ntm_multiplier; /* NTFS blockno to DEV_BSIZE sectorno */ -}; - -#define ntm_mftcn ntm_bootfile.bf_mftcn -#define ntm_mftmirrcn ntm_bootfile.bf_mftmirrcn -#define ntm_mftrecsz ntm_bootfile.bf_mftrecsz -#define ntm_spc ntm_bootfile.bf_spc -#define ntm_bps ntm_bootfile.bf_bps - -#pragma pack() - -#define NTFS_NEXTREC(s, type) ((type)(((caddr_t) s) + (s)->reclen)) - -/* Convert mount ptr to ntfsmount ptr. */ -#define VFSTONTFS(mp) ((struct ntfsmount *)((mp)->mnt_data)) -#define VTONT(v) FTONT(VTOF(v)) -#define VTOF(v) ((struct fnode *)((v)->v_data)) -#define FTOV(f) ((f)->f_vp) -#define FTONT(f) ((f)->f_ip) -#define ntfs_cntobn(cn) (daddr_t)((cn) * (ntmp->ntm_spc)) -#define ntfs_cntob(cn) (off_t)((cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps) -#define ntfs_btocn(off) (cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) -#define ntfs_btocl(off) (cn_t)((off + ntfs_cntob(1) - 1) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) -#define ntfs_btocnoff(off) (off_t)((off) % ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) -#define ntfs_bntob(bn) (daddr_t)((bn) * (ntmp)->ntm_bps) - -#define ntfs_bpbl (daddr_t)((ntmp)->ntm_bps) - -#ifdef MALLOC_DECLARE -MALLOC_DECLARE(M_NTFSNTNODE); -MALLOC_DECLARE(M_NTFSFNODE); -MALLOC_DECLARE(M_NTFSDIR); -MALLOC_DECLARE(M_NTFSNTHASH); -#endif - -#if defined(NTFS_DEBUG) -#define dprintf(a) printf a -#if NTFS_DEBUG > 1 -#define ddprintf(a) printf a -#else -#define ddprintf(a) (void)0 -#endif -#else -#define dprintf(a) (void)0 -#define ddprintf(a) (void)0 -#endif - -extern struct vop_vector ntfs_vnodeops; diff --git a/sys/fs/ntfs/ntfs_compr.c b/sys/fs/ntfs/ntfs_compr.c deleted file mode 100644 index dcc82a3..0000000 --- a/sys/fs/ntfs/ntfs_compr.c +++ /dev/null @@ -1,111 +0,0 @@ -/* $NetBSD: ntfs_compr.c,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/namei.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/file.h> - -#include <fs/ntfs/ntfs.h> -#include <fs/ntfs/ntfs_compr.h> - -#define GET_UINT16(addr) (*((u_int16_t *)(addr))) - -int -ntfs_uncompblock( - u_int8_t * dbuf, - u_int8_t * cbuf) -{ - u_int32_t ctag; - int len, dshift, lmask; - int blen, boff; - int i, j; - int pos, cpos; - - len = GET_UINT16(cbuf) & 0xFFF; - dprintf(("ntfs_uncompblock: block length: %d + 3, 0x%x,0x%04x\n", - len, len, GET_UINT16(cbuf))); - - if (!(GET_UINT16(cbuf) & 0x8000)) { - if ((len + 1) != NTFS_COMPBLOCK_SIZE) { - dprintf(("ntfs_uncompblock: len: %x instead of %d\n", - len, 0xfff)); - } - memcpy(dbuf, cbuf + 2, len + 1); - memset(dbuf + len + 1, 0, NTFS_COMPBLOCK_SIZE - 1 - len); - return len + 3; - } - cpos = 2; - pos = 0; - while ((cpos < len + 3) && (pos < NTFS_COMPBLOCK_SIZE)) { - ctag = cbuf[cpos++]; - for (i = 0; (i < 8) && (pos < NTFS_COMPBLOCK_SIZE); i++) { - if (ctag & 1) { - for (j = pos - 1, lmask = 0xFFF, dshift = 12; - j >= 0x10; j >>= 1) { - dshift--; - lmask >>= 1; - } - boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift); - blen = 3 + (GET_UINT16(cbuf + cpos) & lmask); - for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) { - dbuf[pos] = dbuf[pos + boff]; - pos++; - } - cpos += 2; - } else { - dbuf[pos++] = cbuf[cpos++]; - } - ctag >>= 1; - } - } - return len + 3; -} - -int -ntfs_uncompunit( - struct ntfsmount * ntmp, - u_int8_t * uup, - u_int8_t * cup) -{ - int i; - int off = 0; - int new; - - for (i = 0; i * NTFS_COMPBLOCK_SIZE < ntfs_cntob(NTFS_COMPUNIT_CL); i++) { - new = ntfs_uncompblock(uup + i * NTFS_COMPBLOCK_SIZE, cup + off); - if (new == 0) - return (EINVAL); - off += new; - } - return (0); -} diff --git a/sys/fs/ntfs/ntfs_compr.h b/sys/fs/ntfs/ntfs_compr.h deleted file mode 100644 index e51bc09..0000000 --- a/sys/fs/ntfs/ntfs_compr.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $NetBSD: ntfs_compr.h,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#define NTFS_COMPBLOCK_SIZE 0x1000 -#define NTFS_COMPUNIT_CL 16 - -int ntfs_uncompblock(u_int8_t *, u_int8_t *); -int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, u_int8_t *); diff --git a/sys/fs/ntfs/ntfs_iconv.c b/sys/fs/ntfs/ntfs_iconv.c deleted file mode 100644 index 347306e..0000000 --- a/sys/fs/ntfs/ntfs_iconv.c +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * Copyright (c) 2003 Ryuichiro Imura - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/mount.h> -#include <sys/iconv.h> - -VFS_DECLARE_ICONV(ntfs); diff --git a/sys/fs/ntfs/ntfs_ihash.c b/sys/fs/ntfs/ntfs_ihash.c deleted file mode 100644 index bb40d5c..0000000 --- a/sys/fs/ntfs/ntfs_ihash.c +++ /dev/null @@ -1,130 +0,0 @@ -/* $NetBSD: ntfs_ihash.c,v 1.5 1999/09/30 16:56:40 jdolecek Exp $ */ - -/*- - * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. - * - * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95 - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/vnode.h> -#include <sys/malloc.h> -#include <sys/mount.h> -#include <sys/mutex.h> - -#include <fs/ntfs/ntfs.h> -#include <fs/ntfs/ntfs_inode.h> -#include <fs/ntfs/ntfs_ihash.h> - -MALLOC_DEFINE(M_NTFSNTHASH, "ntfs_nthash", "NTFS ntnode hash tables"); - -/* - * Structures associated with inode cacheing. - */ -static LIST_HEAD(nthashhead, ntnode) *ntfs_nthashtbl; -static u_long ntfs_nthash; /* size of hash table - 1 */ -#define NTNOHASH(inum) (&ntfs_nthashtbl[(inum) & ntfs_nthash]) -static struct mtx ntfs_nthash_mtx; -struct lock ntfs_hashlock; - -/* - * Initialize inode hash table. - */ -void -ntfs_nthashinit() -{ - lockinit(&ntfs_hashlock, PINOD, "ntfs_nthashlock", 0, 0); - ntfs_nthashtbl = hashinit(desiredvnodes, M_NTFSNTHASH, &ntfs_nthash); - mtx_init(&ntfs_nthash_mtx, "ntfs nthash", NULL, MTX_DEF); -} - -/* - * Destroy inode hash table. - */ -void -ntfs_nthashdestroy(void) -{ - hashdestroy(ntfs_nthashtbl, M_NTFSNTHASH, ntfs_nthash); - lockdestroy(&ntfs_hashlock); - mtx_destroy(&ntfs_nthash_mtx); -} - -/* - * Use the device/inum pair to find the incore inode, and return a pointer - * to it. If it is in core, return it, even if it is locked. - */ -struct ntnode * -ntfs_nthashlookup(dev, inum) - struct cdev *dev; - ino_t inum; -{ - struct ntnode *ip; - - mtx_lock(&ntfs_nthash_mtx); - LIST_FOREACH(ip, NTNOHASH(inum), i_hash) - if (inum == ip->i_number && dev == ip->i_dev) - break; - mtx_unlock(&ntfs_nthash_mtx); - - return (ip); -} - -/* - * Insert the ntnode into the hash table. - */ -void -ntfs_nthashins(ip) - struct ntnode *ip; -{ - struct nthashhead *ipp; - - mtx_lock(&ntfs_nthash_mtx); - ipp = NTNOHASH(ip->i_number); - LIST_INSERT_HEAD(ipp, ip, i_hash); - ip->i_flag |= IN_HASHED; - mtx_unlock(&ntfs_nthash_mtx); -} - -/* - * Remove the inode from the hash table. - */ -void -ntfs_nthashrem(ip) - struct ntnode *ip; -{ - mtx_lock(&ntfs_nthash_mtx); - if (ip->i_flag & IN_HASHED) { - ip->i_flag &= ~IN_HASHED; - LIST_REMOVE(ip, i_hash); - } - mtx_unlock(&ntfs_nthash_mtx); -} diff --git a/sys/fs/ntfs/ntfs_ihash.h b/sys/fs/ntfs/ntfs_ihash.h deleted file mode 100644 index 7df7495..0000000 --- a/sys/fs/ntfs/ntfs_ihash.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $NetBSD: ntfs_ihash.h,v 1.4 1999/09/30 16:56:40 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -extern struct lock ntfs_hashlock; -void ntfs_nthashinit(void); -void ntfs_nthashdestroy(void); -struct ntnode *ntfs_nthashlookup(struct cdev *, ino_t); -struct ntnode *ntfs_nthashget(struct cdev *, ino_t); -void ntfs_nthashins(struct ntnode *); -void ntfs_nthashrem(register struct ntnode *); diff --git a/sys/fs/ntfs/ntfs_inode.h b/sys/fs/ntfs/ntfs_inode.h deleted file mode 100644 index c11cfa1..0000000 --- a/sys/fs/ntfs/ntfs_inode.h +++ /dev/null @@ -1,101 +0,0 @@ -/* $NetBSD: ntfs_inode.h,v 1.8 1999/10/31 19:45:26 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -/* These flags are kept in i_flag. */ -#define IN_ACCESS 0x0001 /* Access time update request. */ -#define IN_CHANGE 0x0002 /* Inode change time update request. */ -#define IN_UPDATE 0x0004 /* Modification time update request. */ -#define IN_MODIFIED 0x0008 /* Inode has been modified. */ -#define IN_RENAME 0x0010 /* Inode is being renamed. */ -#define IN_SHLOCK 0x0020 /* File has shared lock. */ -#define IN_EXLOCK 0x0040 /* File has exclusive lock. */ -#define IN_LAZYMOD 0x0080 /* Modified, but don't write yet. */ -#define IN_HASHED 0x0800 /* Inode is on hash list */ -#define IN_LOADED 0x8000 /* ntvattrs loaded */ -#define IN_PRELOADED 0x4000 /* loaded from directory entry */ - -struct ntnode { - struct vnode *i_devvp; /* vnode of blk dev we live on */ - struct cdev *i_dev; /* Device associated with the inode. */ - - LIST_ENTRY(ntnode) i_hash; - struct ntnode *i_next; - struct ntnode **i_prev; - struct ntfsmount *i_mp; - ino_t i_number; - u_int32_t i_flag; - - /* locking */ - struct lock i_lock; - struct mtx i_interlock; - int i_usecount; - - LIST_HEAD(,fnode) i_fnlist; - LIST_HEAD(,ntvattr) i_valist; - - long i_nlink; /* MFR */ - ino_t i_mainrec; /* MFR */ - u_int32_t i_frflag; /* MFR */ -}; - -#define FN_PRELOADED 0x0001 -#define FN_VALID 0x0002 -#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */ -struct fnode { - LIST_ENTRY(fnode) f_fnlist; - struct vnode *f_vp; /* Associatied vnode */ - struct ntnode *f_ip; /* Associated ntnode */ - u_long f_flag; - - ntfs_times_t f_times; /* $NAME/dirinfo */ - ino_t f_pnumber; /* $NAME/dirinfo */ - u_int32_t f_fflag; /* $NAME/dirinfo */ - u_int64_t f_size; /* defattr/dirinfo: */ - u_int64_t f_allocated; /* defattr/dirinfo */ - - u_int32_t f_attrtype; - char *f_attrname; - - /* for ntreaddir */ - u_int32_t f_lastdattr; - u_int32_t f_lastdblnum; - u_int32_t f_lastdoff; - u_int32_t f_lastdnum; - caddr_t f_dirblbuf; - u_int32_t f_dirblsz; -}; - -/* This overlays the fid structure (see <sys/mount.h>) */ -struct ntfid { - u_int16_t ntfid_len; /* Length of structure. */ - u_int16_t ntfid_pad; /* Force 32-bit alignment. */ - ino_t ntfid_ino; /* File number (ino). */ - int32_t ntfid_gen; /* Generation number. */ -}; diff --git a/sys/fs/ntfs/ntfs_subr.c b/sys/fs/ntfs/ntfs_subr.c deleted file mode 100644 index dae7777..0000000 --- a/sys/fs/ntfs/ntfs_subr.c +++ /dev/null @@ -1,2029 +0,0 @@ -/* $NetBSD: ntfs_subr.c,v 1.23 1999/10/31 19:45:26 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/systm.h> -#include <sys/namei.h> -#include <sys/kernel.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/file.h> -#include <sys/malloc.h> -#include <sys/lock.h> -#include <sys/iconv.h> - -/* #define NTFS_DEBUG 1 */ -#include <fs/ntfs/ntfs.h> -#include <fs/ntfs/ntfsmount.h> -#include <fs/ntfs/ntfs_inode.h> -#include <fs/ntfs/ntfs_vfsops.h> -#include <fs/ntfs/ntfs_subr.h> -#include <fs/ntfs/ntfs_compr.h> -#include <fs/ntfs/ntfs_ihash.h> - -static MALLOC_DEFINE(M_NTFSNTVATTR, "ntfs_vattr", - "NTFS file attribute information"); -static MALLOC_DEFINE(M_NTFSRDATA, "ntfsd_resdata", "NTFS resident data"); -static MALLOC_DEFINE(M_NTFSRUN, "ntfs_vrun", "NTFS vrun storage"); -static MALLOC_DEFINE(M_NTFSDECOMP, "ntfs_decomp", - "NTFS decompression temporary"); - -static int ntfs_ntlookupattr(struct ntfsmount *, const char *, int, int *, char **); -static int ntfs_findvattr(struct ntfsmount *, struct ntnode *, struct ntvattr **, struct ntvattr **, u_int32_t, const char *, size_t, cn_t); -static int ntfs_uastricmp(struct ntfsmount *, const wchar *, size_t, const char *, size_t); -static int ntfs_uastrcmp(struct ntfsmount *, const wchar *, size_t, const char *, size_t); - -/* table for mapping Unicode chars into uppercase; it's filled upon first - * ntfs mount, freed upon last ntfs umount */ -static wchar *ntfs_toupper_tab; -#define NTFS_TOUPPER(ch) (ntfs_toupper_tab[(ch)]) -static struct lock ntfs_toupper_lock; -static signed int ntfs_toupper_usecount; - -struct iconv_functions *ntfs_iconv = NULL; - -/* support macro for ntfs_ntvattrget() */ -#define NTFS_AALPCMP(aalp,type,name,namelen) ( \ - (aalp->al_type == type) && (aalp->al_namelen == namelen) && \ - !NTFS_UASTRCMP(aalp->al_name,aalp->al_namelen,name,namelen) ) - -/* - * - */ -int -ntfs_ntvattrrele(vap) - struct ntvattr * vap; -{ - dprintf(("ntfs_ntvattrrele: ino: %ju, type: 0x%x\n", - (uintmax_t)vap->va_ip->i_number, vap->va_type)); - - ntfs_ntrele(vap->va_ip); - - return (0); -} - -/* - * find the attribute in the ntnode - */ -static int -ntfs_findvattr(ntmp, ip, lvapp, vapp, type, name, namelen, vcn) - struct ntfsmount *ntmp; - struct ntnode *ip; - struct ntvattr **lvapp, **vapp; - u_int32_t type; - const char *name; - size_t namelen; - cn_t vcn; -{ - int error; - struct ntvattr *vap; - - if((ip->i_flag & IN_LOADED) == 0) { - dprintf(("ntfs_findvattr: node not loaded, ino: %ju\n", - (uintmax_t)ip->i_number)); - error = ntfs_loadntnode(ntmp,ip); - if (error) { - printf("ntfs_findvattr: FAILED TO LOAD INO: %ju\n", - (uintmax_t)ip->i_number); - return (error); - } - } - - *lvapp = NULL; - *vapp = NULL; - LIST_FOREACH(vap, &ip->i_valist, va_list) { - ddprintf(("ntfs_findvattr: type: 0x%x, vcn: %d - %d\n", \ - vap->va_type, (u_int32_t) vap->va_vcnstart, \ - (u_int32_t) vap->va_vcnend)); - if ((vap->va_type == type) && - (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) && - (vap->va_namelen == namelen) && - (strncmp(name, vap->va_name, namelen) == 0)) { - *vapp = vap; - ntfs_ntref(vap->va_ip); - return (0); - } - if (vap->va_type == NTFS_A_ATTRLIST) - *lvapp = vap; - } - - return (-1); -} - -/* - * Search attribute specifed in ntnode (load ntnode if nessecary). - * If not found but ATTR_A_ATTRLIST present, read it in and search throught. - * VOP_VGET node needed, and lookup througth it's ntnode (load if nessesary). - * - * ntnode should be locked - */ -int -ntfs_ntvattrget( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t type, - const char *name, - cn_t vcn, - struct ntvattr ** vapp) -{ - struct ntvattr *lvap = NULL; - struct attr_attrlist *aalp; - struct attr_attrlist *nextaalp; - struct vnode *newvp; - struct ntnode *newip; - caddr_t alpool; - size_t namelen, len; - int error; - - *vapp = NULL; - - if (name) { - dprintf(("ntfs_ntvattrget: " \ - "ino: %ju, type: 0x%x, name: %s, vcn: %d\n", \ - (uintmax_t)ip->i_number, type, name, (uint32_t)vcn)); - namelen = strlen(name); - } else { - dprintf(("ntfs_ntvattrget: " \ - "ino: %ju, type: 0x%x, vcn: %d\n", \ - (uintmax_t)ip->i_number, type, (uint32_t)vcn)); - name = ""; - namelen = 0; - } - - error = ntfs_findvattr(ntmp, ip, &lvap, vapp, type, name, namelen, vcn); - if (error >= 0) - return (error); - - if (!lvap) { - dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \ - "ino: %ju, type: 0x%x, name: %s, vcn: %d\n", \ - (uintmax_t)ip->i_number, type, name, (uint32_t)vcn)); - return (ENOENT); - } - /* Scan $ATTRIBUTE_LIST for requested attribute */ - len = lvap->va_datalen; - alpool = malloc(len, M_TEMP, M_WAITOK); - error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len, - NULL); - if (error) - goto out; - - aalp = (struct attr_attrlist *) alpool; - nextaalp = NULL; - - for(; len > 0; aalp = nextaalp) { - dprintf(("ntfs_ntvattrget: " \ - "attrlist: ino: %ju, attr: 0x%x, vcn: %d\n", \ - (uintmax_t)aalp->al_inumber, aalp->al_type, \ - (uint32_t)aalp->al_vcnstart)); - - if (len > aalp->reclen) { - nextaalp = NTFS_NEXTREC(aalp, struct attr_attrlist *); - } else { - nextaalp = NULL; - } - len -= aalp->reclen; - - if (!NTFS_AALPCMP(aalp, type, name, namelen) || - (nextaalp && (nextaalp->al_vcnstart <= vcn) && - NTFS_AALPCMP(nextaalp, type, name, namelen))) - continue; - - dprintf(("ntfs_ntvattrget: attribute in ino: %ju\n", - (uintmax_t)aalp->al_inumber)); - - /* this is not a main record, so we can't use just plain - vget() */ - error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber, - NTFS_A_DATA, NULL, LK_EXCLUSIVE, - VG_EXT, curthread, &newvp); - if (error) { - printf("ntfs_ntvattrget: CAN'T VGET INO: %ju\n", - (uintmax_t)aalp->al_inumber); - goto out; - } - newip = VTONT(newvp); - /* XXX have to lock ntnode */ - error = ntfs_findvattr(ntmp, newip, &lvap, vapp, - type, name, namelen, vcn); - vput(newvp); - if (error == 0) - goto out; - printf("ntfs_ntvattrget: ATTRLIST ERROR.\n"); - break; - } - error = ENOENT; - - dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \ - "ino: %ju, type: 0x%x, name: %.*s, vcn: %d\n", \ - (uintmax_t)ip->i_number, type, (int)namelen, name, (uint32_t)vcn)); -out: - free(alpool, M_TEMP); - return (error); -} - -/* - * Read ntnode from disk, make ntvattr list. - * - * ntnode should be locked - */ -int -ntfs_loadntnode( - struct ntfsmount * ntmp, - struct ntnode * ip) -{ - struct filerec *mfrp; - daddr_t bn; - int error,off; - struct attr *ap; - struct ntvattr *nvap; - - dprintf(("ntfs_loadntnode: loading ino: %ju\n", - (uintmax_t)ip->i_number)); - - mfrp = malloc(ntfs_bntob(ntmp->ntm_bpmftrec), - M_TEMP, M_WAITOK); - - if (ip->i_number < NTFS_SYSNODESNUM) { - struct buf *bp; - - dprintf(("ntfs_loadntnode: read system node\n")); - - bn = ntfs_cntobn(ntmp->ntm_mftcn) + - ntmp->ntm_bpmftrec * ip->i_number; - bn *= ntmp->ntm_multiplier; - - error = bread(ntmp->ntm_devvp, - bn, ntfs_bntob(ntmp->ntm_bpmftrec), - NOCRED, &bp); - if (error) { - printf("ntfs_loadntnode: BREAD FAILED\n"); - brelse(bp); - goto out; - } - memcpy(mfrp, bp->b_data, ntfs_bntob(ntmp->ntm_bpmftrec)); - bqrelse(bp); - } else { - struct vnode *vp; - - vp = ntmp->ntm_sysvn[NTFS_MFTINO]; - error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, - ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec), - ntfs_bntob(ntmp->ntm_bpmftrec), mfrp, NULL); - if (error) { - printf("ntfs_loadntnode: ntfs_readattr failed\n"); - goto out; - } - } - - /* Check if magic and fixups are correct */ - error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp, - ntfs_bntob(ntmp->ntm_bpmftrec)); - if (error) { - printf("ntfs_loadntnode: BAD MFT RECORD %ju\n", - (uintmax_t)ip->i_number); - goto out; - } - - dprintf(("ntfs_loadntnode: load attrs for ino: %ju\n", - (uintmax_t)ip->i_number)); - off = mfrp->fr_attroff; - ap = (struct attr *) ((caddr_t)mfrp + off); - - LIST_INIT(&ip->i_valist); - - while (ap->a_hdr.a_type != -1) { - error = ntfs_attrtontvattr(ntmp, &nvap, ap); - if (error) - break; - nvap->va_ip = ip; - - LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list); - - off += ap->a_hdr.reclen; - ap = (struct attr *) ((caddr_t)mfrp + off); - } - if (error) { - printf("ntfs_loadntnode: failed to load attr ino: %ju\n", - (uintmax_t)ip->i_number); - goto out; - } - - ip->i_mainrec = mfrp->fr_mainrec; - ip->i_nlink = mfrp->fr_nlink; - ip->i_frflag = mfrp->fr_flags; - - ip->i_flag |= IN_LOADED; - -out: - free(mfrp, M_TEMP); - return (error); -} - -/* - * Routine locks ntnode and increase usecount, just opposite of - * ntfs_ntput(). - */ -int -ntfs_ntget(ip) - struct ntnode *ip; -{ - dprintf(("ntfs_ntget: get ntnode %ju: %p, usecount: %d\n", - (uintmax_t)ip->i_number, ip, ip->i_usecount)); - - mtx_lock(&ip->i_interlock); - ip->i_usecount++; - lockmgr(&ip->i_lock, LK_EXCLUSIVE | LK_INTERLOCK, &ip->i_interlock); - - return 0; -} - -/* - * Routine search ntnode in hash, if found: lock, inc usecount and return. - * If not in hash allocate structure for ntnode, prefill it, lock, - * inc count and return. - * - * ntnode returned locked - */ -int -ntfs_ntlookup( - struct ntfsmount * ntmp, - ino_t ino, - struct ntnode ** ipp) -{ - struct ntnode *ip; - - dprintf(("ntfs_ntlookup: looking for ntnode %d\n", ino)); - - do { - ip = ntfs_nthashlookup(ntmp->ntm_devvp->v_rdev, ino); - if (ip != NULL) { - ntfs_ntget(ip); - dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", - ino, ip, ip->i_usecount)); - *ipp = ip; - return (0); - } - } while (lockmgr(&ntfs_hashlock, LK_EXCLUSIVE | LK_SLEEPFAIL, NULL)); - - ip = malloc(sizeof(struct ntnode), M_NTFSNTNODE, - M_WAITOK | M_ZERO); - ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip)); - - /* Generic initialization */ - ip->i_devvp = ntmp->ntm_devvp; - ip->i_dev = ntmp->ntm_devvp->v_rdev; - ip->i_number = ino; - ip->i_mp = ntmp; - - LIST_INIT(&ip->i_fnlist); - VREF(ip->i_devvp); - - /* init lock and lock the newborn ntnode */ - lockinit(&ip->i_lock, PINOD, "ntnode", 0, 0); - mtx_init(&ip->i_interlock, "ntnode interlock", NULL, MTX_DEF); - ntfs_ntget(ip); - - ntfs_nthashins(ip); - - lockmgr(&ntfs_hashlock, LK_RELEASE, NULL); - - *ipp = ip; - - dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", - ino, ip, ip->i_usecount)); - - return (0); -} - -/* - * Decrement usecount of ntnode and unlock it, if usecount reach zero, - * deallocate ntnode. - * - * ntnode should be locked on entry, and unlocked on return. - */ -void -ntfs_ntput(ip) - struct ntnode *ip; -{ - struct ntvattr *vap; - - dprintf(("ntfs_ntput: rele ntnode %ju: %p, usecount: %d\n", - (uintmax_t)ip->i_number, ip, ip->i_usecount)); - - mtx_lock(&ip->i_interlock); - ip->i_usecount--; - -#ifdef DIAGNOSTIC - if (ip->i_usecount < 0) { - panic("ntfs_ntput: ino: %ju usecount: %d \n", - (uintmax_t)ip->i_number, ip->i_usecount); - } -#endif - - if (ip->i_usecount > 0) { - lockmgr(&ip->i_lock, LK_RELEASE|LK_INTERLOCK, &ip->i_interlock); - return; - } - - dprintf(("ntfs_ntput: deallocating ntnode: %ju\n", - (uintmax_t)ip->i_number)); - - if (LIST_FIRST(&ip->i_fnlist)) - panic("ntfs_ntput: ntnode has fnodes\n"); - - ntfs_nthashrem(ip); - - while ((vap = LIST_FIRST(&ip->i_valist)) != NULL) { - LIST_REMOVE(vap,va_list); - ntfs_freentvattr(vap); - } - lockmgr(&ip->i_lock, LK_RELEASE | LK_INTERLOCK, &ip->i_interlock); - mtx_destroy(&ip->i_interlock); - lockdestroy(&ip->i_lock); - vrele(ip->i_devvp); - free(ip, M_NTFSNTNODE); -} - -/* - * increment usecount of ntnode - */ -void -ntfs_ntref(ip) - struct ntnode *ip; -{ - mtx_lock(&ip->i_interlock); - ip->i_usecount++; - mtx_unlock(&ip->i_interlock); - - dprintf(("ntfs_ntref: ino %ju, usecount: %d\n", - (uintmax_t)ip->i_number, ip->i_usecount)); -} - -/* - * Decrement usecount of ntnode. - */ -void -ntfs_ntrele(ip) - struct ntnode *ip; -{ - dprintf(("ntfs_ntrele: rele ntnode %ju: %p, usecount: %d\n", - (uintmax_t)ip->i_number, ip, ip->i_usecount)); - - mtx_lock(&ip->i_interlock); - ip->i_usecount--; - - if (ip->i_usecount < 0) - panic("ntfs_ntrele: ino: %ju usecount: %d \n", - (uintmax_t)ip->i_number, ip->i_usecount); - mtx_unlock(&ip->i_interlock); -} - -/* - * Deallocate all memory allocated for ntvattr - */ -void -ntfs_freentvattr(vap) - struct ntvattr * vap; -{ - if (vap->va_flag & NTFS_AF_INRUN) { - if (vap->va_vruncn) - free(vap->va_vruncn, M_NTFSRUN); - if (vap->va_vruncl) - free(vap->va_vruncl, M_NTFSRUN); - } else { - if (vap->va_datap) - free(vap->va_datap, M_NTFSRDATA); - } - free(vap, M_NTFSNTVATTR); -} - -/* - * Convert disk image of attribute into ntvattr structure, - * runs are expanded also. - */ -int -ntfs_attrtontvattr( - struct ntfsmount * ntmp, - struct ntvattr ** rvapp, - struct attr * rap) -{ - int error, i; - struct ntvattr *vap; - - error = 0; - *rvapp = NULL; - - vap = malloc(sizeof(struct ntvattr), - M_NTFSNTVATTR, M_WAITOK | M_ZERO); - vap->va_ip = NULL; - vap->va_flag = rap->a_hdr.a_flag; - vap->va_type = rap->a_hdr.a_type; - vap->va_compression = rap->a_hdr.a_compression; - vap->va_index = rap->a_hdr.a_index; - - ddprintf(("type: 0x%x, index: %d", vap->va_type, vap->va_index)); - - vap->va_namelen = rap->a_hdr.a_namelen; - if (rap->a_hdr.a_namelen) { - wchar *unp = (wchar *) ((caddr_t) rap + rap->a_hdr.a_nameoff); - ddprintf((", name:[")); - for (i = 0; i < vap->va_namelen; i++) { - vap->va_name[i] = unp[i]; - ddprintf(("%c", vap->va_name[i])); - } - ddprintf(("]")); - } - if (vap->va_flag & NTFS_AF_INRUN) { - ddprintf((", nonres.")); - vap->va_datalen = rap->a_nr.a_datalen; - vap->va_allocated = rap->a_nr.a_allocated; - vap->va_vcnstart = rap->a_nr.a_vcnstart; - vap->va_vcnend = rap->a_nr.a_vcnend; - vap->va_compressalg = rap->a_nr.a_compressalg; - error = ntfs_runtovrun(&(vap->va_vruncn), &(vap->va_vruncl), - &(vap->va_vruncnt), - (caddr_t) rap + rap->a_nr.a_dataoff); - } else { - vap->va_compressalg = 0; - ddprintf((", res.")); - vap->va_datalen = rap->a_r.a_datalen; - vap->va_allocated = rap->a_r.a_datalen; - vap->va_vcnstart = 0; - vap->va_vcnend = ntfs_btocn(vap->va_allocated); - vap->va_datap = malloc(vap->va_datalen, - M_NTFSRDATA, M_WAITOK); - memcpy(vap->va_datap, (caddr_t) rap + rap->a_r.a_dataoff, - rap->a_r.a_datalen); - } - ddprintf((", len: %lld", vap->va_datalen)); - - if (error) - free(vap, M_NTFSNTVATTR); - else - *rvapp = vap; - - ddprintf(("\n")); - - return (error); -} - -/* - * Expand run into more utilizable and more memory eating format. - */ -int -ntfs_runtovrun( - cn_t ** rcnp, - cn_t ** rclp, - u_long * rcntp, - u_int8_t * run) -{ - u_int32_t off; - u_int32_t sz, i; - cn_t *cn; - cn_t *cl; - u_long cnt; - cn_t prev; - cn_t tmp; - - off = 0; - cnt = 0; - i = 0; - while (run[off]) { - off += (run[off] & 0xF) + ((run[off] >> 4) & 0xF) + 1; - cnt++; - } - cn = malloc(cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK); - cl = malloc(cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK); - - off = 0; - cnt = 0; - prev = 0; - while (run[off]) { - - sz = run[off++]; - cl[cnt] = 0; - - for (i = 0; i < (sz & 0xF); i++) - cl[cnt] += (u_int32_t) run[off++] << (i << 3); - - sz >>= 4; - if (run[off + sz - 1] & 0x80) { - tmp = ((u_int64_t) - 1) << (sz << 3); - for (i = 0; i < sz; i++) - tmp |= (u_int64_t) run[off++] << (i << 3); - } else { - tmp = 0; - for (i = 0; i < sz; i++) - tmp |= (u_int64_t) run[off++] << (i << 3); - } - if (tmp) - prev = cn[cnt] = prev + tmp; - else - cn[cnt] = tmp; - - cnt++; - } - *rcnp = cn; - *rclp = cl; - *rcntp = cnt; - return (0); -} - -/* - * Compare unicode and ascii string case insens. - */ -static int -ntfs_uastricmp(ntmp, ustr, ustrlen, astr, astrlen) - struct ntfsmount *ntmp; - const wchar *ustr; - size_t ustrlen; - const char *astr; - size_t astrlen; -{ - const char *astrp = astr; - char tmpbuf[5]; - int len, res; - size_t i, j, mbstrlen = astrlen; - - if (ntmp->ntm_ic_l2u) { - for (i = 0, j = 0; i < ustrlen && j < astrlen; i++) { - len = 4; - res = ((int) NTFS_TOUPPER(ustr[i])) - - ((int)NTFS_TOUPPER(NTFS_82U(astrp, &len))); - astrp += len; - j += len; - mbstrlen -= len - 1; - - if (res) - return res; - } - } else { - /* - * We use NTFS_82U(NTFS_U28(c)) to get rid of unicode - * symbols not covered by translation table - */ - for (i = 0; i < ustrlen && i < astrlen; i++) { - res = ((int) NTFS_TOUPPER(NTFS_82U(NTFS_U28(ustr[i]), &len))) - - ((int)NTFS_TOUPPER(NTFS_82U(astrp, &len))); - astrp++; - if (res) - return res; - } - } - return (ustrlen - mbstrlen); -} - -/* - * Compare unicode and ascii string case sens. - */ -static int -ntfs_uastrcmp(ntmp, ustr, ustrlen, astr, astrlen) - struct ntfsmount *ntmp; - const wchar *ustr; - size_t ustrlen; - const char *astr; - size_t astrlen; -{ - char *c, tmpbuf[5]; - size_t i, j, mbstrlen = astrlen; - int res; - - for (i = 0, j = 0; (i < ustrlen) && (j < astrlen); i++, mbstrlen++) { - c = NTFS_U28(ustr[i]); - while (*c != '\0') { - res = (int) (*c++ - astr[j++]); - if (res) - return res; - mbstrlen--; - } - } - return (ustrlen - mbstrlen); -} - -/* - * Search fnode in ntnode, if not found allocate and preinitialize. - * - * ntnode should be locked on entry. - */ -int -ntfs_fget( - struct ntfsmount *ntmp, - struct ntnode *ip, - int attrtype, - char *attrname, - struct fnode **fpp) -{ - struct fnode *fp; - - dprintf(("ntfs_fget: ino: %ju, attrtype: 0x%x, attrname: %s\n", - (uintmax_t)ip->i_number, attrtype, attrname ? attrname : "")); - *fpp = NULL; - LIST_FOREACH(fp, &ip->i_fnlist, f_fnlist){ - dprintf(("ntfs_fget: fnode: attrtype: %d, attrname: %s\n", - fp->f_attrtype, fp->f_attrname?fp->f_attrname:"")); - - if ((attrtype == fp->f_attrtype) && - ((!attrname && !fp->f_attrname) || - (attrname && fp->f_attrname && - !strcmp(attrname,fp->f_attrname)))){ - dprintf(("ntfs_fget: found existed: %p\n",fp)); - *fpp = fp; - } - } - - if (*fpp) - return (0); - - fp = malloc(sizeof(struct fnode), M_NTFSFNODE, - M_WAITOK | M_ZERO); - dprintf(("ntfs_fget: allocating fnode: %p\n",fp)); - - fp->f_ip = ip; - if (attrname) { - fp->f_flag |= FN_AATTRNAME; - fp->f_attrname = malloc(strlen(attrname)+1, M_TEMP, M_WAITOK); - strcpy(fp->f_attrname, attrname); - } else - fp->f_attrname = NULL; - fp->f_attrtype = attrtype; - - ntfs_ntref(ip); - - LIST_INSERT_HEAD(&ip->i_fnlist, fp, f_fnlist); - - *fpp = fp; - - return (0); -} - -/* - * Deallocate fnode, remove it from ntnode's fnode list. - * - * ntnode should be locked. - */ -void -ntfs_frele( - struct fnode *fp) -{ - struct ntnode *ip = FTONT(fp); - - dprintf(("ntfs_frele: fnode: %p for %ju: %p\n", - fp, (uintmax_t)ip->i_number, ip)); - - dprintf(("ntfs_frele: deallocating fnode\n")); - LIST_REMOVE(fp,f_fnlist); - if (fp->f_flag & FN_AATTRNAME) - free(fp->f_attrname, M_TEMP); - if (fp->f_dirblbuf) - free(fp->f_dirblbuf, M_NTFSDIR); - free(fp, M_NTFSFNODE); - ntfs_ntrele(ip); -} - -/* - * Lookup attribute name in format: [[:$ATTR_TYPE]:$ATTR_NAME], - * $ATTR_TYPE is searched in attrdefs read from $AttrDefs. - * If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed. - */ -static int -ntfs_ntlookupattr( - struct ntfsmount * ntmp, - const char * name, - int namelen, - int *attrtype, - char **attrname) -{ - const char *sys; - size_t syslen, i; - struct ntvattrdef *adp; - - if (namelen == 0) - return (0); - - if (name[0] == '$') { - sys = name; - for (syslen = 0; syslen < namelen; syslen++) { - if(sys[syslen] == ':') { - name++; - namelen--; - break; - } - } - name += syslen; - namelen -= syslen; - - adp = ntmp->ntm_ad; - for (i = 0; i < ntmp->ntm_adnum; i++, adp++){ - if (syslen != adp->ad_namelen || - strncmp(sys, adp->ad_name, syslen) != 0) - continue; - - *attrtype = adp->ad_type; - goto out; - } - return (ENOENT); - } else - *attrtype = NTFS_A_DATA; - - out: - if (namelen) { - (*attrname) = malloc(namelen, M_TEMP, M_WAITOK); - memcpy((*attrname), name, namelen); - (*attrname)[namelen] = '\0'; - } - - return (0); -} - -/* - * Lookup specifed node for filename, matching cnp, - * return fnode filled. - */ -int -ntfs_ntlookupfile( - struct ntfsmount * ntmp, - struct vnode * vp, - struct componentname * cnp, - struct vnode ** vpp) -{ - struct fnode *fp = VTOF(vp); - struct ntnode *ip = FTONT(fp); - struct ntvattr *vap; /* Root attribute */ - cn_t cn; /* VCN in current attribute */ - caddr_t rdbuf; /* Buffer to read directory's blocks */ - u_int32_t blsize; - u_int64_t rdsize; /* Length of data to read from current block */ - struct attr_indexentry *iep; - int error, res, anamelen, fnamelen; - const char *fname,*aname; - u_int32_t aoff; - int attrtype = NTFS_A_DATA; - char *attrname = NULL; - struct fnode *nfp; - struct vnode *nvp; - enum vtype f_type; - - error = ntfs_ntget(ip); - if (error) - return (error); - - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); - if (error || (vap->va_flag & NTFS_AF_INRUN)) - return (ENOTDIR); - - blsize = vap->va_a_iroot->ir_size; - rdsize = vap->va_datalen; - - /* - * Divide file name into: foofilefoofilefoofile[:attrspec] - * Store like this: fname:fnamelen [aname:anamelen] - */ - fname = cnp->cn_nameptr; - aname = NULL; - anamelen = 0; - for (fnamelen = 0; fnamelen < cnp->cn_namelen; fnamelen++) - if(fname[fnamelen] == ':') { - aname = fname + fnamelen + 1; - anamelen = cnp->cn_namelen - fnamelen - 1; - dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n", - fname, fnamelen, aname, anamelen)); - break; - } - - dprintf(("ntfs_ntlookupfile: blksz: %d, rdsz: %jd\n", blsize, rdsize)); - - rdbuf = malloc(blsize, M_TEMP, M_WAITOK); - - error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30", - 0, rdsize, rdbuf, NULL); - if (error) - goto fail; - - aoff = sizeof(struct attr_indexroot); - - do { - iep = (struct attr_indexentry *) (rdbuf + aoff); - - for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff); - aoff += iep->reclen, - iep = (struct attr_indexentry *) (rdbuf + aoff)) - { - ddprintf(("scan: %d, %d\n", - (u_int32_t) iep->ie_number, - (u_int32_t) iep->ie_fnametype)); - - /* check the name - the case-insensitible check - * has to come first, to break from this for loop - * if needed, so we can dive correctly */ - res = NTFS_UASTRICMP(iep->ie_fname, iep->ie_fnamelen, - fname, fnamelen); - if (res > 0) break; - if (res < 0) continue; - - if (iep->ie_fnametype == 0 || - !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS)) - { - res = NTFS_UASTRCMP(iep->ie_fname, - iep->ie_fnamelen, fname, fnamelen); - if (res != 0) continue; - } - - if (aname) { - error = ntfs_ntlookupattr(ntmp, - aname, anamelen, - &attrtype, &attrname); - if (error) - goto fail; - } - - /* Check if we've found ourself */ - if ((iep->ie_number == ip->i_number) && - (attrtype == fp->f_attrtype) && - ((!attrname && !fp->f_attrname) || - (attrname && fp->f_attrname && - !strcmp(attrname, fp->f_attrname)))) - { - VREF(vp); - *vpp = vp; - error = 0; - goto fail; - } - - /* vget node, but don't load it */ - error = ntfs_vgetex(ntmp->ntm_mountp, - iep->ie_number, attrtype, attrname, - LK_EXCLUSIVE, VG_DONTLOADIN | VG_DONTVALIDFN, - curthread, &nvp); - - /* free the buffer returned by ntfs_ntlookupattr() */ - if (attrname) { - free(attrname, M_TEMP); - attrname = NULL; - } - - if (error) - goto fail; - - nfp = VTOF(nvp); - - if (nfp->f_flag & FN_VALID) { - *vpp = nvp; - goto fail; - } - - nfp->f_fflag = iep->ie_fflag; - nfp->f_pnumber = iep->ie_fpnumber; - nfp->f_times = iep->ie_ftimes; - - if((nfp->f_fflag & NTFS_FFLAG_DIR) && - (nfp->f_attrtype == NTFS_A_DATA) && - (nfp->f_attrname == NULL)) - f_type = VDIR; - else - f_type = VREG; - - nvp->v_type = f_type; - - if ((nfp->f_attrtype == NTFS_A_DATA) && - (nfp->f_attrname == NULL)) - { - /* Opening default attribute */ - nfp->f_size = iep->ie_fsize; - nfp->f_allocated = iep->ie_fallocated; - nfp->f_flag |= FN_PRELOADED; - } else { - error = ntfs_filesize(ntmp, nfp, - &nfp->f_size, &nfp->f_allocated); - if (error) { - vput(nvp); - goto fail; - } - } - - nfp->f_flag &= ~FN_VALID; - *vpp = nvp; - goto fail; - } - - /* Dive if possible */ - if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) { - dprintf(("ntfs_ntlookupfile: diving\n")); - - cn = *(cn_t *) (rdbuf + aoff + - iep->reclen - sizeof(cn_t)); - rdsize = blsize; - - error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30", - ntfs_cntob(cn), rdsize, rdbuf, NULL); - if (error) - goto fail; - - error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC, - rdbuf, rdsize); - if (error) - goto fail; - - aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize + - 0x18); - } else { - dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n")); - error = ENOENT; - break; - } - } while (1); - - dprintf(("finish\n")); - -fail: - if (attrname) free(attrname, M_TEMP); - ntfs_ntvattrrele(vap); - ntfs_ntput(ip); - free(rdbuf, M_TEMP); - return (error); -} - -/* - * Check if name type is permitted to show. - */ -int -ntfs_isnamepermitted( - struct ntfsmount * ntmp, - struct attr_indexentry * iep) -{ - if (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES) - return 1; - - switch (iep->ie_fnametype) { - case 2: - ddprintf(("ntfs_isnamepermitted: skipped DOS name\n")); - return 0; - case 0: case 1: case 3: - return 1; - default: - printf("ntfs_isnamepermitted: " \ - "WARNING! Unknown file name type: %d\n", - iep->ie_fnametype); - break; - } - return 0; -} - -/* - * Read ntfs dir like stream of attr_indexentry, not like btree of them. - * This is done by scaning $BITMAP:$I30 for busy clusters and reading them. - * Ofcouse $INDEX_ROOT:$I30 is read before. Last read values are stored in - * fnode, so we can skip toward record number num almost immediatly. - * Anyway this is rather slow routine. The problem is that we don't know - * how many records are there in $INDEX_ALLOCATION:$I30 block. - */ -int -ntfs_ntreaddir( - struct ntfsmount * ntmp, - struct fnode * fp, - u_int32_t num, - struct attr_indexentry ** riepp) -{ - struct ntnode *ip = FTONT(fp); - struct ntvattr *vap = NULL; /* IndexRoot attribute */ - struct ntvattr *bmvap = NULL; /* BitMap attribute */ - struct ntvattr *iavap = NULL; /* IndexAllocation attribute */ - caddr_t rdbuf; /* Buffer to read directory's blocks */ - u_int8_t *bmp = NULL; /* Bitmap */ - u_int32_t blsize; /* Index allocation size (2048) */ - u_int32_t rdsize; /* Length of data to read */ - u_int32_t attrnum; /* Current attribute type */ - u_int32_t cpbl = 1; /* Clusters per directory block */ - u_int32_t blnum; - struct attr_indexentry *iep; - int error = ENOENT; - u_int32_t aoff, cnum; - - dprintf(("ntfs_ntreaddir: read ino: %ju, num: %d\n", - (uintmax_t)ip->i_number, num)); - error = ntfs_ntget(ip); - if (error) - return (error); - - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); - if (error) - return (ENOTDIR); - - if (fp->f_dirblbuf == NULL) { - fp->f_dirblsz = vap->va_a_iroot->ir_size; - fp->f_dirblbuf = malloc(max(vap->va_datalen,fp->f_dirblsz), - M_NTFSDIR, M_WAITOK); - } - - blsize = fp->f_dirblsz; - rdbuf = fp->f_dirblbuf; - - dprintf(("ntfs_ntreaddir: rdbuf: %p, blsize: %d\n", rdbuf, blsize)); - - if (vap->va_a_iroot->ir_flag & NTFS_IRFLAG_INDXALLOC) { - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", - 0, &bmvap); - if (error) { - error = ENOTDIR; - goto fail; - } - bmp = malloc(bmvap->va_datalen, M_TEMP, M_WAITOK); - error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0, - bmvap->va_datalen, bmp, NULL); - if (error) - goto fail; - - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDX, "$I30", - 0, &iavap); - if (error) { - error = ENOTDIR; - goto fail; - } - cpbl = ntfs_btocn(blsize + ntfs_cntob(1) - 1); - dprintf(("ntfs_ntreaddir: indexalloc: %jd, cpbl: %d\n", - iavap->va_datalen, cpbl)); - } else { - dprintf(("ntfs_ntreadidir: w/o BitMap and IndexAllocation\n")); - iavap = bmvap = NULL; - bmp = NULL; - } - - /* Try use previous values */ - if ((fp->f_lastdnum < num) && (fp->f_lastdnum != 0)) { - attrnum = fp->f_lastdattr; - aoff = fp->f_lastdoff; - blnum = fp->f_lastdblnum; - cnum = fp->f_lastdnum; - } else { - attrnum = NTFS_A_INDXROOT; - aoff = sizeof(struct attr_indexroot); - blnum = 0; - cnum = 0; - } - - do { - dprintf(("ntfs_ntreaddir: scan: 0x%x, %d, %d, %d, %d\n", - attrnum, (u_int32_t) blnum, cnum, num, aoff)); - rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize; - error = ntfs_readattr(ntmp, ip, attrnum, "$I30", - ntfs_cntob(blnum * cpbl), rdsize, rdbuf, NULL); - if (error) - goto fail; - - if (attrnum == NTFS_A_INDX) { - error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC, - rdbuf, rdsize); - if (error) - goto fail; - } - if (aoff == 0) - aoff = (attrnum == NTFS_A_INDX) ? - (0x18 + ((struct attr_indexalloc *) rdbuf)->ia_hdrsize) : - sizeof(struct attr_indexroot); - - iep = (struct attr_indexentry *) (rdbuf + aoff); - for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff); - aoff += iep->reclen, - iep = (struct attr_indexentry *) (rdbuf + aoff)) - { - if (!ntfs_isnamepermitted(ntmp, iep)) continue; - - if (cnum >= num) { - fp->f_lastdnum = cnum; - fp->f_lastdoff = aoff; - fp->f_lastdblnum = blnum; - fp->f_lastdattr = attrnum; - - *riepp = iep; - - error = 0; - goto fail; - } - cnum++; - } - - if (iavap) { - if (attrnum == NTFS_A_INDXROOT) - blnum = 0; - else - blnum++; - - while (ntfs_cntob(blnum * cpbl) < iavap->va_datalen) { - if (bmp[blnum >> 3] & (1 << (blnum & 7))) - break; - blnum++; - } - - attrnum = NTFS_A_INDX; - aoff = 0; - if (ntfs_cntob(blnum * cpbl) >= iavap->va_datalen) - break; - dprintf(("ntfs_ntreaddir: blnum: %d\n", (u_int32_t) blnum)); - } - } while (iavap); - - *riepp = NULL; - fp->f_lastdnum = 0; - -fail: - if (vap) - ntfs_ntvattrrele(vap); - if (bmvap) - ntfs_ntvattrrele(bmvap); - if (iavap) - ntfs_ntvattrrele(iavap); - if (bmp) - free(bmp, M_TEMP); - ntfs_ntput(ip); - return (error); -} - -/* - * Convert NTFS times that are in 100 ns units and begins from - * 1601 Jan 1 into unix times. - */ -struct timespec -ntfs_nttimetounix( - u_int64_t nt) -{ - struct timespec t; - - /* WindowNT times are in 100 ns and from 1601 Jan 1 */ - t.tv_nsec = (nt % (1000 * 1000 * 10)) * 100; - t.tv_sec = nt / (1000 * 1000 * 10) - - 369LL * 365LL * 24LL * 60LL * 60LL - - 89LL * 1LL * 24LL * 60LL * 60LL; - return (t); -} - -/* - * Get file times from NTFS_A_NAME attribute. - */ -int -ntfs_times( - struct ntfsmount * ntmp, - struct ntnode * ip, - ntfs_times_t * tm) -{ - struct ntvattr *vap; - int error; - - dprintf(("ntfs_times: ino: %ju...\n", (uintmax_t)ip->i_number)); - - error = ntfs_ntget(ip); - if (error) - return (error); - - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap); - if (error) { - ntfs_ntput(ip); - return (error); - } - *tm = vap->va_a_name->n_times; - ntfs_ntvattrrele(vap); - ntfs_ntput(ip); - - return (0); -} - -/* - * Get file sizes from corresponding attribute. - * - * ntnode under fnode should be locked. - */ -int -ntfs_filesize( - struct ntfsmount * ntmp, - struct fnode * fp, - u_int64_t * size, - u_int64_t * bytes) -{ - struct ntvattr *vap; - struct ntnode *ip = FTONT(fp); - u_int64_t sz, bn; - int error; - - dprintf(("ntfs_filesize: ino: %ju\n", (uintmax_t)ip->i_number)); - - error = ntfs_ntvattrget(ntmp, ip, - fp->f_attrtype, fp->f_attrname, 0, &vap); - if (error) - return (error); - - bn = vap->va_allocated; - sz = vap->va_datalen; - - dprintf(("ntfs_filesize: %d bytes (%d bytes allocated)\n", - (u_int32_t) sz, (u_int32_t) bn)); - - if (size) - *size = sz; - if (bytes) - *bytes = bn; - - ntfs_ntvattrrele(vap); - - return (0); -} - -/* - * This is one of read routines. - * - * ntnode should be locked. - */ -int -ntfs_readntvattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - struct ntvattr * vap, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp, - struct uio *uio) -{ - int error = 0; - off_t off; - - *initp = 0; - if (vap->va_flag & NTFS_AF_INRUN) { - int cnt; - cn_t ccn, ccl, cn, left, cl; - caddr_t data = rdata; - struct buf *bp; - size_t tocopy; - - ddprintf(("ntfs_readntvattr_plain: data in run: %ld chains\n", - vap->va_vruncnt)); - - off = roff; - left = rsize; - ccl = 0; - ccn = 0; - cnt = 0; - while (left && (cnt < vap->va_vruncnt)) { - ccn = vap->va_vruncn[cnt]; - ccl = vap->va_vruncl[cnt]; - - ddprintf(("ntfs_readntvattr_plain: " \ - "left %d, cn: 0x%x, cl: %d, off: %d\n", \ - (u_int32_t) left, (u_int32_t) ccn, \ - (u_int32_t) ccl, (u_int32_t) off)); - - if (ntfs_cntob(ccl) < off) { - off -= ntfs_cntob(ccl); - cnt++; - continue; - } - if (ccn || ip->i_number == NTFS_BOOTINO) { - ccl -= ntfs_btocn(off); - cn = ccn + ntfs_btocn(off); - off = ntfs_btocnoff(off); - - while (left && ccl) { - /* - * Always read single clusters at a - * time - we need to avoid reading - * differently-sized blocks at the - * same disk offsets to avoid - * confusing the buffer cache. - */ - tocopy = MIN(left, - ntfs_cntob(1) - off); - cl = ntfs_btocl(tocopy + off); - KASSERT(cl == 1 && - tocopy <= ntfs_cntob(1), - ("single cluster limit mistake")); - - ddprintf(("ntfs_readntvattr_plain: " \ - "read: cn: 0x%x cl: %d, " \ - "off: %d len: %d, left: %d\n", - (u_int32_t) cn, - (u_int32_t) cl, - (u_int32_t) off, - (u_int32_t) tocopy, - (u_int32_t) left)); - error = bread(ntmp->ntm_devvp, - ntfs_cntobn(cn) - * ntmp->ntm_multiplier, - ntfs_cntob(cl), - NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - if (uio) { - uiomove(bp->b_data + off, - tocopy, uio); - } else { - memcpy(data, bp->b_data + off, - tocopy); - } - brelse(bp); - data = data + tocopy; - *initp += tocopy; - off = 0; - left -= tocopy; - cn += cl; - ccl -= cl; - } - } else { - tocopy = MIN(left, ntfs_cntob(ccl) - off); - ddprintf(("ntfs_readntvattr_plain: " - "hole: ccn: 0x%x ccl: %d, off: %d, " \ - " len: %d, left: %d\n", - (u_int32_t) ccn, (u_int32_t) ccl, - (u_int32_t) off, (u_int32_t) tocopy, - (u_int32_t) left)); - left -= tocopy; - off = 0; - if (uio) { - size_t remains = tocopy; - for(; remains; remains--) - uiomove("", 1, uio); - } else - memset(data, 0, tocopy); - data = data + tocopy; - } - cnt++; - } - if (left) { - printf("ntfs_readntvattr_plain: POSSIBLE RUN ERROR\n"); - error = E2BIG; - } - } else { - ddprintf(("ntfs_readnvattr_plain: data is in mft record\n")); - if (uio) - uiomove(vap->va_datap + roff, rsize, uio); - else - memcpy(rdata, vap->va_datap + roff, rsize); - *initp += rsize; - } - - return (error); -} - -/* - * This is one of read routines. - */ -int -ntfs_readattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t attrnum, - char *attrname, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp, - struct uio *uio) -{ - size_t init; - int error = 0; - off_t off = roff, left = rsize, toread; - caddr_t data = rdata; - struct ntvattr *vap; - *initp = 0; - - while (left) { - error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, - ntfs_btocn(off), &vap); - if (error) - return (error); - toread = MIN(left, ntfs_cntob(vap->va_vcnend + 1) - off); - ddprintf(("ntfs_readattr_plain: o: %d, s: %d (%d - %d)\n", - (u_int32_t) off, (u_int32_t) toread, - (u_int32_t) vap->va_vcnstart, - (u_int32_t) vap->va_vcnend)); - error = ntfs_readntvattr_plain(ntmp, ip, vap, - off - ntfs_cntob(vap->va_vcnstart), - toread, data, &init, uio); - if (error) { - printf("ntfs_readattr_plain: " \ - "ntfs_readntvattr_plain failed: o: %d, s: %d\n", - (u_int32_t) off, (u_int32_t) toread); - printf("ntfs_readattr_plain: attrib: %d - %d\n", - (u_int32_t) vap->va_vcnstart, - (u_int32_t) vap->va_vcnend); - ntfs_ntvattrrele(vap); - break; - } - ntfs_ntvattrrele(vap); - left -= toread; - off += toread; - data = data + toread; - *initp += init; - } - - return (error); -} - -/* - * This is one of read routines. - */ -int -ntfs_readattr( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t attrnum, - char *attrname, - off_t roff, - size_t rsize, - void *rdata, - struct uio *uio) -{ - int error = 0; - struct ntvattr *vap; - size_t init; - - ddprintf(("ntfs_readattr: reading %ju: 0x%x, from %jd size %zu bytes\n", - (uintmax_t)ip->i_number, attrnum, (intmax_t)roff, rsize)); - - error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 0, &vap); - if (error) - return (error); - - if ((roff > vap->va_datalen) || - (roff + rsize > vap->va_datalen)) { - ddprintf(("ntfs_readattr: offset too big\n")); - ntfs_ntvattrrele(vap); - return (E2BIG); - } - if (vap->va_compression && vap->va_compressalg) { - u_int8_t *cup; - u_int8_t *uup; - off_t off = roff, left = rsize, tocopy; - caddr_t data = rdata; - cn_t cn; - - ddprintf(("ntfs_ntreadattr: compression: %d\n", - vap->va_compressalg)); - - cup = malloc(ntfs_cntob(NTFS_COMPUNIT_CL), - M_NTFSDECOMP, M_WAITOK); - uup = malloc(ntfs_cntob(NTFS_COMPUNIT_CL), - M_NTFSDECOMP, M_WAITOK); - - cn = (ntfs_btocn(roff)) & (~(NTFS_COMPUNIT_CL - 1)); - off = roff - ntfs_cntob(cn); - - while (left) { - error = ntfs_readattr_plain(ntmp, ip, attrnum, - attrname, ntfs_cntob(cn), - ntfs_cntob(NTFS_COMPUNIT_CL), - cup, &init, NULL); - if (error) - break; - - tocopy = MIN(left, ntfs_cntob(NTFS_COMPUNIT_CL) - off); - - if (init == ntfs_cntob(NTFS_COMPUNIT_CL)) { - if (uio) - uiomove(cup + off, tocopy, uio); - else - memcpy(data, cup + off, tocopy); - } else if (init == 0) { - if (uio) { - size_t remains = tocopy; - for(; remains; remains--) - uiomove("", 1, uio); - } - else - memset(data, 0, tocopy); - } else { - error = ntfs_uncompunit(ntmp, uup, cup); - if (error) - break; - if (uio) - uiomove(uup + off, tocopy, uio); - else - memcpy(data, uup + off, tocopy); - } - - left -= tocopy; - data = data + tocopy; - off += tocopy - ntfs_cntob(NTFS_COMPUNIT_CL); - cn += NTFS_COMPUNIT_CL; - } - - free(uup, M_NTFSDECOMP); - free(cup, M_NTFSDECOMP); - } else - error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, - roff, rsize, rdata, &init, uio); - ntfs_ntvattrrele(vap); - return (error); -} - -#if 0 -int -ntfs_parserun( - cn_t * cn, - cn_t * cl, - u_int8_t * run, - u_long len, - u_long *off) -{ - u_int8_t sz; - int i; - - if (NULL == run) { - printf("ntfs_parsetun: run == NULL\n"); - return (EINVAL); - } - sz = run[(*off)++]; - if (0 == sz) { - printf("ntfs_parserun: trying to go out of run\n"); - return (E2BIG); - } - *cl = 0; - if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { - printf("ntfs_parserun: " \ - "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", - sz, len, *off); - return (EINVAL); - } - for (i = 0; i < (sz & 0xF); i++) - *cl += (u_int32_t) run[(*off)++] << (i << 3); - - sz >>= 4; - if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { - printf("ntfs_parserun: " \ - "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", - sz, len, *off); - return (EINVAL); - } - for (i = 0; i < (sz & 0xF); i++) - *cn += (u_int32_t) run[(*off)++] << (i << 3); - - return (0); -} -#endif - -/* - * Process fixup routine on given buffer. - */ -int -ntfs_procfixups( - struct ntfsmount * ntmp, - u_int32_t magic, - caddr_t buf, - size_t len) -{ - struct fixuphdr *fhp = (struct fixuphdr *) buf; - int i; - u_int16_t fixup; - u_int16_t *fxp; - u_int16_t *cfxp; - - if (fhp->fh_magic != magic) { - printf("ntfs_procfixups: magic doesn't match: %08x != %08x\n", - fhp->fh_magic, magic); - return (EINVAL); - } - if ((fhp->fh_fnum - 1) * NTFS_BLOCK_SIZE != len) { - printf("ntfs_procfixups: " \ - "bad fixups number: %d for %ld bytes block\n", - fhp->fh_fnum, (long)len); /* XXX printf kludge */ - return (EINVAL); - } - if (fhp->fh_foff >= ntmp->ntm_spc * ntmp->ntm_mftrecsz * ntmp->ntm_bps) { - printf("ntfs_procfixups: invalid offset: %x", fhp->fh_foff); - return (EINVAL); - } - fxp = (u_int16_t *) (buf + fhp->fh_foff); - cfxp = (u_int16_t *) (buf + NTFS_BLOCK_SIZE - 2); - fixup = *fxp++; - for (i = 1; i < fhp->fh_fnum; i++, fxp++) { - if (*cfxp != fixup) { - printf("ntfs_procfixups: fixup %d doesn't match\n", i); - return (EINVAL); - } - *cfxp = *fxp; - cfxp = (u_int16_t *) ((caddr_t) cfxp + NTFS_BLOCK_SIZE); - } - return (0); -} - -#if 0 -int -ntfs_runtocn( - cn_t * cn, - struct ntfsmount * ntmp, - u_int8_t * run, - u_long len, - cn_t vcn) -{ - cn_t ccn = 0; - cn_t ccl = 0; - u_long off = 0; - int error = 0; - -#if NTFS_DEBUG - int i; - printf("ntfs_runtocn: run: %p, %ld bytes, vcn:%ld\n", - run, len, (u_long) vcn); - printf("ntfs_runtocn: run: "); - for (i = 0; i < len; i++) - printf("0x%02x ", run[i]); - printf("\n"); -#endif - - if (NULL == run) { - printf("ntfs_runtocn: run == NULL\n"); - return (EINVAL); - } - do { - if (run[off] == 0) { - printf("ntfs_runtocn: vcn too big\n"); - return (E2BIG); - } - vcn -= ccl; - error = ntfs_parserun(&ccn, &ccl, run, len, &off); - if (error) { - printf("ntfs_runtocn: ntfs_parserun failed\n"); - return (error); - } - } while (ccl <= vcn); - *cn = ccn + vcn; - return (0); -} -#endif - -/* - * this initializes toupper table & dependant variables to be ready for - * later work - */ -void -ntfs_toupper_init() -{ - ntfs_toupper_tab = (wchar *) NULL; - lockinit(&ntfs_toupper_lock, PVFS, "ntfs_toupper", 0, 0); - ntfs_toupper_usecount = 0; -} - -void -ntfs_toupper_destroy(void) -{ - - lockdestroy(&ntfs_toupper_lock); -} - -/* - * if the ntfs_toupper_tab[] is filled already, just raise use count; - * otherwise read the data from the filesystem we are currently mounting - */ -int -ntfs_toupper_use(mp, ntmp) - struct mount *mp; - struct ntfsmount *ntmp; -{ - int error = 0; - struct vnode *vp; - - /* get exclusive access */ - lockmgr(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL); - - /* only read the translation data from a file if it hasn't been - * read already */ - if (ntfs_toupper_tab) - goto out; - - /* - * Read in Unicode lowercase -> uppercase translation file. - * XXX for now, just the first 256 entries are used anyway, - * so don't bother reading more - */ - ntfs_toupper_tab = malloc(65536 * sizeof(wchar), - M_NTFSRDATA, M_WAITOK); - - if ((error = VFS_VGET(mp, NTFS_UPCASEINO, LK_EXCLUSIVE, &vp))) - goto out; - error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, - 0, 65536*sizeof(wchar), (char *) ntfs_toupper_tab, NULL); - vput(vp); - - out: - ntfs_toupper_usecount++; - lockmgr(&ntfs_toupper_lock, LK_RELEASE, NULL); - return (error); -} - -/* - * lower the use count and if it reaches zero, free the memory - * tied by toupper table - */ -void -ntfs_toupper_unuse() -{ - /* get exclusive access */ - lockmgr(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL); - - ntfs_toupper_usecount--; - if (ntfs_toupper_usecount == 0) { - free(ntfs_toupper_tab, M_NTFSRDATA); - ntfs_toupper_tab = NULL; - } -#ifdef DIAGNOSTIC - else if (ntfs_toupper_usecount < 0) { - panic("ntfs_toupper_unuse(): use count negative: %d\n", - ntfs_toupper_usecount); - } -#endif - - /* release the lock */ - lockmgr(&ntfs_toupper_lock, LK_RELEASE, NULL); -} - -int -ntfs_u28_init( - struct ntfsmount *ntmp, - wchar *u2w, - char *cs_local, - char *cs_ntfs) -{ - char ** u28; - int i, j, h, l; - - if (ntfs_iconv && cs_local) { - ntfs_iconv->open(cs_local, cs_ntfs, &ntmp->ntm_ic_u2l); - return (0); - } - - u28 = malloc(256 * sizeof(char*), M_TEMP, M_WAITOK | M_ZERO); - - for (i=0; i<256; i++) { - h = (u2w[i] >> 8) & 0xFF; - l = (u2w[i]) &0xFF; - - if (u28[h] == NULL) { - u28[h] = malloc(256 * sizeof(char), M_TEMP, M_WAITOK); - for (j=0; j<256; j++) - u28[h][j] = '_'; - } - - u28[h][l] = i & 0xFF; - } - - ntmp->ntm_u28 = u28; - - return (0); -} - -int -ntfs_u28_uninit(struct ntfsmount *ntmp) -{ - char ** u28; - int i; - - if (ntmp->ntm_u28 == NULL) { - if (ntfs_iconv && ntmp->ntm_ic_u2l) { - ntfs_iconv->close(ntmp->ntm_ic_u2l); - } - return (0); - } - - u28 = ntmp->ntm_u28; - - for (i=0; i<256; i++) - if (u28[i] != NULL) - free(u28[i], M_TEMP); - - free(u28, M_TEMP); - - return (0); -} - -int -ntfs_82u_init( - struct ntfsmount *ntmp, - char *cs_local, - char *cs_ntfs) -{ - wchar * _82u; - int i; - - if (ntfs_iconv && cs_local) { - ntfs_iconv->open(cs_ntfs, cs_local, &ntmp->ntm_ic_l2u); - return (0); - } - - _82u = malloc(256 * sizeof(wchar), M_TEMP, M_WAITOK); - - for (i=0; i<256; i++) - _82u[i] = i; - - ntmp->ntm_82u = _82u; - - return (0); -} - -int -ntfs_82u_uninit(struct ntfsmount *ntmp) -{ - - if (ntmp->ntm_82u == NULL) { - if (ntfs_iconv && ntmp->ntm_ic_l2u) { - ntfs_iconv->close(ntmp->ntm_ic_l2u); - } - return (0); - } - - free(ntmp->ntm_82u, M_TEMP); - return (0); -} - -/* - * maps the Unicode char to local character - */ -char * -ntfs_u28( - char *outbuf, - struct ntfsmount *ntmp, - wchar wc) -{ - char *p, *outp, inbuf[3]; - size_t ilen, olen; - - outp = outbuf; - if (ntfs_iconv && ntmp->ntm_ic_u2l) { - ilen = 2; - olen = 4; - - inbuf[0] = (char)(wc>>8); - inbuf[1] = (char)wc; - inbuf[2] = '\0'; - p = inbuf; - ntfs_iconv->convchr(ntmp->ntm_ic_u2l, (const char **)&p, &ilen, - &outp, &olen); - if (olen == 4) - *outp++ = '?'; - *outp = '\0'; - outp = outbuf; - return (outp); - } - - p = ntmp->ntm_u28[(wc>>8)&0xFF]; - outbuf[0] = (p == NULL) ? '_' : p[wc&0xFF] & 0xFF; - outbuf[1] = '\0'; - return (outp); -} - -wchar -ntfs_82u( - struct ntfsmount *ntmp, - const char *c, - int *len) -{ - char *outp, outbuf[3]; - wchar uc; - size_t ilen, olen; - - if (ntfs_iconv && ntmp->ntm_ic_l2u) { - ilen = (size_t)*len; - olen = 2; - - outp = outbuf; - ntfs_iconv->convchr(ntmp->ntm_ic_l2u, &c, &ilen, &outp, &olen); - *len -= (int)ilen; - uc = (wchar)((outbuf[0]<<8) | (outbuf[1]&0xFF)); - - return (uc); - } - - if (ntmp->ntm_82u != NULL) - return (ntmp->ntm_82u[*c&0xFF]); - - return ('?'); -} - diff --git a/sys/fs/ntfs/ntfs_subr.h b/sys/fs/ntfs/ntfs_subr.h deleted file mode 100644 index 9ccbb42..0000000 --- a/sys/fs/ntfs/ntfs_subr.h +++ /dev/null @@ -1,120 +0,0 @@ -/* $NetBSD: ntfs_subr.h,v 1.8 1999/10/10 14:48:37 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#define VA_LOADED 0x0001 -#define VA_PRELOADED 0x0002 - -struct ntvattr { - LIST_ENTRY(ntvattr) va_list; - - u_int32_t va_vflag; - struct vnode *va_vp; - struct ntnode *va_ip; - - u_int32_t va_flag; - u_int32_t va_type; - u_int8_t va_namelen; - char va_name[NTFS_MAXATTRNAME]; - - u_int32_t va_compression; - u_int32_t va_compressalg; - u_int64_t va_datalen; - u_int64_t va_allocated; - cn_t va_vcnstart; - cn_t va_vcnend; - u_int16_t va_index; - union { - struct { - cn_t * cn; - cn_t * cl; - u_long cnt; - } vrun; - caddr_t datap; - struct attr_name *name; - struct attr_indexroot *iroot; - struct attr_indexalloc *ialloc; - } va_d; -}; -#define va_vruncn va_d.vrun.cn -#define va_vruncl va_d.vrun.cl -#define va_vruncnt va_d.vrun.cnt -#define va_datap va_d.datap -#define va_a_name va_d.name -#define va_a_iroot va_d.iroot -#define va_a_ialloc va_d.ialloc - -struct componentname; -struct fnode; -struct uio; - -int ntfs_procfixups( struct ntfsmount *, u_int32_t, caddr_t, size_t ); -int ntfs_parserun( cn_t *, cn_t *, u_int8_t *, u_long, u_long *); -int ntfs_runtocn( cn_t *, struct ntfsmount *, u_int8_t *, u_long, cn_t); -int ntfs_readntvattr_plain( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *, struct uio *); -int ntfs_readattr_plain( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *, struct uio *); -int ntfs_readattr( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, struct uio *); -int ntfs_filesize( struct ntfsmount *, struct fnode *, u_int64_t *, u_int64_t *); -int ntfs_times( struct ntfsmount *, struct ntnode *, ntfs_times_t *); -struct timespec ntfs_nttimetounix( u_int64_t ); -int ntfs_ntreaddir( struct ntfsmount *, struct fnode *, u_int32_t, struct attr_indexentry **); -int ntfs_runtovrun( cn_t **, cn_t **, u_long *, u_int8_t *); -int ntfs_attrtontvattr( struct ntfsmount *, struct ntvattr **, struct attr * ); -void ntfs_freentvattr( struct ntvattr * ); -int ntfs_loadntvattrs( struct ntfsmount *, struct vnode *, caddr_t, struct ntvattr **); -struct ntvattr * ntfs_findntvattr( struct ntfsmount *, struct ntnode *, u_int32_t, cn_t ); -int ntfs_ntlookupfile(struct ntfsmount *, struct vnode *, struct componentname *, struct vnode **); -int ntfs_isnamepermitted(struct ntfsmount *, struct attr_indexentry * ); -int ntfs_ntvattrrele(struct ntvattr * ); -int ntfs_ntvattrget(struct ntfsmount *, struct ntnode *, u_int32_t, const char *, cn_t , struct ntvattr **); -int ntfs_ntlookup(struct ntfsmount *, ino_t, struct ntnode **); -int ntfs_ntget(struct ntnode *); -void ntfs_ntref(struct ntnode *); -void ntfs_ntrele(struct ntnode *); -void ntfs_ntput(struct ntnode *); -int ntfs_loadntnode( struct ntfsmount *, struct ntnode * ); -void ntfs_toupper_init(void); -void ntfs_toupper_destroy(void); -int ntfs_toupper_use(struct mount *, struct ntfsmount *); -void ntfs_toupper_unuse(void); -int ntfs_fget(struct ntfsmount *, struct ntnode *, int, char *, struct fnode **); -void ntfs_frele(struct fnode *); - -int ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w, char *cs_local, char *cs_ntfs); -int ntfs_u28_uninit(struct ntfsmount *ntmp); -int ntfs_82u_init(struct ntfsmount *ntmp, char *cs_local, char *cs_ntfs); -int ntfs_82u_uninit(struct ntfsmount *ntmp); -char * ntfs_u28(char *outbuf, struct ntfsmount *ntmp, wchar wc); -wchar ntfs_82u(struct ntfsmount *ntmp, const char *c, int *len); -#define NTFS_U28(ch) ntfs_u28(tmpbuf, ntmp, (ch)) -#define NTFS_82U(ch, len) ntfs_82u(ntmp, (ch), len) -#define NTFS_UASTRCMP(ustr, ustrlen, astr, astrlen) \ - ntfs_uastrcmp(ntmp, (ustr), (ustrlen), (astr), (astrlen)) -#define NTFS_UASTRICMP(ustr, ustrlen, astr, astrlen) \ - ntfs_uastricmp(ntmp, (ustr), (ustrlen), (astr), (astrlen)) diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c deleted file mode 100644 index c0408dd..0000000 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ /dev/null @@ -1,780 +0,0 @@ -/* $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/namei.h> -#include <sys/conf.h> -#include <sys/priv.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> -#include <sys/stat.h> -#include <sys/systm.h> - -#include <geom/geom.h> -#include <geom/geom_vfs.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/vm_page.h> -#include <vm/vm_object.h> -#include <vm/vm_extern.h> - -/*#define NTFS_DEBUG 1*/ -#include <fs/ntfs/ntfs.h> -#include <fs/ntfs/ntfs_inode.h> -#include <fs/ntfs/ntfs_subr.h> -#include <fs/ntfs/ntfs_vfsops.h> -#include <fs/ntfs/ntfs_ihash.h> -#include <fs/ntfs/ntfsmount.h> - -static MALLOC_DEFINE(M_NTFSMNT, "ntfs_mount", "NTFS mount structure"); -MALLOC_DEFINE(M_NTFSNTNODE,"ntfs_ntnode", "NTFS ntnode information"); -MALLOC_DEFINE(M_NTFSFNODE,"ntfs_fnode", "NTFS fnode information"); -MALLOC_DEFINE(M_NTFSDIR,"ntfs_dir", "NTFS dir buffer"); - -static int ntfs_mountfs(register struct vnode *, struct mount *, - struct thread *); -static int ntfs_calccfree(struct ntfsmount *ntmp, cn_t *cfreep); - -static vfs_init_t ntfs_init; -static vfs_uninit_t ntfs_uninit; -static vfs_vget_t ntfs_vget; -static vfs_fhtovp_t ntfs_fhtovp; -static vfs_cmount_t ntfs_cmount; -static vfs_mount_t ntfs_mount; -static vfs_root_t ntfs_root; -static vfs_statfs_t ntfs_statfs; -static vfs_unmount_t ntfs_unmount; - -static b_strategy_t ntfs_bufstrategy; - -/* - * Buffer operations for NTFS vnodes. - * We punt on VOP_BMAP, so we need to do - * strategy on the file's vnode rather - * than the underlying device's - */ -static struct buf_ops ntfs_vnbufops = { - .bop_name = "NTFS", - .bop_strategy = ntfs_bufstrategy, -}; - -static int -ntfs_init ( - struct vfsconf *vcp ) -{ - ntfs_nthashinit(); - ntfs_toupper_init(); - return 0; -} - -static int -ntfs_uninit ( - struct vfsconf *vcp ) -{ - ntfs_toupper_destroy(); - ntfs_nthashdestroy(); - return 0; -} - -static int -ntfs_cmount ( - struct mntarg *ma, - void *data, - uint64_t flags) -{ - struct ntfs_args args; - struct export_args exp; - int error; - - error = copyin(data, &args, sizeof(args)); - if (error) - return (error); - vfs_oexport_conv(&args.export, &exp); - ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); - ma = mount_arg(ma, "export", &exp, sizeof(exp)); - ma = mount_argf(ma, "uid", "%d", args.uid); - ma = mount_argf(ma, "gid", "%d", args.gid); - ma = mount_argf(ma, "mode", "%d", args.mode); - ma = mount_argb(ma, args.flag & NTFS_MFLAG_CASEINS, "nocaseins"); - ma = mount_argb(ma, args.flag & NTFS_MFLAG_ALLNAMES, "noallnames"); - if (args.flag & NTFS_MFLAG_KICONV) { - ma = mount_argsu(ma, "cs_ntfs", args.cs_ntfs, 64); - ma = mount_argsu(ma, "cs_local", args.cs_local, 64); - } - - error = kernel_mount(ma, flags); - - return (error); -} - -static const char *ntfs_opts[] = { - "from", "export", "uid", "gid", "mode", "caseins", "allnames", - "kiconv", "cs_ntfs", "cs_local", NULL -}; - -static int -ntfs_mount(struct mount *mp) -{ - int err = 0, error; - struct vnode *devvp; - struct nameidata ndp; - struct thread *td; - char *from; - - td = curthread; - if (vfs_filteropt(mp->mnt_optnew, ntfs_opts)) - return (EINVAL); - - /* Force mount as read-only. */ - MNT_ILOCK(mp); - mp->mnt_flag |= MNT_RDONLY; - MNT_IUNLOCK(mp); - - from = vfs_getopts(mp->mnt_optnew, "from", &error); - if (error) - return (error); - - /* - * If updating, check whether changing from read-only to - * read/write. - */ - if (mp->mnt_flag & MNT_UPDATE) { - if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) { - /* Process export requests in vfs_mount.c */ - return (0); - } else { - printf("ntfs_mount(): MNT_UPDATE not supported\n"); - return (EINVAL); - } - } - - /* - * Not an update, or updating the name: look up the name - * and verify that it refers to a sensible block device. - */ - NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td); - err = namei(&ndp); - if (err) - return (err); - NDFREE(&ndp, NDF_ONLY_PNBUF); - devvp = ndp.ni_vp; - - if (!vn_isdisk(devvp, &err)) { - vput(devvp); - return (err); - } - - /* - * If mount by non-root, then verify that user has necessary - * permissions on the device. - */ - err = VOP_ACCESS(devvp, VREAD, td->td_ucred, td); - if (err) - err = priv_check(td, PRIV_VFS_MOUNT_PERM); - if (err) { - vput(devvp); - return (err); - } - - - /* - * Since this is a new mount, we want the names for the device and - * the mount point copied in. If an error occurs, the mountpoint is - * discarded by the upper level code. Note that vfs_mount() handles - * copying the mountpoint f_mntonname for us, so we don't have to do - * it here unless we want to set it to something other than "path" - * for some rason. - */ - - err = ntfs_mountfs(devvp, mp, td); - if (err == 0) { - - /* Save "mounted from" info for mount point. */ - vfs_mountedfrom(mp, from); - } else - vrele(devvp); - return (err); -} - -/* - * Common code for mount and mountroot - */ -int -ntfs_mountfs(devvp, mp, td) - register struct vnode *devvp; - struct mount *mp; - struct thread *td; -{ - struct buf *bp; - struct ntfsmount *ntmp; - struct cdev *dev = devvp->v_rdev; - int error, i, v; - struct vnode *vp; - struct g_consumer *cp; - struct g_provider *pp; - char *cs_ntfs, *cs_local; - - DROP_GIANT(); - g_topology_lock(); - - /* - * XXX: Do not allow more than one consumer to open a device - * associated with a particular GEOM provider. - * This disables multiple read-only mounts of a device, - * but it gets rid of panics in vget() when you try to - * mount the same device more than once. - */ - pp = g_dev_getprovider(devvp->v_rdev); - if ((pp != NULL) && ((pp->acr | pp->acw | pp->ace ) != 0)) - error = EPERM; - else - error = g_vfs_open(devvp, &cp, "ntfs", 0); - - g_topology_unlock(); - PICKUP_GIANT(); - VOP_UNLOCK(devvp, 0); - if (error) - return (error); - - bp = NULL; - - error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp); - if (error) - goto out; - ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO); - bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) ); - /* - * We must not cache the boot block if its size is not exactly - * one cluster in order to avoid confusing the buffer cache when - * the boot file is read later by ntfs_readntvattr_plain(), which - * reads a cluster at a time. - */ - if (ntfs_cntob(1) != BBSIZE) - bp->b_flags |= B_NOCACHE; - brelse( bp ); - bp = NULL; - - if (strncmp((const char *)ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) { - error = EINVAL; - dprintf(("ntfs_mountfs: invalid boot block\n")); - goto out; - } - - { - int8_t cpr = ntmp->ntm_mftrecsz; - if( cpr > 0 ) - ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr; - else - ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps; - } - ntmp->ntm_multiplier = ntmp->ntm_bps / DEV_BSIZE; - - dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n", - ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media, - ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec)); - dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n", - (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn)); - - ntmp->ntm_mountp = mp; - ntmp->ntm_devvp = devvp; - if (vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v) == 1) - ntmp->ntm_uid = v; - if (vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v) == 1) - ntmp->ntm_gid = v; - if (vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v) == 1) - ntmp->ntm_mode = v & ACCESSPERMS; - vfs_flagopt(mp->mnt_optnew, - "caseins", &ntmp->ntm_flag, NTFS_MFLAG_CASEINS); - vfs_flagopt(mp->mnt_optnew, - "allnames", &ntmp->ntm_flag, NTFS_MFLAG_ALLNAMES); - ntmp->ntm_cp = cp; - ntmp->ntm_bo = &devvp->v_bufobj; - - cs_local = vfs_getopts(mp->mnt_optnew, "cs_local", &error); - if (error && error != ENOENT) - goto out; - cs_ntfs = vfs_getopts(mp->mnt_optnew, "cs_ntfs", &error); - if (error && error != ENOENT) - goto out; - /* Copy in the 8-bit to Unicode conversion table */ - /* Initialize Unicode to 8-bit table from 8toU table */ - ntfs_82u_init(ntmp, cs_local, cs_ntfs); - if (cs_local != NULL && cs_ntfs != NULL) - ntfs_u28_init(ntmp, NULL, cs_local, cs_ntfs); - else - ntfs_u28_init(ntmp, ntmp->ntm_82u, cs_local, cs_ntfs); - - mp->mnt_data = ntmp; - - dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", - (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.", - (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"", - ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode)); - - /* - * We read in some system nodes to do not allow - * reclaim them and to have everytime access to them. - */ - { - int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO }; - for (i=0; i<3; i++) { - error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE, - &(ntmp->ntm_sysvn[pi[i]])); - if(error) - goto out1; - ntmp->ntm_sysvn[pi[i]]->v_vflag |= VV_SYSTEM; - VREF(ntmp->ntm_sysvn[pi[i]]); - vput(ntmp->ntm_sysvn[pi[i]]); - } - } - - /* read the Unicode lowercase --> uppercase translation table, - * if necessary */ - if ((error = ntfs_toupper_use(mp, ntmp))) - goto out1; - - /* - * Scan $BitMap and count free clusters - */ - error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree); - if(error) - goto out1; - - /* - * Read and translate to internal format attribute - * definition file. - */ - { - int num,j; - struct attrdef ad; - - /* Open $AttrDef */ - error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp ); - if(error) - goto out1; - - /* Count valid entries */ - for(num=0;;num++) { - error = ntfs_readattr(ntmp, VTONT(vp), - NTFS_A_DATA, NULL, - num * sizeof(ad), sizeof(ad), - &ad, NULL); - if (error) - goto out1; - if (ad.ad_name[0] == 0) - break; - } - - /* Alloc memory for attribute definitions */ - ntmp->ntm_ad = malloc(num * sizeof(struct ntvattrdef), - M_NTFSMNT, M_WAITOK); - - ntmp->ntm_adnum = num; - - /* Read them and translate */ - for(i=0;i<num;i++){ - error = ntfs_readattr(ntmp, VTONT(vp), - NTFS_A_DATA, NULL, - i * sizeof(ad), sizeof(ad), - &ad, NULL); - if (error) - goto out1; - j = 0; - do { - ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j]; - } while(ad.ad_name[j++]); - ntmp->ntm_ad[i].ad_namelen = j - 1; - ntmp->ntm_ad[i].ad_type = ad.ad_type; - } - - vput(vp); - } - - mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); - mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; - mp->mnt_maxsymlinklen = 0; - MNT_ILOCK(mp); - mp->mnt_flag |= MNT_LOCAL; - MNT_IUNLOCK(mp); - return (0); - -out1: - for(i=0;i<NTFS_SYSNODESNUM;i++) - if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); - - if (vflush(mp, 0, 0, td)) - dprintf(("ntfs_mountfs: vflush failed\n")); - -out: - if (bp) - brelse(bp); - - DROP_GIANT(); - g_topology_lock(); - g_vfs_close(cp); - g_topology_unlock(); - PICKUP_GIANT(); - - return (error); -} - -static int -ntfs_unmount( - struct mount *mp, - int mntflags) -{ - struct thread *td; - struct ntfsmount *ntmp; - int error, flags, i; - - dprintf(("ntfs_unmount: unmounting...\n")); - td = curthread; - ntmp = VFSTONTFS(mp); - - flags = 0; - if(mntflags & MNT_FORCE) - flags |= FORCECLOSE; - - dprintf(("ntfs_unmount: vflushing...\n")); - error = vflush(mp, 0, flags | SKIPSYSTEM, td); - if (error) { - printf("ntfs_unmount: vflush failed: %d\n",error); - return (error); - } - - /* Check if only system vnodes are rest */ - for(i=0;i<NTFS_SYSNODESNUM;i++) - if((ntmp->ntm_sysvn[i]) && - (vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY); - - /* Dereference all system vnodes */ - for(i=0;i<NTFS_SYSNODESNUM;i++) - if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); - - /* vflush system vnodes */ - error = vflush(mp, 0, flags, td); - if (error) - printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error); - - vinvalbuf(ntmp->ntm_devvp, V_SAVE, 0, 0); - - DROP_GIANT(); - g_topology_lock(); - g_vfs_close(ntmp->ntm_cp); - g_topology_unlock(); - PICKUP_GIANT(); - - vrele(ntmp->ntm_devvp); - - /* free the toupper table, if this has been last mounted ntfs volume */ - ntfs_toupper_unuse(); - - dprintf(("ntfs_umount: freeing memory...\n")); - ntfs_u28_uninit(ntmp); - ntfs_82u_uninit(ntmp); - mp->mnt_data = NULL; - MNT_ILOCK(mp); - mp->mnt_flag &= ~MNT_LOCAL; - MNT_IUNLOCK(mp); - free(ntmp->ntm_ad, M_NTFSMNT); - free(ntmp, M_NTFSMNT); - return (error); -} - -static int -ntfs_root( - struct mount *mp, - int flags, - struct vnode **vpp) -{ - struct vnode *nvp; - int error = 0; - - dprintf(("ntfs_root(): sysvn: %p\n", - VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO])); - error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp); - if(error) { - printf("ntfs_root: VFS_VGET failed: %d\n",error); - return (error); - } - - *vpp = nvp; - return (0); -} - -static int -ntfs_calccfree( - struct ntfsmount *ntmp, - cn_t *cfreep) -{ - struct vnode *vp; - u_int8_t *tmp; - int j, error; - long cfree = 0; - size_t bmsize, i; - - vp = ntmp->ntm_sysvn[NTFS_BITMAPINO]; - - bmsize = VTOF(vp)->f_size; - - tmp = malloc(bmsize, M_TEMP, M_WAITOK); - - error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, - 0, bmsize, tmp, NULL); - if (error) - goto out; - - for(i=0;i<bmsize;i++) - for(j=0;j<8;j++) - if(~tmp[i] & (1 << j)) cfree++; - *cfreep = cfree; - - out: - free(tmp, M_TEMP); - return(error); -} - -static int -ntfs_statfs( - struct mount *mp, - struct statfs *sbp) -{ - struct ntfsmount *ntmp = VFSTONTFS(mp); - u_int64_t mftsize,mftallocated; - - dprintf(("ntfs_statfs():\n")); - - mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size; - mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated; - - sbp->f_type = mp->mnt_vfc->vfc_typenum; - sbp->f_bsize = ntmp->ntm_bps; - sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc; - sbp->f_blocks = ntmp->ntm_bootfile.bf_spv; - sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree); - sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec; - sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) + - sbp->f_ffree; - sbp->f_flags = mp->mnt_flag; - - return (0); -} - -/*ARGSUSED*/ -static int -ntfs_fhtovp( - struct mount *mp, - struct fid *fhp, - int flags, - struct vnode **vpp) -{ - struct vnode *nvp; - struct ntfid *ntfhp = (struct ntfid *)fhp; - int error; - - ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino)); - - if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) { - *vpp = NULLVP; - return (error); - } - /* XXX as unlink/rmdir/mkdir/creat are not currently possible - * with NTFS, we don't need to check anything else for now */ - *vpp = nvp; - vnode_create_vobject(nvp, VTOF(nvp)->f_size, curthread); - return (0); -} - -int -ntfs_vgetex( - struct mount *mp, - ino_t ino, - u_int32_t attrtype, - char *attrname, - u_long lkflags, - u_long flags, - struct thread *td, - struct vnode **vpp) -{ - int error; - register struct ntfsmount *ntmp; - struct ntnode *ip; - struct fnode *fp; - struct vnode *vp; - enum vtype f_type; - - dprintf(("ntfs_vgetex: ino: %ju, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n", - (uintmax_t)ino, attrtype, attrname ? attrname : "", lkflags, - (u_long)flags)); - - ntmp = VFSTONTFS(mp); - *vpp = NULL; - - /* Get ntnode */ - error = ntfs_ntlookup(ntmp, ino, &ip); - if (error) { - printf("ntfs_vget: ntfs_ntget failed\n"); - return (error); - } - - /* It may be not initialized fully, so force load it */ - if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) { - error = ntfs_loadntnode(ntmp, ip); - if(error) { - printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %ju\n", - (uintmax_t)ip->i_number); - ntfs_ntput(ip); - return (error); - } - } - - error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); - if (error) { - printf("ntfs_vget: ntfs_fget failed\n"); - ntfs_ntput(ip); - return (error); - } - - f_type = VNON; - if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) { - if ((ip->i_frflag & NTFS_FRFLAG_DIR) && - (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) { - f_type = VDIR; - } else if (flags & VG_EXT) { - f_type = VNON; - fp->f_size = fp->f_allocated = 0; - } else { - f_type = VREG; - - error = ntfs_filesize(ntmp, fp, - &fp->f_size, &fp->f_allocated); - if (error) { - ntfs_ntput(ip); - return (error); - } - } - - fp->f_flag |= FN_VALID; - } - - if (FTOV(fp)) { - vget(FTOV(fp), lkflags, td); - *vpp = FTOV(fp); - ntfs_ntput(ip); - return (0); - } - - error = getnewvnode("ntfs", ntmp->ntm_mountp, &ntfs_vnodeops, &vp); - if(error) { - ntfs_frele(fp); - ntfs_ntput(ip); - return (error); - } - /* XXX: Too early for mpsafe fs, lacks vnode lock */ - error = insmntque(vp, ntmp->ntm_mountp); - if (error) { - ntfs_frele(fp); - ntfs_ntput(ip); - return (error); - } - dprintf(("ntfs_vget: vnode: %p for ntnode: %ju\n", vp, (uintmax_t)ino)); - - fp->f_vp = vp; - vp->v_data = fp; - vp->v_type = f_type; - - vp->v_bufobj.bo_ops = &ntfs_vnbufops; - vp->v_bufobj.bo_private = vp; - - if (ino == NTFS_ROOTINO) - vp->v_vflag |= VV_ROOT; - - ntfs_ntput(ip); - - if (lkflags & LK_TYPE_MASK) { - error = vn_lock(vp, lkflags); - if (error) { - vput(vp); - return (error); - } - } - - *vpp = vp; - return (0); - -} - -static int -ntfs_vget( - struct mount *mp, - ino_t ino, - int lkflags, - struct vnode **vpp) -{ - return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0, - curthread, vpp); -} - -static void -ntfs_bufstrategy(struct bufobj *bo, struct buf *bp) -{ - struct vnode *vp; - int rc; - - vp = bo->bo_private; - KASSERT(bo == &vp->v_bufobj, ("BO/VP mismatch: vp %p bo %p != %p", - vp, &vp->v_bufobj, bo)); - rc = VOP_STRATEGY(vp, bp); - KASSERT(rc == 0, ("NTFS VOP_STRATEGY failed: bp=%p, " - "vp=%p, rc=%d", bp, vp, rc)); -} - -static struct vfsops ntfs_vfsops = { - .vfs_fhtovp = ntfs_fhtovp, - .vfs_init = ntfs_init, - .vfs_cmount = ntfs_cmount, - .vfs_mount = ntfs_mount, - .vfs_root = ntfs_root, - .vfs_statfs = ntfs_statfs, - .vfs_uninit = ntfs_uninit, - .vfs_unmount = ntfs_unmount, - .vfs_vget = ntfs_vget, -}; -VFS_SET(ntfs_vfsops, ntfs, VFCF_READONLY); -MODULE_VERSION(ntfs, 1); diff --git a/sys/fs/ntfs/ntfs_vfsops.h b/sys/fs/ntfs/ntfs_vfsops.h deleted file mode 100644 index adb737d..0000000 --- a/sys/fs/ntfs/ntfs_vfsops.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $NetBSD: ntfs_vfsops.h,v 1.4 1999/10/10 14:20:33 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ -#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */ - /* ntfs_loadntnode() on ntnode, even if */ - /* ntnode not loaded */ -#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */ - /* fnode */ -#define VG_EXT 0x0004 /* This is not main record */ - -struct mount; -struct ntfsmount; -struct thread; -struct vnode; - -int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long, - struct thread *, struct vnode **); diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c deleted file mode 100644 index e78dcef..0000000 --- a/sys/fs/ntfs/ntfs_vnops.c +++ /dev/null @@ -1,687 +0,0 @@ -/* $NetBSD: ntfs_vnops.c,v 1.23 1999/10/31 19:45:27 jdolecek Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * John Heidemann of the UCLA Ficus project. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. - * - * $FreeBSD$ - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/malloc.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/dirent.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/vm_page.h> -#include <vm/vm_object.h> -#include <vm/vm_pager.h> -#include <vm/vnode_pager.h> -#include <vm/vm_extern.h> - -#include <sys/sysctl.h> - -/*#define NTFS_DEBUG 1*/ -#include <fs/ntfs/ntfs.h> -#include <fs/ntfs/ntfs_inode.h> -#include <fs/ntfs/ntfs_subr.h> - -#include <sys/unistd.h> /* for pathconf(2) constants */ - -static vop_read_t ntfs_read; -static vop_getattr_t ntfs_getattr; -static vop_inactive_t ntfs_inactive; -static vop_reclaim_t ntfs_reclaim; -static vop_bmap_t ntfs_bmap; -static vop_strategy_t ntfs_strategy; -static vop_access_t ntfs_access; -static vop_open_t ntfs_open; -static vop_close_t ntfs_close; -static vop_readdir_t ntfs_readdir; -static vop_cachedlookup_t ntfs_lookup; -static vop_pathconf_t ntfs_pathconf; -static vop_vptofh_t ntfs_vptofh; - -/* - * This is a noop, simply returning what one has been given. - */ -int -ntfs_bmap(ap) - struct vop_bmap_args /* { - struct vnode *a_vp; - daddr_t a_bn; - struct bufobj **a_bop; - daddr_t *a_bnp; - int *a_runp; - int *a_runb; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - - dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn)); - if (ap->a_bop != NULL) - *ap->a_bop = &vp->v_bufobj; - if (ap->a_bnp != NULL) - *ap->a_bnp = ap->a_bn; - if (ap->a_runp != NULL) - *ap->a_runp = 0; - if (ap->a_runb != NULL) - *ap->a_runb = 0; - return (0); -} - -static int -ntfs_read(ap) - struct vop_read_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - struct uio *uio = ap->a_uio; - struct ntfsmount *ntmp = ip->i_mp; - struct buf *bp; - daddr_t cn; - int resid, off, toread; - int error; - - dprintf(("ntfs_read: ino: %ju, off: %jd resid: %d, segflg: %d\n", - (uintmax_t)ip->i_number, (intmax_t)uio->uio_offset, - uio->uio_resid, uio->uio_segflg)); - - dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size)); - - /* don't allow reading after end of file */ - if (uio->uio_offset > fp->f_size) - return (0); - - resid = MIN(uio->uio_resid, fp->f_size - uio->uio_offset); - - dprintf((", resid: %d\n", resid)); - - error = 0; - while (resid) { - cn = ntfs_btocn(uio->uio_offset); - off = ntfs_btocnoff(uio->uio_offset); - - toread = MIN(off + resid, ntfs_cntob(1)); - - error = bread(vp, cn, ntfs_cntob(1), NOCRED, &bp); - if (error) { - brelse(bp); - break; - } - - error = uiomove(bp->b_data + off, toread - off, uio); - if(error) { - brelse(bp); - break; - } - brelse(bp); - - resid -= toread - off; - } - - return (error); -} - -static int -ntfs_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - register struct vattr *vap = ap->a_vap; - - dprintf(("ntfs_getattr: %ju, flags: %d\n", - (uintmax_t)ip->i_number, ip->i_flag)); - - vap->va_fsid = dev2udev(ip->i_dev); - vap->va_fileid = ip->i_number; - vap->va_mode = ip->i_mp->ntm_mode; - vap->va_nlink = (ip->i_nlink || ip->i_flag & IN_LOADED ? ip->i_nlink : 1); - vap->va_uid = ip->i_mp->ntm_uid; - vap->va_gid = ip->i_mp->ntm_gid; - vap->va_rdev = NODEV; - vap->va_size = fp->f_size; - vap->va_bytes = fp->f_allocated; - vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access); - vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write); - vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create); - vap->va_flags = ip->i_flag; - vap->va_gen = 0; - vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps; - vap->va_type = vp->v_type; - vap->va_filerev = 0; - return (0); -} - -/* - * Last reference to an ntnode. If necessary, write or delete it. - */ -int -ntfs_inactive(ap) - struct vop_inactive_args /* { - struct vnode *a_vp; - } */ *ap; -{ -#ifdef NTFS_DEBUG - register struct ntnode *ip = VTONT(ap->a_vp); -#endif - - dprintf(("ntfs_inactive: vnode: %p, ntnode: %ju\n", ap->a_vp, - (uintmax_t)ip->i_number)); - - /* XXX since we don't support any filesystem changes - * right now, nothing more needs to be done - */ - return (0); -} - -/* - * Reclaim an fnode/ntnode so that it can be used for other purposes. - */ -int -ntfs_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - int error; - - dprintf(("ntfs_reclaim: vnode: %p, ntnode: %ju\n", - vp, (uintmax_t)ip->i_number)); - - /* - * Destroy the vm object and flush associated pages. - */ - vnode_destroy_vobject(vp); - - if ((error = ntfs_ntget(ip)) != 0) - return (error); - - /* Purge old data structures associated with the inode. */ - ntfs_frele(fp); - ntfs_ntput(ip); - vp->v_data = NULL; - - return (0); -} - -/* - * Calculate the logical to physical mapping if not done already, - * then call the device strategy routine. - */ -int -ntfs_strategy(ap) - struct vop_strategy_args /* { - struct buf *a_bp; - } */ *ap; -{ - register struct buf *bp = ap->a_bp; - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - struct ntfsmount *ntmp = ip->i_mp; - u_int32_t toread; - int error; - - dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n", - (u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno, - (u_int32_t)bp->b_lblkno)); - - dprintf(("strategy: bcount: %d flags: 0x%x\n", - (u_int32_t)bp->b_bcount,bp->b_flags)); - - KASSERT(bp->b_iocmd == BIO_READ, ("Invalid buffer\n")); - - if (ntfs_cntob(bp->b_blkno) >= fp->f_size) { - clrbuf(bp); - error = 0; - } else { - toread = MIN(bp->b_bcount, - fp->f_size-ntfs_cntob(bp->b_blkno)); - dprintf(("ntfs_strategy: toread: %d, fsize: %d\n", - toread,(u_int32_t)fp->f_size)); - - error = ntfs_readattr(ntmp, ip, fp->f_attrtype, - fp->f_attrname, ntfs_cntob(bp->b_blkno), - toread, bp->b_data, NULL); - - if (error) { - printf("ntfs_strategy: ntfs_readattr failed\n"); - bp->b_error = error; - bp->b_ioflags |= BIO_ERROR; - } - - bzero(bp->b_data + toread, bp->b_bcount - toread); - } - bufdone(bp); - return (0); -} - -int -ntfs_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - accmode_t a_accmode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct ntnode *ip = VTONT(vp); - accmode_t accmode = ap->a_accmode; - - dprintf(("ntfs_access: %d\n",ip->i_number)); - - /* - * Disallow write attempts as we assume read-only filesystems; - * unless the file is a socket, fifo, or a block or - * character device resident on the filesystem. - */ - if (accmode & VWRITE) { - switch ((int)vp->v_type) { - case VDIR: - case VLNK: - case VREG: - return (EROFS); - default: - break; - } - } - - return (vaccess(vp->v_type, ip->i_mp->ntm_mode, ip->i_mp->ntm_uid, - ip->i_mp->ntm_gid, ap->a_accmode, ap->a_cred, NULL)); -} - -/* - * Open called. - * - * Nothing to do. - */ -/* ARGSUSED */ -static int -ntfs_open(ap) - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ -#ifdef NTFS_DEBUG - register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); - - printf("ntfs_open: %d\n",ip->i_number); -#endif - - vnode_create_vobject(ap->a_vp, VTOF(ap->a_vp)->f_size, ap->a_td); - - /* - * Files marked append-only must be opened for appending. - */ - - return (0); -} - -/* - * Close called. - * - * Update the times on the inode. - */ -/* ARGSUSED */ -static int -ntfs_close(ap) - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ -#ifdef NTFS_DEBUG - register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); - - printf("ntfs_close: %d\n",ip->i_number); -#endif - - return (0); -} - -int -ntfs_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_ncookies; - u_int **cookies; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - struct uio *uio = ap->a_uio; - struct ntfsmount *ntmp = ip->i_mp; - int i, j, error = 0; - char *c, tmpbuf[5]; - u_int32_t faked = 0, num; - int ncookies = 0; - struct dirent cde; - off_t off; - - dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid)); - - off = uio->uio_offset; - - /* Simulate . in every dir except ROOT */ - if( ip->i_number != NTFS_ROOTINO ) { - struct dirent dot = { - .d_fileno = NTFS_ROOTINO, - .d_reclen = sizeof(struct dirent), - .d_type = DT_DIR, - .d_namlen = 1, - .d_name = "." - }; - - if( uio->uio_offset < sizeof(struct dirent) ) { - dot.d_fileno = ip->i_number; - error = uiomove((char *)&dot,sizeof(struct dirent),uio); - if(error) - return (error); - - ncookies ++; - } - } - - /* Simulate .. in every dir including ROOT */ - if( uio->uio_offset < 2 * sizeof(struct dirent) ) { - struct dirent dotdot = { - .d_fileno = NTFS_ROOTINO, - .d_reclen = sizeof(struct dirent), - .d_type = DT_DIR, - .d_namlen = 2, - .d_name = ".." - }; - - error = uiomove((char *)&dotdot,sizeof(struct dirent),uio); - if(error) - return (error); - - ncookies ++; - } - - faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2; - num = uio->uio_offset / sizeof(struct dirent) - faked; - - while( uio->uio_resid >= sizeof(struct dirent) ) { - struct attr_indexentry *iep; - - error = ntfs_ntreaddir(ntmp, fp, num, &iep); - - if(error) - return (error); - - if( NULL == iep ) - break; - - for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent)); - iep = NTFS_NEXTREC(iep, struct attr_indexentry *)) - { - if(!ntfs_isnamepermitted(ntmp,iep)) - continue; - - for(i=0, j=0; i<iep->ie_fnamelen; i++) { - c = NTFS_U28(iep->ie_fname[i]); - while (*c != '\0') - cde.d_name[j++] = *c++; - } - cde.d_name[j] = '\0'; - dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ", - num, cde.d_name, iep->ie_fnametype, - iep->ie_flag)); - cde.d_namlen = j; - cde.d_fileno = iep->ie_number; - cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG; - cde.d_reclen = sizeof(struct dirent); - dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg")); - - error = uiomove((char *)&cde, sizeof(struct dirent), uio); - if(error) - return (error); - - ncookies++; - num++; - } - } - - dprintf(("ntfs_readdir: %d entries (%d bytes) read\n", - ncookies,(u_int)(uio->uio_offset - off))); - dprintf(("ntfs_readdir: off: %d resid: %d\n", - (u_int32_t)uio->uio_offset,uio->uio_resid)); - - if (!error && ap->a_ncookies != NULL) { - struct dirent* dpStart; - struct dirent* dp; - u_long *cookies; - u_long *cookiep; - - ddprintf(("ntfs_readdir: %d cookies\n",ncookies)); - if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) - panic("ntfs_readdir: unexpected uio from NFS server"); - dpStart = (struct dirent *) - ((caddr_t)uio->uio_iov->iov_base - - (uio->uio_offset - off)); - cookies = malloc(ncookies * sizeof(u_long), - M_TEMP, M_WAITOK); - for (dp = dpStart, cookiep = cookies, i=0; - i < ncookies; - dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) { - off += dp->d_reclen; - *cookiep++ = (u_int) off; - } - *ap->a_ncookies = ncookies; - *ap->a_cookies = cookies; - } -/* - if (ap->a_eofflag) - *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset; -*/ - return (error); -} - -int -ntfs_lookup(ap) - struct vop_cachedlookup_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - } */ *ap; -{ - register struct vnode *dvp = ap->a_dvp; - register struct ntnode *dip = VTONT(dvp); - struct ntfsmount *ntmp = dip->i_mp; - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - int error; - dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d\n", - (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen, - dip->i_number)); - - error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread); - if(error) - return (error); - - if ((cnp->cn_flags & ISLASTCN) && - (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) - return (EROFS); - - if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { - dprintf(("ntfs_lookup: faking . directory in %d\n", - dip->i_number)); - - VREF(dvp); - *ap->a_vpp = dvp; - error = 0; - } else if (cnp->cn_flags & ISDOTDOT) { - struct ntvattr *vap; - - dprintf(("ntfs_lookup: faking .. directory in %d\n", - dip->i_number)); - - error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap); - if(error) - return (error); - - VOP_UNLOCK(dvp,0); - dprintf(("ntfs_lookup: parentdir: %d\n", - vap->va_a_name->n_pnumber)); - error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber, - LK_EXCLUSIVE, ap->a_vpp); - ntfs_ntvattrrele(vap); - if (error) { - vn_lock(dvp,LK_EXCLUSIVE|LK_RETRY); - return (error); - } - } else { - error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp); - if (error) { - dprintf(("ntfs_ntlookupfile: returned %d\n", error)); - return (error); - } - - dprintf(("ntfs_lookup: found ino: %ju\n", - (uintmax_t)VTONT(*ap->a_vpp)->i_number)); - } - - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, *ap->a_vpp, cnp); - - return (error); -} - -/* - * Return POSIX pathconf information applicable to NTFS filesystem - */ -int -ntfs_pathconf(ap) - struct vop_pathconf_args *ap; -{ - - switch (ap->a_name) { - case _PC_LINK_MAX: - *ap->a_retval = 1; - return (0); - case _PC_NAME_MAX: - *ap->a_retval = NTFS_MAXFILENAME; - return (0); - case _PC_PATH_MAX: - *ap->a_retval = PATH_MAX; - return (0); - case _PC_CHOWN_RESTRICTED: - *ap->a_retval = 1; - return (0); - case _PC_NO_TRUNC: - *ap->a_retval = 0; - return (0); - default: - return (EINVAL); - } - /* NOTREACHED */ -} - -int -ntfs_vptofh(ap) - struct vop_vptofh_args /* { - struct vnode *a_vp; - struct fid *a_fhp; - } */ *ap; -{ - register struct ntnode *ntp; - register struct ntfid *ntfhp; - - ddprintf(("ntfs_fhtovp(): %p\n", ap->a_vp)); - - ntp = VTONT(ap->a_vp); - ntfhp = (struct ntfid *)ap->a_fhp; - ntfhp->ntfid_len = sizeof(struct ntfid); - ntfhp->ntfid_ino = ntp->i_number; - /* ntfhp->ntfid_gen = ntp->i_gen; */ - return (0); -} - -/* - * Global vfs data structures - */ -struct vop_vector ntfs_vnodeops = { - .vop_default = &default_vnodeops, - - .vop_access = ntfs_access, - .vop_bmap = ntfs_bmap, - .vop_cachedlookup = ntfs_lookup, - .vop_close = ntfs_close, - .vop_getattr = ntfs_getattr, - .vop_inactive = ntfs_inactive, - .vop_lookup = vfs_cache_lookup, - .vop_open = ntfs_open, - .vop_pathconf = ntfs_pathconf, - .vop_read = ntfs_read, - .vop_readdir = ntfs_readdir, - .vop_reclaim = ntfs_reclaim, - .vop_strategy = ntfs_strategy, - .vop_vptofh = ntfs_vptofh, -}; diff --git a/sys/fs/ntfs/ntfsmount.h b/sys/fs/ntfs/ntfsmount.h deleted file mode 100644 index f64652c..0000000 --- a/sys/fs/ntfs/ntfsmount.h +++ /dev/null @@ -1,44 +0,0 @@ -/* $NetBSD: ntfsmount.h,v 1.3 1999/07/26 14:02:32 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * All rights reserved. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#define NTFS_MFLAG_CASEINS 0x00000001 -#define NTFS_MFLAG_ALLNAMES 0x00000002 -#define NTFS_MFLAG_KICONV 0x00000004 - -struct ntfs_args { - char *fspec; /* block special device to mount */ - struct oexport_args export; /* network export information */ - uid_t uid; /* uid that owns ntfs files */ - gid_t gid; /* gid that owns ntfs files */ - mode_t mode; /* mask to be applied for ntfs perms */ - u_long flag; /* additional flags */ - char *cs_ntfs; /* NTFS Charset */ - char *cs_local; /* Local Charset */ -}; diff --git a/sys/fs/portalfs/portal.h b/sys/fs/portalfs/portal.h deleted file mode 100644 index 1fd2d99..0000000 --- a/sys/fs/portalfs/portal.h +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. - * - * @(#)portal.h 8.4 (Berkeley) 1/21/94 - * - * $FreeBSD$ - */ - -struct portal_args { - char *pa_config; /* Config file */ - int pa_socket; /* Socket to server */ -}; - -struct portal_cred { - int pcr_flag; /* File open mode */ - uid_t pcr_uid; /* From ucred */ - short pcr_ngroups; /* From ucred */ - gid_t pcr_groups[XU_NGROUPS]; /* From ucred */ -}; - -#ifdef _KERNEL -struct portalmount { - struct vnode *pm_root; /* Root node */ - struct file *pm_server; /* Held reference to server socket */ -}; - -struct portalnode { - int pt_size; /* Length of Arg */ - char *pt_arg; /* Arg to send to server */ - int pt_fileid; /* cookie */ -}; - -#define VFSTOPORTAL(mp) ((struct portalmount *)((mp)->mnt_data)) -#define VTOPORTAL(vp) ((struct portalnode *)(vp)->v_data) - -#define PORTAL_ROOTFILEID 2 - -extern struct vop_vector portal_vnodeops; -#endif /* _KERNEL */ diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c deleted file mode 100644 index 62131dc..0000000 --- a/sys/fs/portalfs/portal_vfsops.c +++ /dev/null @@ -1,263 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. - * - * @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95 - * - * $FreeBSD$ - */ - -/* - * Portal Filesystem - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/capability.h> -#include <sys/domain.h> -#include <sys/filedesc.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/malloc.h> -#include <sys/file.h> /* Must come after sys/malloc.h */ -#include <sys/mount.h> -#include <sys/proc.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/vnode.h> - -#include <fs/portalfs/portal.h> - -static MALLOC_DEFINE(M_PORTALFSMNT, "portal_mount", "PORTAL mount structure"); - -static vfs_unmount_t portal_unmount; -static vfs_root_t portal_root; -static vfs_statfs_t portal_statfs; - -static const char *portal_opts[] = { - "socket", "config", - NULL -}; - -static int -portal_cmount(struct mntarg *ma, void *data, uint64_t flags) -{ - struct portal_args args; - int error; - - if (data == NULL) - return (EINVAL); - error = copyin(data, &args, sizeof args); - if (error) - return (error); - - ma = mount_argf(ma, "socket", "%d", args.pa_socket); - ma = mount_argsu(ma, "config", args.pa_config, MAXPATHLEN); - error = kernel_mount(ma, flags); - - return (error); -} - -/* - * Mount the per-process file descriptors (/dev/fd) - */ -static int -portal_mount(struct mount *mp) -{ - struct file *fp; - struct portalmount *fmp; - struct socket *so; - struct vnode *rvp; - struct thread *td; - struct portalnode *pn; - int error, v; - char *p; - - td = curthread; - if (vfs_filteropt(mp->mnt_optnew, portal_opts)) - return (EINVAL); - - error = vfs_scanopt(mp->mnt_optnew, "socket", "%d", &v); - if (error != 1) - return (EINVAL); - error = vfs_getopt(mp->mnt_optnew, "config", (void **)&p, NULL); - if (error) - return (error); - - /* - * Capsicum is not incompatible with portalfs, but we don't really - * know what rights are required. In the spirit of "better safe than - * sorry", pretend that all rights are required for now. - */ - if ((error = fget(td, v, CAP_MASK_VALID, &fp)) != 0) - return (error); - if (fp->f_type != DTYPE_SOCKET) { - fdrop(fp, td); - return(ENOTSOCK); - } - so = fp->f_data; /* XXX race against userland */ - if (so->so_proto->pr_domain->dom_family != AF_UNIX) { - fdrop(fp, td); - return (ESOCKTNOSUPPORT); - } - - pn = malloc(sizeof(struct portalnode), - M_TEMP, M_WAITOK); - - fmp = malloc(sizeof(struct portalmount), - M_PORTALFSMNT, M_WAITOK); /* XXX */ - - error = getnewvnode("portal", mp, &portal_vnodeops, &rvp); /* XXX */ - if (error) { - free(fmp, M_PORTALFSMNT); - free(pn, M_TEMP); - fdrop(fp, td); - return (error); - } - - error = insmntque(rvp, mp); /* XXX: Too early for mpsafe fs */ - if (error != 0) { - free(fmp, M_PORTALFSMNT); - free(pn, M_TEMP); - fdrop(fp, td); - return (error); - } - rvp->v_data = pn; - rvp->v_type = VDIR; - rvp->v_vflag |= VV_ROOT; - VTOPORTAL(rvp)->pt_arg = 0; - VTOPORTAL(rvp)->pt_size = 0; - VTOPORTAL(rvp)->pt_fileid = PORTAL_ROOTFILEID; - fmp->pm_root = rvp; - fhold(fp); - fmp->pm_server = fp; - - MNT_ILOCK(mp); - mp->mnt_flag |= MNT_LOCAL; - MNT_IUNLOCK(mp); - mp->mnt_data = fmp; - vfs_getnewfsid(mp); - - vfs_mountedfrom(mp, p); - fdrop(fp, td); - return (0); -} - -static int -portal_unmount(mp, mntflags) - struct mount *mp; - int mntflags; -{ - int error, flags = 0; - - - if (mntflags & MNT_FORCE) - flags |= FORCECLOSE; - - /* - * Clear out buffer cache. I don't think we - * ever get anything cached at this level at the - * moment, but who knows... - */ -#ifdef notyet - mntflushbuf(mp, 0); - if (mntinvalbuf(mp, 1)) - return (EBUSY); -#endif - /* There is 1 extra root vnode reference (pm_root). */ - error = vflush(mp, 1, flags, curthread); - if (error) - return (error); - - /* - * Shutdown the socket. This will cause the select in the - * daemon to wake up, and then the accept will get ECONNABORTED - * which it interprets as a request to go and bury itself. - */ - soshutdown(VFSTOPORTAL(mp)->pm_server->f_data, 2); - /* - * Discard reference to underlying file. Must call closef because - * this may be the last reference. - */ - closef(VFSTOPORTAL(mp)->pm_server, (struct thread *) 0); - /* - * Finally, throw away the portalmount structure - */ - free(mp->mnt_data, M_PORTALFSMNT); /* XXX */ - mp->mnt_data = NULL; - return (0); -} - -static int -portal_root(mp, flags, vpp) - struct mount *mp; - int flags; - struct vnode **vpp; -{ - struct vnode *vp; - - /* - * Return locked reference to root. - */ - vp = VFSTOPORTAL(mp)->pm_root; - VREF(vp); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - *vpp = vp; - return (0); -} - -static int -portal_statfs(mp, sbp) - struct mount *mp; - struct statfs *sbp; -{ - - sbp->f_flags = 0; - sbp->f_bsize = DEV_BSIZE; - sbp->f_iosize = DEV_BSIZE; - sbp->f_blocks = 2; /* 1K to keep df happy */ - sbp->f_bfree = 0; - sbp->f_bavail = 0; - sbp->f_files = 1; /* Allow for "." */ - sbp->f_ffree = 0; /* See comments above */ - return (0); -} - -static struct vfsops portal_vfsops = { - .vfs_cmount = portal_cmount, - .vfs_mount = portal_mount, - .vfs_root = portal_root, - .vfs_statfs = portal_statfs, - .vfs_unmount = portal_unmount, -}; - -VFS_SET(portal_vfsops, portalfs, VFCF_SYNTHETIC); diff --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c deleted file mode 100644 index 6b70dae..0000000 --- a/sys/fs/portalfs/portal_vnops.c +++ /dev/null @@ -1,586 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. - * - * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95 - * - * $FreeBSD$ - */ - -/* - * Portal Filesystem - */ - -#include "opt_capsicum.h" - -#include <sys/param.h> -#include <sys/capability.h> -#include <sys/fcntl.h> -#include <sys/file.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/mount.h> -#include <sys/mutex.h> -#include <sys/namei.h> -#include <sys/proc.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/stat.h> -#include <sys/syscallsubr.h> -#include <sys/systm.h> -#include <sys/un.h> -#include <sys/unpcb.h> -#include <sys/vnode.h> - -#include <fs/portalfs/portal.h> - -#include <net/vnet.h> - -static int portal_fileid = PORTAL_ROOTFILEID+1; - -static void portal_closefd(struct thread *td, int fd); -static int portal_connect(struct socket *so, struct socket *so2); -static vop_getattr_t portal_getattr; -static vop_lookup_t portal_lookup; -static vop_open_t portal_open; -static vop_readdir_t portal_readdir; -static vop_reclaim_t portal_reclaim; -static vop_setattr_t portal_setattr; - -static void -portal_closefd(td, fd) - struct thread *td; - int fd; -{ - int error; - - error = kern_close(td, fd); - /* - * We should never get an error, and there isn't anything - * we could do if we got one, so just print a message. - */ - if (error) - printf("portal_closefd: error = %d\n", error); -} - -/* - * vp is the current namei directory - * cnp is the name to locate in that directory... - */ -static int -portal_lookup(ap) - struct vop_lookup_args /* { - struct vnode * a_dvp; - struct vnode ** a_vpp; - struct componentname * a_cnp; - } */ *ap; -{ - struct componentname *cnp = ap->a_cnp; - struct vnode **vpp = ap->a_vpp; - struct vnode *dvp = ap->a_dvp; - char *pname = cnp->cn_nameptr; - struct portalnode *pt; - int error; - struct vnode *fvp = NULL; - char *path; - int size; - - *vpp = NULLVP; - - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) - return (EROFS); - - if (cnp->cn_namelen == 1 && *pname == '.') { - *vpp = dvp; - VREF(dvp); - return (0); - } - KASSERT((cnp->cn_flags & ISDOTDOT) == 0, - ("portal_lookup: Can not handle dotdot lookups.")); - - /* - * Do the MALLOC before the getnewvnode since doing so afterward - * might cause a bogus v_data pointer to get dereferenced - * elsewhere if MALLOC should block. - */ - pt = malloc(sizeof(struct portalnode), - M_TEMP, M_WAITOK); - - error = getnewvnode("portal", dvp->v_mount, &portal_vnodeops, &fvp); - if (error) { - free(pt, M_TEMP); - goto bad; - } - fvp->v_type = VREG; - fvp->v_data = pt; - /* - * Save all of the remaining pathname and - * advance the namei next pointer to the end - * of the string. - */ - for (size = 0, path = pname; *path; path++) - size++; - cnp->cn_consume = size - cnp->cn_namelen; - - pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK); - pt->pt_size = size+1; - bcopy(pname, pt->pt_arg, pt->pt_size); - pt->pt_fileid = portal_fileid++; - - *vpp = fvp; - vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY); - error = insmntque(fvp, dvp->v_mount); - if (error != 0) { - *vpp = NULLVP; - return (error); - } - return (0); - -bad:; - if (fvp) - vrele(fvp); - return (error); -} - -static int -portal_connect(so, so2) - struct socket *so; - struct socket *so2; -{ - /* from unp_connect, bypassing the namei stuff... */ - struct socket *so3; - struct unpcb *unp2; - struct unpcb *unp3; - - if (so2 == 0) - return (ECONNREFUSED); - - if (so->so_type != so2->so_type) - return (EPROTOTYPE); - - if ((so2->so_options & SO_ACCEPTCONN) == 0) - return (ECONNREFUSED); - - CURVNET_SET(so2->so_vnet); - if ((so3 = sonewconn(so2, 0)) == 0) { - CURVNET_RESTORE(); - return (ECONNREFUSED); - } - CURVNET_RESTORE(); - - unp2 = sotounpcb(so2); - unp3 = sotounpcb(so3); - if (unp2->unp_addr) - unp3->unp_addr = (struct sockaddr_un *) - sodupsockaddr((struct sockaddr *)unp2->unp_addr, - M_NOWAIT); - so2 = so3; - - return (soconnect2(so, so2)); -} - -static int -portal_open(ap) - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ - struct socket *so = NULL; - struct portalnode *pt; - struct thread *td = ap->a_td; - struct vnode *vp = ap->a_vp; - struct uio auio; - struct iovec aiov[2]; - int res; - struct mbuf *cm = NULL; - struct cmsghdr *cmsg; - int newfds; - int *ip; - int fd; - int error; - int len; - struct portalmount *fmp; - struct file *fp; - struct portal_cred pcred; - -#ifdef CAPABILITY_MODE - /* - * This may require access to a global namespace (e.g. an IP address); - * disallow it entirely, as we do open(2). - */ - if (IN_CAPABILITY_MODE(td)) { -#ifdef KTRACE - if (KTRPOINT(td, KTR_CAPFAIL)) - ktrcapfail(CAPFAIL_SYSCALL, 0, 0); -#endif - return (ECAPMODE); - } -#endif - - /* - * Nothing to do when opening the root node. - */ - if (vp->v_vflag & VV_ROOT) - return (0); - - /* - * Can't be opened unless the caller is set up - * to deal with the side effects. Check for this - * by testing whether td_dupfd has been set. - */ - if (td->td_dupfd >= 0) - return (ENODEV); - - pt = VTOPORTAL(vp); - fmp = VFSTOPORTAL(vp->v_mount); - - /* - * Create a new socket. - */ - error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, ap->a_cred, - ap->a_td); - if (error) - goto bad; - - /* - * Reserve some buffer space - */ - res = pt->pt_size + sizeof(pcred) + 512; /* XXX */ - error = soreserve(so, res, res); - if (error) - goto bad; - - /* - * Kick off connection - */ - error = portal_connect(so, fmp->pm_server->f_data); - if (error) - goto bad; - - /* - * Wait for connection to complete - */ - /* - * XXX: Since the mount point is holding a reference on the - * underlying server socket, it is not easy to find out whether - * the server process is still running. To handle this problem - * we loop waiting for the new socket to be connected (something - * which will only happen if the server is still running) or for - * the reference count on the server socket to drop to 1, which - * will happen if the server dies. Sleep for 5 second intervals - * and keep polling the reference count. XXX. - */ - SOCK_LOCK(so); - while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { - if (fmp->pm_server->f_count == 1) { - SOCK_UNLOCK(so); - error = ECONNREFUSED; - goto bad; - } - (void) msleep((caddr_t) &so->so_timeo, SOCK_MTX(so), PSOCK, - "portalcon", 5 * hz); - } - SOCK_UNLOCK(so); - - if (so->so_error) { - error = so->so_error; - goto bad; - } - - /* - * Set miscellaneous flags - */ - SOCKBUF_LOCK(&so->so_rcv); - so->so_rcv.sb_timeo = 0; - so->so_rcv.sb_flags |= SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); - so->so_snd.sb_timeo = 0; - so->so_snd.sb_flags |= SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_snd); - - - pcred.pcr_flag = ap->a_mode; - pcred.pcr_uid = ap->a_cred->cr_uid; - pcred.pcr_ngroups = MIN(ap->a_cred->cr_ngroups, XU_NGROUPS); - bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, - pcred.pcr_ngroups * sizeof(gid_t)); - aiov[0].iov_base = (caddr_t) &pcred; - aiov[0].iov_len = sizeof(pcred); - aiov[1].iov_base = pt->pt_arg; - aiov[1].iov_len = pt->pt_size; - auio.uio_iov = aiov; - auio.uio_iovcnt = 2; - auio.uio_rw = UIO_WRITE; - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_td = td; - auio.uio_offset = 0; - auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len; - - error = sosend(so, (struct sockaddr *) 0, &auio, - (struct mbuf *) 0, (struct mbuf *) 0, 0 , td); - if (error) - goto bad; - - len = auio.uio_resid = sizeof(int); - do { - struct mbuf *m = NULL; - int flags = MSG_WAITALL; - error = soreceive(so, (struct sockaddr **) 0, &auio, - &m, &cm, &flags); - if (error) - goto bad; - - /* - * Grab an error code from the mbuf. - */ - if (m) { - m = m_pullup(m, sizeof(int)); /* Needed? */ - if (m) { - error = *(mtod(m, int *)); - m_freem(m); - } else { - error = EINVAL; - } - } else { - if (cm == 0) { - error = ECONNRESET; /* XXX */ -#ifdef notdef - break; -#endif - } - } - } while (cm == 0 && auio.uio_resid == len && !error); - - if (cm == 0) - goto bad; - - if (auio.uio_resid) { - error = 0; -#ifdef notdef - error = EMSGSIZE; - goto bad; -#endif - } - - /* - * XXX: Break apart the control message, and retrieve the - * received file descriptor. Note that more than one descriptor - * may have been received, or that the rights chain may have more - * than a single mbuf in it. What to do? - */ - cmsg = mtod(cm, struct cmsghdr *); - newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int); - if (newfds == 0) { - error = ECONNREFUSED; - goto bad; - } - /* - * At this point the rights message consists of a control message - * header, followed by a data region containing a vector of - * integer file descriptors. The fds were allocated by the action - * of receiving the control message. - */ - ip = (int *) (cmsg + 1); - fd = *ip++; - if (newfds > 1) { - /* - * Close extra fds. - */ - int i; - printf("portal_open: %d extra fds\n", newfds - 1); - for (i = 1; i < newfds; i++) { - portal_closefd(td, *ip); - ip++; - } - } - - /* - * Check that the mode the file is being opened for is a subset - * of the mode of the existing descriptor. - */ - if ((error = fget(td, fd, 0, &fp)) != 0) - goto bad; - if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) { - fdrop(fp, td); - portal_closefd(td, fd); - error = EACCES; - goto bad; - } - fdrop(fp, td); - - /* - * Save the dup fd in the proc structure then return the - * special error code (ENXIO) which causes magic things to - * happen in vn_open. The whole concept is, well, hmmm. - */ - td->td_dupfd = fd; - error = ENXIO; - -bad:; - /* - * And discard the control message. - */ - if (cm) { - m_freem(cm); - } - - if (so) { - soshutdown(so, 2); - soclose(so); - } - return (error); -} - -static int -portal_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct vattr *vap = ap->a_vap; - - vap->va_uid = 0; - vap->va_gid = 0; - vap->va_size = DEV_BSIZE; - vap->va_blocksize = DEV_BSIZE; - nanotime(&vap->va_atime); - vap->va_mtime = vap->va_atime; - vap->va_ctime = vap->va_mtime; - vap->va_gen = 0; - vap->va_flags = 0; - vap->va_rdev = NODEV; - /* vap->va_qbytes = 0; */ - vap->va_bytes = 0; - vap->va_filerev = 0; - /* vap->va_qsize = 0; */ - if (vp->v_vflag & VV_ROOT) { - vap->va_type = VDIR; - vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR| - S_IRGRP|S_IWGRP|S_IXGRP| - S_IROTH|S_IWOTH|S_IXOTH; - vap->va_nlink = 2; - vap->va_fileid = 2; - } else { - vap->va_type = VREG; - vap->va_mode = S_IRUSR|S_IWUSR| - S_IRGRP|S_IWGRP| - S_IROTH|S_IWOTH; - vap->va_nlink = 1; - vap->va_fileid = VTOPORTAL(vp)->pt_fileid; - } - return (0); -} - -static int -portal_setattr(ap) - struct vop_setattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - } */ *ap; -{ - - /* - * Can't mess with the root vnode - */ - if (ap->a_vp->v_vflag & VV_ROOT) - return (EACCES); - - if (ap->a_vap->va_flags != VNOVAL) - return (EOPNOTSUPP); - - return (0); -} - -/* - * Fake readdir, just return empty directory. - * It is hard to deal with '.' and '..' so don't bother. - */ -static int -portal_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - u_long *a_cookies; - int a_ncookies; - } */ *ap; -{ - - /* - * We don't allow exporting portal mounts, and currently local - * requests do not need cookies. - */ - if (ap->a_ncookies) - panic("portal_readdir: not hungry"); - - return (0); -} - -static int -portal_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - struct portalnode *pt = VTOPORTAL(ap->a_vp); - - if (pt->pt_arg) { - free((caddr_t) pt->pt_arg, M_TEMP); - pt->pt_arg = 0; - } - free(ap->a_vp->v_data, M_TEMP); - ap->a_vp->v_data = 0; - - return (0); -} - -struct vop_vector portal_vnodeops = { - .vop_default = &default_vnodeops, - - .vop_access = VOP_NULL, - .vop_getattr = portal_getattr, - .vop_lookup = portal_lookup, - .vop_open = portal_open, - .vop_pathconf = vop_stdpathconf, - .vop_readdir = portal_readdir, - .vop_reclaim = portal_reclaim, - .vop_setattr = portal_setattr, -}; |