diff options
Diffstat (limited to 'sys/fs')
57 files changed, 981 insertions, 707 deletions
diff --git a/sys/fs/coda/cnode.h b/sys/fs/coda/cnode.h index 8506404..27531a4 100644 --- a/sys/fs/coda/cnode.h +++ b/sys/fs/coda/cnode.h @@ -94,7 +94,7 @@ extern int coda_vfsop_print_entry; struct cnode { struct vnode *c_vnode; u_short c_flags; /* flags (see below) */ - CodaFid c_fid; /* file handle */ + 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 */ @@ -196,7 +196,8 @@ void coda_unmounting(struct mount *whoIam); int coda_vmflush(struct cnode *cp); /* cfs_vnodeops.h */ -struct cnode *make_coda_node(CodaFid *fid, struct mount *vfsp, short type); +struct cnode *make_coda_node(struct CodaFid *fid, struct mount *vfsp, + short type); int coda_vnodeopstats_init(void); /* sigh */ diff --git a/sys/fs/coda/coda.h b/sys/fs/coda/coda.h index 93547a4..ee1e760 100644 --- a/sys/fs/coda/coda.h +++ b/sys/fs/coda/coda.h @@ -103,6 +103,8 @@ struct timespec { }; #endif +typedef u_int32_t cuid_t; +typedef u_int32_t cgid_t; /* * Cfs constants @@ -132,14 +134,13 @@ struct timespec { #define C_A_F_OK 0 /* Test for existence. */ - #ifndef _VENUS_DIRENT_T_ #define _VENUS_DIRENT_T_ 1 struct venus_dirent { - unsigned long d_fileno; /* file number of entry */ + unsigned int d_fileno; /* file number of entry */ unsigned short d_reclen; /* length of this record */ - char d_type; /* file type, see below */ - char d_namlen; /* length of string in d_name */ + 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 @@ -169,19 +170,19 @@ struct venus_dirent { #ifdef CODA_COMPAT_5 -typedef struct { +struct CodaFid { u_long Volume; u_long Vnode; u_long Unique; -} CodaFid; +}; -static __inline__ ino_t coda_f2i(CodaFid *fid) +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(CodaFid *fid) +static __inline__ char * coda_f2s(struct CodaFid *fid) { static char fid_str [35]; snprintf (fid_str, 35, "[%lx.%lx.%lx]", fid->Volume, @@ -189,7 +190,7 @@ static __inline__ char * coda_f2s(CodaFid *fid) return fid_str; } -static __inline__ int coda_fid_eq (CodaFid *fid1, CodaFid *fid2) +static __inline__ int coda_fid_eq (struct CodaFid *fid1, struct CodaFid *fid2) { return (fid1->Volume == fid2->Volume && fid1->Vnode == fid2->Vnode && @@ -203,18 +204,18 @@ struct coda_cred { #else /* CODA_COMPAT_5 */ -typedef struct { +struct CodaFid { u_int32_t opaque[4]; -} CodaFid; +}; -static __inline__ ino_t coda_f2i(CodaFid *fid) +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(CodaFid *fid) +static __inline__ char * coda_f2s(struct CodaFid *fid) { static char fid_str [35]; snprintf (fid_str, 35, "[%x.%x.%x.%x]", fid->opaque[0], @@ -222,7 +223,7 @@ static __inline__ char * coda_f2s(CodaFid *fid) return fid_str; } -static __inline__ int coda_fid_eq (CodaFid *fid1, CodaFid *fid2) +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] && @@ -240,11 +241,11 @@ static __inline__ int coda_fid_eq (CodaFid *fid1, CodaFid *fid2) enum coda_vtype { C_VNON, C_VREG, C_VDIR, C_VBLK, C_VCHR, C_VLNK, C_VSOCK, C_VFIFO, C_VBAD }; struct coda_vattr { - int va_type; /* vnode type (for create) */ + long va_type; /* vnode type (for create) */ u_short va_mode; /* files access mode and type */ short va_nlink; /* number of references to file */ - uid_t va_uid; /* owner user id */ - gid_t va_gid; /* owner group id */ + 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 */ @@ -313,7 +314,7 @@ struct coda_statfs { #define VC_MAXMSGSIZE sizeof(union inputArgs)+sizeof(union outputArgs) +\ VC_MAXDATASIZE -#define CIOC_KERNEL_VERSION _IOWR('c', 10, sizeof (int)) +#define CIOC_KERNEL_VERSION _IOWR('c', 10, int) #if 0 /* don't care about kernel version number */ #define CODA_KERNEL_VERSION 0 @@ -344,23 +345,23 @@ struct coda_in_hdr { struct coda_in_hdr { u_int32_t opcode; u_int32_t unique; /* Keep multiple outstanding msgs distinct */ - pid_t pid; /* Common to all */ - pid_t pgid; /* Common to all */ - uid_t uid; /* Common to all */ + pid_t pid; + pid_t pgid; + cuid_t uid; }; #endif /* Really important that opcode and unique are 1st two fields! */ struct coda_out_hdr { - unsigned long opcode; - unsigned long unique; - unsigned long result; + 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; - CodaFid Fid; + struct CodaFid Fid; }; struct coda_root_in { @@ -373,7 +374,7 @@ struct coda_root_in { /* coda_open: */ struct coda_open_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; int flags; }; @@ -387,7 +388,7 @@ struct coda_open_out { /* coda_close: */ struct coda_close_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; int flags; }; @@ -398,7 +399,7 @@ struct coda_close_out { /* coda_ioctl: */ struct coda_ioctl_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; int cmd; int len; int rwflag; @@ -415,7 +416,7 @@ struct coda_ioctl_out { /* coda_getattr: */ struct coda_getattr_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; }; struct coda_getattr_out { @@ -427,7 +428,7 @@ struct coda_getattr_out { /* coda_setattr: NO_OUT */ struct coda_setattr_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; struct coda_vattr attr; }; @@ -438,7 +439,7 @@ struct coda_setattr_out { /* coda_access: NO_OUT */ struct coda_access_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; int flags; }; @@ -454,14 +455,14 @@ struct coda_access_out { /* coda_lookup: */ struct coda_lookup_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; int name; /* Place holder for data. */ int flags; }; struct coda_lookup_out { struct coda_out_hdr oh; - CodaFid Fid; + struct CodaFid Fid; int vtype; }; @@ -469,7 +470,7 @@ struct coda_lookup_out { /* coda_create: */ struct coda_create_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; struct coda_vattr attr; int excl; int mode; @@ -478,7 +479,7 @@ struct coda_create_in { struct coda_create_out { struct coda_out_hdr oh; - CodaFid Fid; + struct CodaFid Fid; struct coda_vattr attr; }; @@ -486,7 +487,7 @@ struct coda_create_out { /* coda_remove: NO_OUT */ struct coda_remove_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; int name; /* Place holder for data. */ }; @@ -497,8 +498,8 @@ struct coda_remove_out { /* coda_link: NO_OUT */ struct coda_link_in { struct coda_in_hdr ih; - CodaFid sourceFid; /* cnode to link *to* */ - CodaFid destFid; /* Directory in which to place link */ + struct CodaFid sourceFid; /* cnode to link *to* */ + struct CodaFid destFid; /* Directory in which to place link */ int tname; /* Place holder for data. */ }; @@ -510,9 +511,9 @@ struct coda_link_out { /* coda_rename: NO_OUT */ struct coda_rename_in { struct coda_in_hdr ih; - CodaFid sourceFid; + struct CodaFid sourceFid; int srcname; - CodaFid destFid; + struct CodaFid destFid; int destname; }; @@ -523,14 +524,14 @@ struct coda_rename_out { /* coda_mkdir: */ struct coda_mkdir_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; struct coda_vattr attr; int name; /* Place holder for data. */ }; struct coda_mkdir_out { struct coda_out_hdr oh; - CodaFid Fid; + struct CodaFid Fid; struct coda_vattr attr; }; @@ -538,7 +539,7 @@ struct coda_mkdir_out { /* coda_rmdir: NO_OUT */ struct coda_rmdir_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; int name; /* Place holder for data. */ }; @@ -549,7 +550,7 @@ struct coda_rmdir_out { /* coda_readdir: */ struct coda_readdir_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; int count; int offset; }; @@ -563,7 +564,7 @@ struct coda_readdir_out { /* coda_symlink: NO_OUT */ struct coda_symlink_in { struct coda_in_hdr ih; - CodaFid Fid; /* Directory to put symlink in */ + struct CodaFid Fid; /* Directory to put symlink in */ int srcname; struct coda_vattr attr; int tname; @@ -576,7 +577,7 @@ struct coda_symlink_out { /* coda_readlink: */ struct coda_readlink_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; }; struct coda_readlink_out { @@ -589,7 +590,7 @@ struct coda_readlink_out { /* coda_fsync: NO_OUT */ struct coda_fsync_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; }; struct coda_fsync_out { @@ -599,18 +600,18 @@ struct coda_fsync_out { /* coda_inactive: NO_OUT */ struct coda_inactive_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; }; /* coda_vget: */ struct coda_vget_in { struct coda_in_hdr ih; - CodaFid Fid; + struct CodaFid Fid; }; struct coda_vget_out { struct coda_out_hdr oh; - CodaFid Fid; + struct CodaFid Fid; int vtype; }; @@ -626,7 +627,7 @@ struct coda_purgeuser_out { #ifdef CODA_COMPAT_5 struct coda_cred cred; #else - uid_t uid; + cuid_t uid; #endif }; @@ -634,14 +635,14 @@ struct coda_purgeuser_out { /* CODA_ZAPFILE is a venus->kernel call */ struct coda_zapfile_out { struct coda_out_hdr oh; - CodaFid Fid; + struct CodaFid Fid; }; /* coda_zapdir: */ /* CODA_ZAPDIR is a venus->kernel call */ struct coda_zapdir_out { struct coda_out_hdr oh; - CodaFid Fid; + struct CodaFid Fid; }; /* coda_zapnode: */ @@ -651,41 +652,44 @@ struct coda_zapvnode_out { #ifdef CODA_COMPAT_5 struct coda_cred cred; #endif - CodaFid Fid; + struct CodaFid Fid; }; /* coda_purgefid: */ /* CODA_PURGEFID is a venus->kernel call */ struct coda_purgefid_out { struct coda_out_hdr oh; - CodaFid Fid; + 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; - CodaFid NewFid; - CodaFid OldFid; + struct CodaFid NewFid; + struct CodaFid OldFid; }; /* coda_open_by_fd: */ struct coda_open_by_fd_in { struct coda_in_hdr ih; - CodaFid Fid; + 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; - CodaFid Fid; + struct CodaFid Fid; int flags; }; @@ -799,6 +803,9 @@ struct PioctlData { #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" @@ -810,10 +817,9 @@ struct PioctlData { #define INVAL_FID { 0, 0, 0 } #else #define CTL_FID { { -1, -1, -1, -1 } } -#define IS_CTL_FID(fidp) ((fidp)->opaque[0] == -1 &&\ - (fidp)->opaque[1] == -1 &&\ - (fidp)->opaque[2] == -1 &&\ - (fidp)->opaque[3] == -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 diff --git a/sys/fs/coda/coda_subr.c b/sys/fs/coda/coda_subr.c index e24950b..08c03cb 100644 --- a/sys/fs/coda/coda_subr.c +++ b/sys/fs/coda/coda_subr.c @@ -164,7 +164,7 @@ coda_unsave(struct cnode *cp) * NOTE: this allows multiple cnodes with same fid -- dcs 1/25/95 */ struct cnode * -coda_find(CodaFid *fid) +coda_find(struct CodaFid *fid) { struct cnode *cp; diff --git a/sys/fs/coda/coda_subr.h b/sys/fs/coda/coda_subr.h index 0efc081..b8edfd3 100644 --- a/sys/fs/coda/coda_subr.h +++ b/sys/fs/coda/coda_subr.h @@ -35,7 +35,7 @@ struct cnode *coda_alloc(void); void coda_free(struct cnode *cp); -struct cnode *coda_find(CodaFid *fid); +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); diff --git a/sys/fs/coda/coda_venus.c b/sys/fs/coda/coda_venus.c index b5e3b96..9999d3a 100644 --- a/sys/fs/coda/coda_venus.c +++ b/sys/fs/coda/coda_venus.c @@ -177,7 +177,7 @@ int coda_kernel_version = CODA_KERNEL_VERSION; int venus_root(void *mdp, struct ucred *cred, struct proc *p, - /*out*/ CodaFid *VFid) + /*out*/ struct CodaFid *VFid) { DECL_NO_IN(coda_root); /* sets Isize & Osize */ ALLOC_NO_IN(coda_root); /* sets inp & outp */ @@ -194,7 +194,7 @@ venus_root(void *mdp, struct ucred *cred, struct proc *p, } int -venus_open(void *mdp, CodaFid *fid, int flag, struct ucred *cred, +venus_open(void *mdp, struct CodaFid *fid, int flag, struct ucred *cred, struct proc *p, /*out*/ struct vnode **vp) { int cflag; @@ -215,7 +215,7 @@ venus_open(void *mdp, CodaFid *fid, int flag, struct ucred *cred, } int -venus_close(void *mdp, CodaFid *fid, int flag, struct ucred *cred, +venus_close(void *mdp, struct CodaFid *fid, int flag, struct ucred *cred, struct proc *p) { int cflag; @@ -252,7 +252,7 @@ venus_write(void) * normal files. */ int -venus_ioctl(void *mdp, CodaFid *fid, int com, int flag, caddr_t data, +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 */ @@ -304,7 +304,8 @@ venus_ioctl(void *mdp, CodaFid *fid, int com, int flag, caddr_t data, } int -venus_getattr(void *mdp, CodaFid *fid, struct ucred *cred, struct vattr *vap) +venus_getattr(void *mdp, struct CodaFid *fid, struct ucred *cred, + struct vattr *vap) { struct proc *p; DECL(coda_getattr); /* sets Isize & Osize */ @@ -326,7 +327,8 @@ venus_getattr(void *mdp, CodaFid *fid, struct ucred *cred, struct vattr *vap) } int -venus_setattr(void *mdp, CodaFid *fid, struct vattr *vap, struct ucred *cred) +venus_setattr(void *mdp, struct CodaFid *fid, struct vattr *vap, + struct ucred *cred) { struct proc *p; DECL_NO_OUT(coda_setattr); /* sets Isize & Osize */ @@ -347,8 +349,8 @@ venus_setattr(void *mdp, CodaFid *fid, struct vattr *vap, struct ucred *cred) } int -venus_access(void *mdp, CodaFid *fid, accmode_t accmode, struct ucred *cred, - struct proc *p) +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 */ @@ -374,8 +376,8 @@ venus_access(void *mdp, CodaFid *fid, accmode_t accmode, struct ucred *cred, } int -venus_readlink(void *mdp, CodaFid *fid, struct ucred *cred, struct proc *p, - /*out*/ char **str, int *len) +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; @@ -400,7 +402,7 @@ venus_readlink(void *mdp, CodaFid *fid, struct ucred *cred, struct proc *p, } int -venus_fsync(void *mdp, CodaFid *fid, struct proc *p) +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 */ @@ -420,8 +422,9 @@ venus_fsync(void *mdp, CodaFid *fid, struct proc *p) } int -venus_lookup(void *mdp, CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p, /*out*/ CodaFid *VFid, int *vtype) +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; @@ -457,9 +460,9 @@ venus_lookup(void *mdp, CodaFid *fid, const char *nm, int len, } int -venus_create(void *mdp, CodaFid *fid, const char *nm, int len, int exclusive, - int mode, struct vattr *va, struct ucred *cred, struct proc *p, - /*out*/ CodaFid *VFid, struct vattr *attr) +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; @@ -488,7 +491,7 @@ venus_create(void *mdp, CodaFid *fid, const char *nm, int len, int exclusive, } int -venus_remove(void *mdp, CodaFid *fid, const char *nm, int len, +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 */ @@ -511,8 +514,8 @@ venus_remove(void *mdp, CodaFid *fid, const char *nm, int len, } int -venus_link(void *mdp, CodaFid *fid, CodaFid *tfid, const char *nm, int len, - struct ucred *cred, struct proc *p) +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; @@ -535,8 +538,9 @@ venus_link(void *mdp, CodaFid *fid, CodaFid *tfid, const char *nm, int len, } int -venus_rename(void *mdp, CodaFid *fid, CodaFid *tfid, const char *nm, int len, - const char *tnm, int tlen, struct ucred *cred, struct proc *p) +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; @@ -562,9 +566,9 @@ venus_rename(void *mdp, CodaFid *fid, CodaFid *tfid, const char *nm, int len, } int -venus_mkdir(void *mdp, CodaFid *fid, const char *nm, int len, +venus_mkdir(void *mdp, struct CodaFid *fid, const char *nm, int len, struct vattr *va, struct ucred *cred, struct proc *p, - /*out*/ CodaFid *VFid, struct vattr *ova) + /*out*/ struct CodaFid *VFid, struct vattr *ova) { DECL(coda_mkdir); /* sets Isize & Osize */ coda_mkdir_size += len + 1; @@ -591,7 +595,7 @@ venus_mkdir(void *mdp, CodaFid *fid, const char *nm, int len, } int -venus_rmdir(void *mdp, CodaFid *fid, const char *nm, int len, +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 */ @@ -614,7 +618,7 @@ venus_rmdir(void *mdp, CodaFid *fid, const char *nm, int len, } int -venus_symlink(void *mdp, CodaFid *fid, const char *lnm, int llen, +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) { @@ -645,7 +649,7 @@ venus_symlink(void *mdp, CodaFid *fid, const char *lnm, int llen, * XXX: Unused. */ int -venus_readdir(void *mdp, CodaFid *fid, int count, int offset, +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 */ @@ -672,8 +676,8 @@ venus_readdir(void *mdp, CodaFid *fid, int count, int offset, } int -venus_fhtovp(void *mdp, CodaFid *fid, struct ucred *cred, struct proc *p, - /*out*/ CodaFid *VFid, int *vtype) +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 */ diff --git a/sys/fs/coda/coda_venus.h b/sys/fs/coda/coda_venus.h index 0d4dac0..95f1c57 100644 --- a/sys/fs/coda/coda_venus.h +++ b/sys/fs/coda/coda_venus.h @@ -34,49 +34,50 @@ #define _CODA_VENUS_H_ int venus_root(void *mdp, struct ucred *cred, struct proc *p, - /*out*/ CodaFid *VFid); -int venus_open(void *mdp, CodaFid *fid, int flag, struct ucred *cred, - struct proc *p, /*out*/ struct vnode **vp); -int venus_close(void *mdp, CodaFid *fid, int flag, 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, CodaFid *fid, int com, int flag, caddr_t data, - struct ucred *cred, struct proc *p); -int venus_getattr(void *mdp, CodaFid *fid, struct ucred *cred, +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, CodaFid *fid, struct vattr *vap, +int venus_setattr(void *mdp, struct CodaFid *fid, struct vattr *vap, struct ucred *cred); -int venus_access(void *mdp, CodaFid *fid, int mode, struct ucred *cred, - struct proc *p); -int venus_readlink(void *mdp, CodaFid *fid, 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, CodaFid *fid, struct proc *p); -int venus_lookup(void *mdp, CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p, /*out*/ CodaFid *VFid, +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, CodaFid *fid, const char *nm, int len, +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*/ CodaFid *VFid, struct vattr *attr); -int venus_remove(void *mdp, CodaFid *fid, const char *nm, int len, + 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, CodaFid *fid, CodaFid *tfid, const char *nm, - int len, struct ucred *cred, struct proc *p); -int venus_rename(void *mdp, CodaFid *fid, CodaFid *tfid, const char *nm, - int len, const char *tnm, int tlen, struct ucred *cred, - struct proc *p); -int venus_mkdir(void *mdp, CodaFid *fid, const char *nm, int len, +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*/ CodaFid *VFid, struct vattr *ova); -int venus_rmdir(void *mdp, CodaFid *fid, const char *nm, int len, + /*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_symlink(void *mdp, 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, CodaFid *fid, int count, int offset, +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, CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ CodaFid *VFid, int *vtype); +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 index b12c43b..90660c6 100644 --- a/sys/fs/coda/coda_vfsops.c +++ b/sys/fs/coda/coda_vfsops.c @@ -113,8 +113,8 @@ coda_mount(struct mount *vfsp) struct cdev *dev; struct coda_mntinfo *mi; struct vnode *rootvp; - CodaFid rootfid = INVAL_FID; - CodaFid ctlfid = CTL_FID; + struct CodaFid rootfid = INVAL_FID; + struct CodaFid ctlfid = CTL_FID; int error; struct nameidata ndp; ENTRY; @@ -268,8 +268,8 @@ coda_root(struct mount *vfsp, int flags, struct vnode **vpp) int error; struct proc *p; struct thread *td; - CodaFid VFid; - static const CodaFid invalfid = INVAL_FID; + struct CodaFid VFid; + static const struct CodaFid invalfid = INVAL_FID; td = curthread; p = td->td_proc; @@ -288,7 +288,7 @@ coda_root(struct mount *vfsp, int flags, struct vnode **vpp) * but not in any released versions as of 6 Mar 2003. */ if (memcmp(&VTOC(mi->mi_rootvp)->c_fid, &invalfid, - sizeof(CodaFid)) != 0 || mi->mi_started == 0) { + sizeof(struct CodaFid)) != 0 || mi->mi_started == 0) { /* * Found valid root. */ @@ -407,7 +407,7 @@ coda_fhtovp(struct mount *vfsp, struct fid *fhp, struct mbuf *nam, int error; struct thread *td = curthread; /* XXX -mach */ struct proc *p = td->td_proc; - CodaFid VFid; + struct CodaFid VFid; int vtype; ENTRY; diff --git a/sys/fs/coda/coda_vfsops.h b/sys/fs/coda/coda_vfsops.h index b51f4bc..e5b3a11 100644 --- a/sys/fs/coda/coda_vfsops.h +++ b/sys/fs/coda/coda_vfsops.h @@ -42,7 +42,7 @@ struct cfid { u_short cfid_len; u_short padding; - CodaFid cfid_fid; + struct CodaFid cfid_fid; }; struct mbuf; diff --git a/sys/fs/coda/coda_vnops.c b/sys/fs/coda/coda_vnops.c index edaba65..79d53e5 100644 --- a/sys/fs/coda/coda_vnops.c +++ b/sys/fs/coda/coda_vnops.c @@ -872,7 +872,7 @@ coda_lookup(struct vop_cachedlookup_args *ap) struct cnode *cp; const char *nm = cnp->cn_nameptr; int len = cnp->cn_namelen; - CodaFid VFid; + struct CodaFid VFid; int vtype; int error = 0; @@ -1009,7 +1009,7 @@ coda_create(struct vop_create_args *ap) struct cnode *cp; const char *nm = cnp->cn_nameptr; int len = cnp->cn_namelen; - CodaFid VFid; + struct CodaFid VFid; struct vattr attr; MARK_ENTRY(CODA_CREATE_STATS); @@ -1278,7 +1278,7 @@ coda_mkdir(struct vop_mkdir_args *ap) const char *nm = cnp->cn_nameptr; int len = cnp->cn_namelen; struct cnode *cp; - CodaFid VFid; + struct CodaFid VFid; struct vattr ova; MARK_ENTRY(CODA_MKDIR_STATS); @@ -1687,7 +1687,7 @@ coda_print_cred(struct ucred *cred) * coda_unsave. */ struct cnode * -make_coda_node(CodaFid *fid, struct mount *vfsp, short type) +make_coda_node(struct CodaFid *fid, struct mount *vfsp, short type) { struct cnode *cp; struct vnode *vp; diff --git a/sys/fs/deadfs/dead_vnops.c b/sys/fs/deadfs/dead_vnops.c index 7a07b38..e255654 100644 --- a/sys/fs/deadfs/dead_vnops.c +++ b/sys/fs/deadfs/dead_vnops.c @@ -225,13 +225,7 @@ dead_rename(ap) struct componentname *a_tcnp; } */ *ap; { - if (ap->a_tvp) - vput(ap->a_tvp); - if (ap->a_tdvp == ap->a_tvp) - vrele(ap->a_tdvp); - else - vput(ap->a_tdvp); - vrele(ap->a_fdvp); - vrele(ap->a_fvp); + + vop_rename_fail(ap); return (EXDEV); } diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index 07b2547..43cf65e 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -522,11 +522,10 @@ fdesc_readdir(ap) FILEDESC_SLOCK(fdp); while (i < fdp->fd_nfiles + 2 && uio->uio_resid >= UIO_MX) { + bzero((caddr_t)dp, UIO_MX); switch (i) { case 0: /* `.' */ case 1: /* `..' */ - bzero((caddr_t)dp, UIO_MX); - dp->d_fileno = i + FD_ROOT; dp->d_namlen = i + 1; dp->d_reclen = UIO_MX; @@ -535,26 +534,24 @@ fdesc_readdir(ap) dp->d_type = DT_DIR; break; default: - if (fdp->fd_ofiles[fcnt] == NULL) { - FILEDESC_SUNLOCK(fdp); - goto done; - } - - bzero((caddr_t) dp, UIO_MX); + if (fdp->fd_ofiles[fcnt] == NULL) + break; dp->d_namlen = sprintf(dp->d_name, "%d", fcnt); dp->d_reclen = UIO_MX; dp->d_type = DT_UNKNOWN; dp->d_fileno = i + FD_DESC; break; } - /* - * And ship to userland - */ - FILEDESC_SUNLOCK(fdp); - error = uiomove(dp, UIO_MX, uio); - if (error) - goto done; - FILEDESC_SLOCK(fdp); + if (dp->d_namlen != 0) { + /* + * And ship to userland + */ + FILEDESC_SUNLOCK(fdp); + error = uiomove(dp, UIO_MX, uio); + if (error) + goto done; + FILEDESC_SLOCK(fdp); + } i++; fcnt++; } diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c index ce5048a..999125d 100644 --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -125,14 +125,14 @@ msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp, #endif dp = VTODE(vdp); pmp = dp->de_pmp; - if (vpp != NULL) - *vpp = NULL; #ifdef MSDOSFS_DEBUG printf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n", vdp, dp, dp->de_Attributes); #endif restart: + if (vpp != NULL) + *vpp = NULL; /* * If they are going after the . or .. entry in the root directory, * they won't find it. DOS filesystems don't have them in the root @@ -525,8 +525,10 @@ foundroot: pdp = vdp; if (flags & ISDOTDOT) { error = msdosfs_deget_dotdot(pdp, cluster, blkoff, vpp); - if (error) + if (error) { + *vpp = NULL; return (error); + } /* * Recheck that ".." still points to the inode we * looked up before pdp lock was dropped. @@ -534,6 +536,7 @@ foundroot: error = msdosfs_lookup_(pdp, NULL, cnp, &inode1); if (error) { vput(*vpp); + *vpp = NULL; return (error); } if (VTODE(*vpp)->de_inode != inode1) { diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index 20a4dbd..a0801bd 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -383,10 +383,9 @@ msdosfs_mount(struct mount *mp) pmp = VFSTOMSDOSFS(mp); #endif } else { + vput(devvp); if (devvp != pmp->pm_devvp) - error = EINVAL; /* XXX needs translation */ - else - vput(devvp); + return (EINVAL); /* XXX needs translation */ } if (error) { vrele(devvp); @@ -581,6 +580,7 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp) || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) || (pmp->pm_HugeSectors == 0) || (pmp->pm_FATsecs == 0) + || (SecPerClust * pmp->pm_BlkPerSec > MAXBSIZE / DEV_BSIZE) ) { error = EINVAL; goto error_exit; diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index 8b6ada3..384bdb4 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -650,7 +650,7 @@ tryagain: trylater_delay = NFS_TRYLATERDEL; waituntil = NFSD_MONOSEC + trylater_delay; while (NFSD_MONOSEC < waituntil) - (void) nfs_catnap(PZERO, "nfstry"); + (void) nfs_catnap(PZERO, 0, "nfstry"); trylater_delay *= 2; goto tryagain; } diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index 7f27494..2676566 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -82,7 +82,8 @@ SYSCTL_STRING(_vfs_newnfs, OID_AUTO, callback_addr, CTLFLAG_RW, */ MALLOC_DEFINE(M_NEWNFSRVCACHE, "NFSD srvcache", "NFSD Server Request Cache"); MALLOC_DEFINE(M_NEWNFSDCLIENT, "NFSD V4client", "NFSD V4 Client Id"); -MALLOC_DEFINE(M_NEWNFSDSTATE, "NFSD V4state", "NFSD V4 State (Openowner, Open, Lockowner, Delegation"); +MALLOC_DEFINE(M_NEWNFSDSTATE, "NFSD V4state", + "NFSD V4 State (Openowner, Open, Lockowner, Delegation"); MALLOC_DEFINE(M_NEWNFSDLOCK, "NFSD V4lock", "NFSD V4 byte range lock"); MALLOC_DEFINE(M_NEWNFSDLOCKFILE, "NFSD lckfile", "NFSD Open/Lock file"); MALLOC_DEFINE(M_NEWNFSSTRING, "NFSD string", "NFSD V4 long string"); @@ -97,7 +98,10 @@ MALLOC_DEFINE(M_NEWNFSCLLOCKOWNER, "NFSCL lckown", "NFSCL Lock Owner"); MALLOC_DEFINE(M_NEWNFSCLLOCK, "NFSCL lck", "NFSCL Lock"); MALLOC_DEFINE(M_NEWNFSV4NODE, "NEWNFSnode", "New nfs vnode"); MALLOC_DEFINE(M_NEWNFSDIRECTIO, "NEWdirectio", "New nfs Direct IO buffer"); -MALLOC_DEFINE(M_NEWNFSDIROFF, "Newnfscl_diroff", "New NFS directory offset data"); +MALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL diroffdiroff", + "New NFS directory offset data"); +MALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback", + "New NFS local lock rollback"); /* * Definition of mutex locks. @@ -117,7 +121,7 @@ struct mtx nfs_slock_mutex; /* local functions */ static int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *); -#if defined(__i386__) +#ifdef __NO_STRICT_ALIGNMENT /* * These architectures don't need re-alignment, so just return. */ @@ -127,7 +131,7 @@ newnfs_realign(struct mbuf **pm) return; } -#else +#else /* !__NO_STRICT_ALIGNMENT */ /* * newnfs_realign: * @@ -185,7 +189,7 @@ newnfs_realign(struct mbuf **pm) pm = &m->m_next; } } -#endif /* !__i386__ */ +#endif /* __NO_STRICT_ALIGNMENT */ #ifdef notdef static void @@ -221,6 +225,8 @@ void newnfs_copycred(struct nfscred *nfscr, struct ucred *cr) { + KASSERT(nfscr->nfsc_ngroups >= 0, + ("newnfs_copycred: negative nfsc_ngroups")); cr->cr_uid = nfscr->nfsc_uid; crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); } @@ -339,17 +345,21 @@ newnfs_timer(void *arg) /* - * sleep for a short period of time. + * Sleep for a short period of time unless errval == NFSERR_GRACE, where + * the sleep should be for 5 seconds. * Since lbolt doesn't exist in FreeBSD-CURRENT, just use a timeout on * an event that never gets a wakeup. Only return EINTR or 0. */ int -nfs_catnap(int prio, const char *wmesg) +nfs_catnap(int prio, int errval, const char *wmesg) { static int non_event; int ret; - ret = tsleep(&non_event, prio, wmesg, 1); + if (errval == NFSERR_GRACE) + ret = tsleep(&non_event, prio, wmesg, 5 * hz); + else + ret = tsleep(&non_event, prio, wmesg, 1); if (ret != EINTR) ret = 0; return (ret); diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 8e53ae6..dc5b2dc 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -1824,6 +1824,19 @@ nfsv4_getref(struct nfsv4lock *lp, int *isleptp, void *mutex) } /* + * Test for a lock. Return 1 if locked, 0 otherwise. + */ +APPLESTATIC int +nfsv4_testlock(struct nfsv4lock *lp) +{ + + if ((lp->nfslock_lock & NFSV4LOCK_LOCK) == 0 && + lp->nfslock_usecnt == 0) + return (0); + return (1); +} + +/* * Wake up anyone sleeping, waiting for this lock. */ static void diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index 17714d7..d6ecda2 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -251,6 +251,7 @@ int nfsv4_lock(struct nfsv4lock *, int, int *, void *); void nfsv4_unlock(struct nfsv4lock *, int); void nfsv4_relref(struct nfsv4lock *); void nfsv4_getref(struct nfsv4lock *, int *, void *); +int nfsv4_testlock(struct nfsv4lock *); int nfsrv_mtostr(struct nfsrv_descript *, char *, int); int nfsrv_checkutf8(u_int8_t *, int); int newnfs_sndlock(int *); @@ -321,7 +322,7 @@ int nfsvno_v4rootexport(struct nfsrv_descript *); void newnfs_portinit(void); struct ucred *newnfs_getcred(void); void newnfs_setroot(struct ucred *); -int nfs_catnap(int, const char *); +int nfs_catnap(int, int, const char *); struct nfsreferral *nfsv4root_getreferral(vnode_t, vnode_t, u_int32_t); int nfsrv_atroot(vnode_t, long *); void newnfs_timer(void *); @@ -368,7 +369,7 @@ int nfsrpc_readlink(vnode_t, struct uio *, struct ucred *, int nfsrpc_read(vnode_t, struct uio *, struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, void *); int nfsrpc_write(vnode_t, struct uio *, int *, u_char *, - struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, void *); + struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, void *, int); int nfsrpc_mknod(vnode_t, char *, int, struct vattr *, u_int32_t, enum vtype, struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *, struct nfsfh **, int *, int *, void *); @@ -501,7 +502,7 @@ int nfscl_maperr(NFSPROC_T *, int, uid_t, gid_t); void nfscl_init(void); /* nfs_clbio.c */ -int ncl_flush(vnode_t, int, struct ucred *, NFSPROC_T *, int); +int ncl_flush(vnode_t, int, struct ucred *, NFSPROC_T *, int, int); /* nfs_clnode.c */ void ncl_invalcaches(vnode_t); diff --git a/sys/fs/nfs/nfsclstate.h b/sys/fs/nfs/nfsclstate.h index 10747af..72d8eeb 100644 --- a/sys/fs/nfs/nfsclstate.h +++ b/sys/fs/nfs/nfsclstate.h @@ -74,6 +74,7 @@ struct nfsclclient { #define NFSCLFLAGS_EXPIREIT 0x0040 #define NFSCLFLAGS_FIRSTDELEG 0x0080 #define NFSCLFLAGS_GOTDELEG 0x0100 +#define NFSCLFLAGS_RECVRINPROG 0x0200 struct nfsclowner { LIST_ENTRY(nfsclowner) nfsow_list; @@ -140,6 +141,7 @@ struct nfsclopen { #define NFSCLOPEN_OK 0 #define NFSCLOPEN_DOOPEN 1 #define NFSCLOPEN_DOOPENDOWNGRADE 2 +#define NFSCLOPEN_SETCRED 3 struct nfscllockowner { LIST_ENTRY(nfscllockowner) nfsl_list; diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h index c7ef67c..0fa2e14 100644 --- a/sys/fs/nfs/nfsport.h +++ b/sys/fs/nfs/nfsport.h @@ -143,21 +143,21 @@ #define NFSMGET(m) do { \ MGET((m), M_TRYWAIT, MT_DATA); \ while ((m) == NULL ) { \ - (void) nfs_catnap(PZERO, "nfsmget"); \ + (void) nfs_catnap(PZERO, 0, "nfsmget"); \ MGET((m), M_TRYWAIT, MT_DATA); \ } \ } while (0) #define NFSMGETHDR(m) do { \ MGETHDR((m), M_TRYWAIT, MT_DATA); \ while ((m) == NULL ) { \ - (void) nfs_catnap(PZERO, "nfsmget"); \ + (void) nfs_catnap(PZERO, 0, "nfsmget"); \ MGETHDR((m), M_TRYWAIT, MT_DATA); \ } \ } while (0) #define NFSMCLGET(m, w) do { \ MGET((m), M_TRYWAIT, MT_DATA); \ while ((m) == NULL ) { \ - (void) nfs_catnap(PZERO, "nfsmget"); \ + (void) nfs_catnap(PZERO, 0, "nfsmget"); \ MGET((m), M_TRYWAIT, MT_DATA); \ } \ MCLGET((m), (w)); \ @@ -165,7 +165,7 @@ #define NFSMCLGETHDR(m, w) do { \ MGETHDR((m), M_TRYWAIT, MT_DATA); \ while ((m) == NULL ) { \ - (void) nfs_catnap(PZERO, "nfsmget"); \ + (void) nfs_catnap(PZERO, 0, "nfsmget"); \ MGETHDR((m), M_TRYWAIT, MT_DATA); \ } \ } while (0) @@ -539,6 +539,7 @@ void nfsrvd_rcv(struct socket *, void *, int); #define NFSSTATESPINLOCK extern struct mtx nfs_state_mutex #define NFSLOCKSTATE() mtx_lock(&nfs_state_mutex) #define NFSUNLOCKSTATE() mtx_unlock(&nfs_state_mutex) +#define NFSSTATEMUTEXPTR (&nfs_state_mutex) #define NFSREQSPINLOCK extern struct mtx nfs_req_mutex #define NFSLOCKREQ() mtx_lock(&nfs_req_mutex) #define NFSUNLOCKREQ() mtx_unlock(&nfs_req_mutex) @@ -674,6 +675,7 @@ MALLOC_DECLARE(M_NEWNFSDIROFF); MALLOC_DECLARE(M_NEWNFSV4NODE); MALLOC_DECLARE(M_NEWNFSDIRECTIO); MALLOC_DECLARE(M_NEWNFSMNT); +MALLOC_DECLARE(M_NEWNFSDROLLBACK); #define M_NFSRVCACHE M_NEWNFSRVCACHE #define M_NFSDCLIENT M_NEWNFSDCLIENT #define M_NFSDSTATE M_NEWNFSDSTATE @@ -692,6 +694,7 @@ MALLOC_DECLARE(M_NEWNFSMNT); #define M_NFSDIROFF M_NEWNFSDIROFF #define M_NFSV4NODE M_NEWNFSV4NODE #define M_NFSDIRECTIO M_NEWNFSDIRECTIO +#define M_NFSDROLLBACK M_NEWNFSDROLLBACK #define NFSINT_SIGMASK(set) \ (SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \ diff --git a/sys/fs/nfs/nfsrvstate.h b/sys/fs/nfs/nfsrvstate.h index 629b18c..964b998 100644 --- a/sys/fs/nfs/nfsrvstate.h +++ b/sys/fs/nfs/nfsrvstate.h @@ -185,6 +185,17 @@ struct nfslockconflict { }; /* + * This structure is used to keep track of local locks that might need + * to be rolled back. + */ +struct nfsrollback { + LIST_ENTRY(nfsrollback) rlck_list; + uint64_t rlck_first; + uint64_t rlck_end; + int rlck_type; +}; + +/* * This structure refers to a file for which lock(s) and/or open(s) exist. * Searched via hash table on file handle or found via the back pointer from an * open or lock owner. @@ -193,8 +204,12 @@ struct nfslockfile { LIST_HEAD(, nfsstate) lf_open; /* Open list */ LIST_HEAD(, nfsstate) lf_deleg; /* Delegation list */ LIST_HEAD(, nfslock) lf_lock; /* Lock list */ + LIST_HEAD(, nfslock) lf_locallock; /* Local lock list */ + LIST_HEAD(, nfsrollback) lf_rollback; /* Local lock rollback list */ LIST_ENTRY(nfslockfile) lf_hash; /* Hash list entry */ fhandle_t lf_fh; /* The file handle */ + struct nfsv4lock lf_locallock_lck; /* serialize local locking */ + int lf_usecount; /* Ref count for locking */ }; /* diff --git a/sys/fs/nfsclient/nfs.h b/sys/fs/nfsclient/nfs.h index 4b54286..c6071af 100644 --- a/sys/fs/nfsclient/nfs.h +++ b/sys/fs/nfsclient/nfs.h @@ -79,14 +79,16 @@ int ncl_biowrite(struct vnode *, struct uio *, int, struct ucred *); int ncl_vinvalbuf(struct vnode *, int, struct thread *, int); int ncl_asyncio(struct nfsmount *, struct buf *, struct ucred *, struct thread *); -int ncl_doio(struct vnode *, struct buf *, struct ucred *, struct thread *); +int ncl_doio(struct vnode *, struct buf *, struct ucred *, struct thread *, + int); void ncl_nhinit(void); void ncl_nhuninit(void); void ncl_nodelock(struct nfsnode *); void ncl_nodeunlock(struct nfsnode *); int ncl_getattrcache(struct vnode *, struct vattr *); int ncl_readrpc(struct vnode *, struct uio *, struct ucred *); -int ncl_writerpc(struct vnode *, struct uio *, struct ucred *, int *, int *); +int ncl_writerpc(struct vnode *, struct uio *, struct ucred *, int *, int *, + int); int ncl_readlinkrpc(struct vnode *, struct uio *, struct ucred *); int ncl_readdirrpc(struct vnode *, struct uio *, struct ucred *, struct thread *); diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c index d0dd2cc..2401c88 100644 --- a/sys/fs/nfsclient/nfs_clbio.c +++ b/sys/fs/nfsclient/nfs_clbio.c @@ -336,7 +336,7 @@ ncl_putpages(struct vop_putpages_args *ap) else iomode = NFSWRITE_FILESYNC; - error = ncl_writerpc(vp, &uio, cred, &iomode, &must_commit); + error = ncl_writerpc(vp, &uio, cred, &iomode, &must_commit, 0); pmap_qremove(kva, npages); relpbuf(bp, &ncl_pbuf_freecnt); @@ -554,7 +554,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; vfs_busy_pages(bp, 0); - error = ncl_doio(vp, bp, cred, td); + error = ncl_doio(vp, bp, cred, td, 0); if (error) { brelse(bp); return (error); @@ -583,7 +583,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; vfs_busy_pages(bp, 0); - error = ncl_doio(vp, bp, cred, td); + error = ncl_doio(vp, bp, cred, td, 0); if (error) { bp->b_ioflags |= BIO_ERROR; brelse(bp); @@ -609,7 +609,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; vfs_busy_pages(bp, 0); - error = ncl_doio(vp, bp, cred, td); + error = ncl_doio(vp, bp, cred, td, 0); if (error) { brelse(bp); } @@ -638,7 +638,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; vfs_busy_pages(bp, 0); - error = ncl_doio(vp, bp, cred, td); + error = ncl_doio(vp, bp, cred, td, 0); /* * no error + B_INVAL == directory EOF, * use the block. @@ -771,7 +771,7 @@ do_sync: uio.uio_td = td; iomode = NFSWRITE_FILESYNC; error = ncl_writerpc(vp, &uio, cred, &iomode, - &must_commit); + &must_commit, 0); KASSERT((must_commit == 0), ("ncl_directio_write: Did not commit write")); if (error) @@ -1122,7 +1122,7 @@ again: if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; vfs_busy_pages(bp, 0); - error = ncl_doio(vp, bp, cred, td); + error = ncl_doio(vp, bp, cred, td, 0); if (error) { brelse(bp); break; @@ -1523,7 +1523,7 @@ ncl_doio_directwrite(struct buf *bp) iomode = NFSWRITE_FILESYNC; uiop->uio_td = NULL; /* NULL since we're in nfsiod */ - ncl_writerpc(bp->b_vp, uiop, bp->b_wcred, &iomode, &must_commit); + ncl_writerpc(bp->b_vp, uiop, bp->b_wcred, &iomode, &must_commit, 0); KASSERT((must_commit == 0), ("ncl_doio_directwrite: Did not commit write")); free(iov_base, M_NFSDIRECTIO); free(uiop->uio_iov, M_NFSDIRECTIO); @@ -1550,7 +1550,8 @@ ncl_doio_directwrite(struct buf *bp) * synchronously or from an nfsiod. */ int -ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td) +ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td, + int called_from_strategy) { struct uio *uiop; struct nfsnode *np; @@ -1695,7 +1696,8 @@ ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td) else iomode = NFSWRITE_FILESYNC; - error = ncl_writerpc(vp, uiop, cr, &iomode, &must_commit); + error = ncl_writerpc(vp, uiop, cr, &iomode, &must_commit, + called_from_strategy); /* * When setting B_NEEDCOMMIT also set B_CLUSTEROK to try @@ -1732,6 +1734,12 @@ ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td) * the block is reused. This is indicated by setting * the B_DELWRI and B_NEEDCOMMIT flags. * + * EIO is returned by ncl_writerpc() to indicate a recoverable + * write error and is handled as above, except that + * B_EINTR isn't set. One cause of this is a stale stateid + * error for the RPC that indicates recovery is required, + * when called with called_from_strategy != 0. + * * If the buffer is marked B_PAGING, it does not reside on * the vp's paging queues so we cannot call bdirty(). The * bp in this case is not an NFS cache block so we should @@ -1760,7 +1768,8 @@ ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td) bdirty(bp); bp->b_flags &= ~B_DONE; } - if (error && (bp->b_flags & B_ASYNC) == 0) + if ((error == EINTR || error == ETIMEDOUT) && + (bp->b_flags & B_ASYNC) == 0) bp->b_flags |= B_EINTR; splx(s); } else { diff --git a/sys/fs/nfsclient/nfs_clnfsiod.c b/sys/fs/nfsclient/nfs_clnfsiod.c index 6649fc0..62ea4f8 100644 --- a/sys/fs/nfsclient/nfs_clnfsiod.c +++ b/sys/fs/nfsclient/nfs_clnfsiod.c @@ -278,9 +278,11 @@ nfssvc_iod(void *instance) (void)ncl_doio_directwrite(bp); } else { if (bp->b_iocmd == BIO_READ) - (void) ncl_doio(bp->b_vp, bp, bp->b_rcred, NULL); + (void) ncl_doio(bp->b_vp, bp, bp->b_rcred, + NULL, 0); else - (void) ncl_doio(bp->b_vp, bp, bp->b_wcred, NULL); + (void) ncl_doio(bp->b_vp, bp, bp->b_wcred, + NULL, 0); } mtx_lock(&ncl_iod_mutex); /* diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c index 6b2aa7a..c133742 100644 --- a/sys/fs/nfsclient/nfs_clnode.c +++ b/sys/fs/nfsclient/nfs_clnode.c @@ -199,7 +199,7 @@ ncl_inactive(struct vop_inactive_args *ap) * available for the writes. */ if (nfscl_mustflush(vp)) - (void) ncl_flush(vp, MNT_WAIT, NULL, ap->a_td, 1); + (void) ncl_flush(vp, MNT_WAIT, NULL, ap->a_td, 1, 0); (void) nfsrpc_close(vp, 1, ap->a_td); } diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c index e81c3bf..f39666d 100644 --- a/sys/fs/nfsclient/nfs_clport.c +++ b/sys/fs/nfsclient/nfs_clport.c @@ -978,6 +978,8 @@ newnfs_copyincred(struct ucred *cr, struct nfscred *nfscr) { int i; + KASSERT(cr->cr_ngroups >= 0, + ("newnfs_copyincred: negative cr_ngroups")); nfscr->nfsc_uid = cr->cr_uid; nfscr->nfsc_ngroups = MIN(cr->cr_ngroups, NFS_MAXGRPS + 1); for (i = 0; i < nfscr->nfsc_ngroups; i++) diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index 95943a9..a84a301 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -278,7 +278,13 @@ else printf(" fhl=0\n"); error = EIO; } newnfs_copyincred(cred, &op->nfso_cred); - } + } else if (ret == NFSCLOPEN_SETCRED) + /* + * This is a new local open on a delegation. It needs + * to have credentials so that an open can be done + * against the server during recovery. + */ + newnfs_copyincred(cred, &op->nfso_cred); /* * nfso_opencnt is the count of how many VOP_OPEN()s have @@ -292,7 +298,7 @@ else printf(" fhl=0\n"); nfscl_openrelease(op, error, newone); if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID || error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY) { - (void) nfs_catnap(PZERO, "nfs_open"); + (void) nfs_catnap(PZERO, error, "nfs_open"); } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) && clidrev != 0) { expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p); @@ -454,7 +460,7 @@ nfsrpc_openrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp, int fhlen, ret = nfsrpc_openconfirm(vp, newfhp, newfhlen, op, cred, p); if (ret == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfs_open"); + (void) nfs_catnap(PZERO, ret, "nfs_open"); } while (ret == NFSERR_DELAY); error = ret; } @@ -478,7 +484,7 @@ nfsrpc_openrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp, int fhlen, newfhlen, mode, op, name, namelen, &ndp, 0, 0x0, cred, p, syscred, 1); if (ret == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfs_open2"); + (void) nfs_catnap(PZERO, ret, "nfs_open2"); } while (ret == NFSERR_DELAY); if (ret) { if (ndp != NULL) @@ -618,6 +624,7 @@ nfsrpc_doclose(struct nfsmount *nmp, struct nfsclopen *op, NFSPROC_T *p) nd->nd_repstat == NFSERR_DELAY) && error == 0) (void) nfs_catnap(PZERO, + (int)nd->nd_repstat, "nfs_close"); } while ((nd->nd_repstat == NFSERR_GRACE || nd->nd_repstat == NFSERR_DELAY) && @@ -639,7 +646,7 @@ nfsrpc_doclose(struct nfsmount *nmp, struct nfsclopen *op, NFSPROC_T *p) do { error = nfscl_tryclose(op, tcred, nmp, p); if (error == NFSERR_GRACE) - (void) nfs_catnap(PZERO, "nfs_close"); + (void) nfs_catnap(PZERO, error, "nfs_close"); } while (error == NFSERR_GRACE); NFSLOCKCLSTATE(); nfscl_lockunlock(&op->nfso_own->nfsow_rwlock); @@ -993,7 +1000,7 @@ nfsrpc_setattr(vnode_t vp, struct vattr *vap, NFSACL_T *aclp, if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID || error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY || error == NFSERR_OLDSTATEID) { - (void) nfs_catnap(PZERO, "nfs_setattr"); + (void) nfs_catnap(PZERO, error, "nfs_setattr"); } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) && clidrev != 0) { expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p); @@ -1238,7 +1245,7 @@ nfsrpc_read(vnode_t vp, struct uio *uiop, struct ucred *cred, if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID || error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY || error == NFSERR_OLDSTATEID) { - (void) nfs_catnap(PZERO, "nfs_read"); + (void) nfs_catnap(PZERO, error, "nfs_read"); } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) && clidrev != 0) { expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p); @@ -1340,11 +1347,16 @@ nfsmout: /* * nfs write operation + * When called_from_strategy != 0, it should return EIO for an error that + * indicates recovery is in progress, so that the buffer will be left + * dirty and be written back to the server later. If it loops around, + * the recovery thread could get stuck waiting for the buffer and recovery + * will then deadlock. */ APPLESTATIC int nfsrpc_write(vnode_t vp, struct uio *uiop, int *iomode, u_char *verfp, struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, - void *stuff) + void *stuff, int called_from_strategy) { int error, expireret = 0, retrycnt, nostateid; u_int32_t clidrev = 0; @@ -1398,18 +1410,21 @@ nfscl_dumpstate(nmp, 1, 1, 0, 0); if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID || error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY || error == NFSERR_OLDSTATEID) { - (void) nfs_catnap(PZERO, "nfs_write"); + (void) nfs_catnap(PZERO, error, "nfs_write"); } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) && clidrev != 0) { expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p); } retrycnt++; - } while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID || - error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY || + } while (error == NFSERR_GRACE || error == NFSERR_DELAY || + ((error == NFSERR_STALESTATEID || + error == NFSERR_STALEDONTRECOVER) && called_from_strategy == 0) || (error == NFSERR_OLDSTATEID && retrycnt < 20) || ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) && expireret == 0 && clidrev != 0 && retrycnt < 4)); - if (error && retrycnt >= 4) + if (error != 0 && (retrycnt >= 4 || + ((error == NFSERR_STALESTATEID || + error == NFSERR_STALEDONTRECOVER) && called_from_strategy != 0))) error = EIO; if (NFSHASNFSV4(nmp) && p == NULL) NFSFREECRED(newcred); @@ -1722,7 +1737,7 @@ nfsrpc_create(vnode_t dvp, char *name, int namelen, struct vattr *vap, nfscl_ownerrelease(owp, error, newone, unlocked); if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID || error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY) { - (void) nfs_catnap(PZERO, "nfs_open"); + (void) nfs_catnap(PZERO, error, "nfs_open"); } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) && clidrev != 0) { expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p); @@ -1955,7 +1970,7 @@ nfsrpc_createv4(vnode_t dvp, char *name, int namelen, struct vattr *vap, ret = nfsrpc_openconfirm(dvp, nfhp->nfh_fh, nfhp->nfh_len, op, cred, p); if (ret == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfs_create"); + (void) nfs_catnap(PZERO, ret, "nfs_create"); } while (ret == NFSERR_DELAY); error = ret; } @@ -1977,7 +1992,7 @@ nfsrpc_createv4(vnode_t dvp, char *name, int namelen, struct vattr *vap, (NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), op, name, namelen, &dp, 0, 0x0, cred, p, 0, 1); if (ret == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfs_crt2"); + (void) nfs_catnap(PZERO, ret, "nfs_crt2"); } while (ret == NFSERR_DELAY); if (ret) { if (dp != NULL) @@ -3519,7 +3534,8 @@ nfsrpc_advlock(vnode_t vp, off_t size, int op, struct flock *fl, if ((nd->nd_repstat == NFSERR_GRACE || nd->nd_repstat == NFSERR_DELAY) && error == 0) - (void) nfs_catnap(PZERO, "nfs_advlock"); + (void) nfs_catnap(PZERO, (int)nd->nd_repstat, + "nfs_advlock"); } while ((nd->nd_repstat == NFSERR_GRACE || nd->nd_repstat == NFSERR_DELAY) && error == 0); } @@ -3556,7 +3572,7 @@ nfsrpc_advlock(vnode_t vp, off_t size, int op, struct flock *fl, if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID || error == NFSERR_STALEDONTRECOVER || error == NFSERR_STALECLIENTID || error == NFSERR_DELAY) { - (void) nfs_catnap(PZERO, "nfs_advlock"); + (void) nfs_catnap(PZERO, error, "nfs_advlock"); } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) && clidrev != 0) { expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p); diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index 568c5de..b6fad20 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -139,7 +139,7 @@ static void nfscl_freedeleg(struct nfscldeleghead *, struct nfscldeleg *); static int nfscl_errmap(struct nfsrv_descript *); static void nfscl_cleanup_common(struct nfsclclient *, u_int8_t *); static int nfscl_recalldeleg(struct nfsclclient *, struct nfsmount *, - struct nfscldeleg *, vnode_t, struct ucred *, NFSPROC_T *); + struct nfscldeleg *, vnode_t, struct ucred *, NFSPROC_T *, int); static void nfscl_freeopenowner(struct nfsclowner *, int); static void nfscl_cleandeleg(struct nfscldeleg *); static int nfscl_trydelegreturn(struct nfscldeleg *, struct ucred *, @@ -274,8 +274,13 @@ nfscl_open(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t amode, int usedeleg, *owpp = owp; if (opp != NULL) *opp = op; - if (retp != NULL) - *retp = NFSCLOPEN_OK; + if (retp != NULL) { + if (nfhp != NULL && dp != NULL && nop == NULL) + /* new local open on delegation */ + *retp = NFSCLOPEN_SETCRED; + else + *retp = NFSCLOPEN_OK; + } /* * Now, check the mode on the open and return the appropriate @@ -476,6 +481,13 @@ nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode, } /* + * Wait for recovery to complete. + */ + while ((clp->nfsc_flags & NFSCLFLAGS_RECVRINPROG)) + (void) nfsmsleep(&clp->nfsc_flags, NFSCLSTATEMUTEXPTR, + PZERO, "nfsrecvr", NULL); + + /* * First, look for a delegation. */ LIST_FOREACH(dp, NFSCLDELEGHASH(clp, nfhp, fhlen), nfsdl_hash) { @@ -772,7 +784,7 @@ nfscl_getcl(vnode_t vp, struct ucred *cred, NFSPROC_T *p, if (error == NFSERR_STALECLIENTID || error == NFSERR_STALEDONTRECOVER || error == NFSERR_CLIDINUSE) { - (void) nfs_catnap(PZERO, "nfs_setcl"); + (void) nfs_catnap(PZERO, error, "nfs_setcl"); } } while (((error == NFSERR_STALECLIENTID || error == NFSERR_STALEDONTRECOVER) && --trystalecnt > 0) || @@ -1773,6 +1785,7 @@ nfscl_recover(struct nfsclclient *clp, struct ucred *cred, NFSPROC_T *p) * block when trying to use state. */ NFSLOCKCLSTATE(); + clp->nfsc_flags |= NFSCLFLAGS_RECVRINPROG; do { igotlock = nfsv4_lock(&clp->nfsc_lock, 1, NULL, NFSCLSTATEMUTEXPTR); @@ -1789,9 +1802,10 @@ nfscl_recover(struct nfsclclient *clp, struct ucred *cred, NFSPROC_T *p) error == NFSERR_STALEDONTRECOVER) && --trycnt > 0); if (error) { nfscl_cleanclient(clp); - clp->nfsc_flags &= ~(NFSCLFLAGS_HASCLIENTID | - NFSCLFLAGS_RECOVER); NFSLOCKCLSTATE(); + clp->nfsc_flags &= ~(NFSCLFLAGS_HASCLIENTID | + NFSCLFLAGS_RECOVER | NFSCLFLAGS_RECVRINPROG); + wakeup(&clp->nfsc_flags); nfsv4_unlock(&clp->nfsc_lock, 0); NFSUNLOCKCLSTATE(); return; @@ -2032,7 +2046,7 @@ nfscl_recover(struct nfsclclient *clp, struct ucred *cred, NFSPROC_T *p) newnfs_copycred(&op->nfso_cred, tcred); error = nfscl_tryclose(op, tcred, nmp, p); if (error == NFSERR_GRACE) - (void) nfs_catnap(PZERO, "nfsexcls"); + (void) nfs_catnap(PZERO, error, "nfsexcls"); } while (error == NFSERR_GRACE); LIST_REMOVE(op, nfso_list); FREE((caddr_t)op, M_NFSCLOPEN); @@ -2045,13 +2059,15 @@ nfscl_recover(struct nfsclclient *clp, struct ucred *cred, NFSPROC_T *p) newnfs_copycred(&dp->nfsdl_cred, tcred); error = nfscl_trydelegreturn(dp, tcred, nmp, p); if (error == NFSERR_GRACE) - (void) nfs_catnap(PZERO, "nfsexdlg"); + (void) nfs_catnap(PZERO, error, "nfsexdlg"); } while (error == NFSERR_GRACE); TAILQ_REMOVE(&extra_deleg, dp, nfsdl_list); FREE((caddr_t)dp, M_NFSCLDELEG); } NFSLOCKCLSTATE(); + clp->nfsc_flags &= ~NFSCLFLAGS_RECVRINPROG; + wakeup(&clp->nfsc_flags); nfsv4_unlock(&clp->nfsc_lock, 0); NFSUNLOCKCLSTATE(); NFSFREECRED(tcred); @@ -2095,6 +2111,7 @@ nfscl_hasexpired(struct nfsclclient *clp, u_int32_t clidrev, NFSPROC_T *p) NFSUNLOCKCLSTATE(); return (0); } + clp->nfsc_flags |= NFSCLFLAGS_RECVRINPROG; NFSUNLOCKCLSTATE(); nmp = clp->nfsc_nmp; @@ -2111,6 +2128,7 @@ nfscl_hasexpired(struct nfsclclient *clp, u_int32_t clidrev, NFSPROC_T *p) * Clear out any state. */ nfscl_cleanclient(clp); + NFSLOCKCLSTATE(); clp->nfsc_flags &= ~(NFSCLFLAGS_HASCLIENTID | NFSCLFLAGS_RECOVER); } else { @@ -2124,14 +2142,15 @@ nfscl_hasexpired(struct nfsclclient *clp, u_int32_t clidrev, NFSPROC_T *p) * Expire the state for the client. */ nfscl_expireclient(clp, nmp, cred, p); + NFSLOCKCLSTATE(); clp->nfsc_flags |= NFSCLFLAGS_HASCLIENTID; clp->nfsc_flags &= ~NFSCLFLAGS_RECOVER; } - NFSFREECRED(cred); - clp->nfsc_flags &= ~NFSCLFLAGS_EXPIREIT; - NFSLOCKCLSTATE(); + clp->nfsc_flags &= ~(NFSCLFLAGS_EXPIREIT | NFSCLFLAGS_RECVRINPROG); + wakeup(&clp->nfsc_flags); nfsv4_unlock(&clp->nfsc_lock, 0); NFSUNLOCKCLSTATE(); + NFSFREECRED(cred); return (error); } @@ -2311,14 +2330,30 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p) struct ucred *cred; u_int32_t clidrev; int error, cbpathdown, islept, igotlock, ret, clearok; + uint32_t recover_done_time = 0; cred = newnfs_getcred(); + NFSLOCKCLSTATE(); clp->nfsc_flags |= NFSCLFLAGS_HASTHREAD; + NFSUNLOCKCLSTATE(); for(;;) { newnfs_setroot(cred); cbpathdown = 0; - if (clp->nfsc_flags & NFSCLFLAGS_RECOVER) - nfscl_recover(clp, cred, p); + if (clp->nfsc_flags & NFSCLFLAGS_RECOVER) { + /* + * Only allow one recover within 1/2 of the lease + * duration (nfsc_renew). + */ + if (recover_done_time < NFSD_MONOSEC) { + recover_done_time = NFSD_MONOSEC + + clp->nfsc_renew; + nfscl_recover(clp, cred, p); + } else { + NFSLOCKCLSTATE(); + clp->nfsc_flags &= ~NFSCLFLAGS_RECOVER; + NFSUNLOCKCLSTATE(); + } + } if (clp->nfsc_expire <= NFSD_MONOSEC && (clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID)) { clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew; @@ -2326,9 +2361,11 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p) error = nfsrpc_renew(clp, cred, p); if (error == NFSERR_CBPATHDOWN) cbpathdown = 1; - else if (error == NFSERR_STALECLIENTID) + else if (error == NFSERR_STALECLIENTID) { + NFSLOCKCLSTATE(); clp->nfsc_flags |= NFSCLFLAGS_RECOVER; - else if (error == NFSERR_EXPIRED) + NFSUNLOCKCLSTATE(); + } else if (error == NFSERR_EXPIRED) (void) nfscl_hasexpired(clp, clidrev, p); } @@ -2432,7 +2469,7 @@ tryagain: NFSUNLOCKCLSTATE(); newnfs_copycred(&dp->nfsdl_cred, cred); ret = nfscl_recalldeleg(clp, clp->nfsc_nmp, dp, - NULL, cred, p); + NULL, cred, p, 1); if (!ret) { nfscl_cleandeleg(dp); TAILQ_REMOVE(&clp->nfsc_deleg, dp, @@ -3272,7 +3309,8 @@ nfscl_lockt(vnode_t vp, struct nfsclclient *clp, u_int64_t off, */ static int nfscl_recalldeleg(struct nfsclclient *clp, struct nfsmount *nmp, - struct nfscldeleg *dp, vnode_t vp, struct ucred *cred, NFSPROC_T *p) + struct nfscldeleg *dp, vnode_t vp, struct ucred *cred, NFSPROC_T *p, + int called_from_renewthread) { struct nfsclowner *owp, *lowp, *nowp; struct nfsclopen *op, *lop; @@ -3306,6 +3344,7 @@ nfscl_recalldeleg(struct nfsclclient *clp, struct nfsmount *nmp, * Ok, if it's a write delegation, flush data to the server, so * that close/open consistency is retained. */ + ret = 0; NFSLOCKNODE(np); if ((dp->nfsdl_flags & NFSCLDL_WRITE) && (np->n_flag & NMODIFIED)) { #ifdef APPLE @@ -3314,7 +3353,8 @@ nfscl_recalldeleg(struct nfsclclient *clp, struct nfsmount *nmp, np->n_flag |= NDELEGRECALL; #endif NFSUNLOCKNODE(np); - (void) ncl_flush(vp, MNT_WAIT, cred, p, 1); + ret = ncl_flush(vp, MNT_WAIT, cred, p, 1, + called_from_renewthread); NFSLOCKNODE(np); #ifdef APPLE OSBitAndAtomic((int32_t)~(NMODIFIED | NDELEGRECALL), (UInt32 *)&np->n_flag); @@ -3323,6 +3363,16 @@ nfscl_recalldeleg(struct nfsclclient *clp, struct nfsmount *nmp, #endif } NFSUNLOCKNODE(np); + if (ret == EIO && called_from_renewthread != 0) { + /* + * If the flush failed with EIO for the renew thread, + * return now, so that the dirty buffer will be flushed + * later. + */ + if (gotvp != 0) + vrele(vp); + return (ret); + } /* * Now, for each openowner with opens issued locally, move them @@ -3569,7 +3619,7 @@ nfscl_tryopen(struct nfsmount *nmp, vnode_t vp, u_int8_t *fhp, int fhlen, mode, op, name, namelen, ndpp, reclaim, delegtype, cred, p, 0, 0); if (error == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfstryop"); + (void) nfs_catnap(PZERO, error, "nfstryop"); } while (error == NFSERR_DELAY); if (error == EAUTH || error == EACCES) { /* Try again using system credentials */ @@ -3579,7 +3629,7 @@ nfscl_tryopen(struct nfsmount *nmp, vnode_t vp, u_int8_t *fhp, int fhlen, newfhlen, mode, op, name, namelen, ndpp, reclaim, delegtype, cred, p, 1, 0); if (error == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfstryop"); + (void) nfs_catnap(PZERO, error, "nfstryop"); } while (error == NFSERR_DELAY); } return (error); @@ -3602,7 +3652,8 @@ nfscl_trylock(struct nfsmount *nmp, vnode_t vp, u_int8_t *fhp, error = nfsrpc_lock(nd, nmp, vp, fhp, fhlen, nlp, newone, reclaim, off, len, type, cred, p, 0); if (!error && nd->nd_repstat == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfstrylck"); + (void) nfs_catnap(PZERO, (int)nd->nd_repstat, + "nfstrylck"); } while (!error && nd->nd_repstat == NFSERR_DELAY); if (!error) error = nd->nd_repstat; @@ -3613,7 +3664,8 @@ nfscl_trylock(struct nfsmount *nmp, vnode_t vp, u_int8_t *fhp, error = nfsrpc_lock(nd, nmp, vp, fhp, fhlen, nlp, newone, reclaim, off, len, type, cred, p, 1); if (!error && nd->nd_repstat == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfstrylck"); + (void) nfs_catnap(PZERO, (int)nd->nd_repstat, + "nfstrylck"); } while (!error && nd->nd_repstat == NFSERR_DELAY); if (!error) error = nd->nd_repstat; @@ -3635,7 +3687,7 @@ nfscl_trydelegreturn(struct nfscldeleg *dp, struct ucred *cred, do { error = nfsrpc_delegreturn(dp, cred, nmp, p, 0); if (error == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfstrydp"); + (void) nfs_catnap(PZERO, error, "nfstrydp"); } while (error == NFSERR_DELAY); if (error == EAUTH || error == EACCES) { /* Try again using system credentials */ @@ -3643,7 +3695,7 @@ nfscl_trydelegreturn(struct nfscldeleg *dp, struct ucred *cred, do { error = nfsrpc_delegreturn(dp, cred, nmp, p, 1); if (error == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfstrydp"); + (void) nfs_catnap(PZERO, error, "nfstrydp"); } while (error == NFSERR_DELAY); } return (error); @@ -3664,7 +3716,7 @@ nfscl_tryclose(struct nfsclopen *op, struct ucred *cred, do { error = nfsrpc_closerpc(nd, nmp, op, cred, p, 0); if (error == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfstrycl"); + (void) nfs_catnap(PZERO, error, "nfstrycl"); } while (error == NFSERR_DELAY); if (error == EAUTH || error == EACCES) { /* Try again using system credentials */ @@ -3672,7 +3724,7 @@ nfscl_tryclose(struct nfsclopen *op, struct ucred *cred, do { error = nfsrpc_closerpc(nd, nmp, op, cred, p, 1); if (error == NFSERR_DELAY) - (void) nfs_catnap(PZERO, "nfstrycl"); + (void) nfs_catnap(PZERO, error, "nfstrycl"); } while (error == NFSERR_DELAY); } return (error); @@ -3820,7 +3872,7 @@ nfscl_removedeleg(vnode_t vp, NFSPROC_T *p, nfsv4stateid_t *stp) NFSUNLOCKCLSTATE(); cred = newnfs_getcred(); newnfs_copycred(&dp->nfsdl_cred, cred); - (void) nfscl_recalldeleg(clp, nmp, dp, vp, cred, p); + (void) nfscl_recalldeleg(clp, nmp, dp, vp, cred, p, 0); NFSFREECRED(cred); triedrecall = 1; NFSLOCKCLSTATE(); @@ -3918,7 +3970,7 @@ nfscl_renamedeleg(vnode_t fvp, nfsv4stateid_t *fstp, int *gotfdp, vnode_t tvp, NFSUNLOCKCLSTATE(); cred = newnfs_getcred(); newnfs_copycred(&dp->nfsdl_cred, cred); - (void) nfscl_recalldeleg(clp, nmp, dp, fvp, cred, p); + (void) nfscl_recalldeleg(clp, nmp, dp, fvp, cred, p, 0); NFSFREECRED(cred); triedrecall = 1; NFSLOCKCLSTATE(); diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c index 0bf2bf4..76154c3 100644 --- a/sys/fs/nfsclient/nfs_clvfsops.c +++ b/sys/fs/nfsclient/nfs_clvfsops.c @@ -652,7 +652,7 @@ nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp, while (newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)) { printf("newnfs_args: retrying connect\n"); - (void) nfs_catnap(PSOCK, "newnfscon"); + (void) nfs_catnap(PSOCK, 0, "newnfscon"); } } } else { @@ -1188,7 +1188,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp), cred, td); if (error) - (void) nfs_catnap(PZERO, "nfsgetdirp"); + (void) nfs_catnap(PZERO, error, "nfsgetdirp"); } while (error && --trycnt > 0); if (error) { error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); @@ -1284,7 +1284,7 @@ nfs_unmount(struct mount *mp, int mntflags) do { error = vflush(mp, 1, flags, td); if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30) - (void) nfs_catnap(PSOCK, "newndm"); + (void) nfs_catnap(PSOCK, error, "newndm"); } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30); if (error) goto out; diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 3be823f..d53c838 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -670,13 +670,13 @@ nfs_close(struct vop_close_args *ap) * traditional vnode locking implemented for Vnode Ops. */ int cm = newnfs_commit_on_close ? 1 : 0; - error = ncl_flush(vp, MNT_WAIT, cred, ap->a_td, cm); + error = ncl_flush(vp, MNT_WAIT, cred, ap->a_td, cm, 0); /* np->n_flag &= ~NMODIFIED; */ } else if (NFS_ISV4(vp)) { if (nfscl_mustflush(vp)) { int cm = newnfs_commit_on_close ? 1 : 0; error = ncl_flush(vp, MNT_WAIT, cred, ap->a_td, - cm); + cm, 0); /* * as above w.r.t races when clearing * NMODIFIED. @@ -1306,7 +1306,7 @@ ncl_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred) */ int ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, - int *iomode, int *must_commit) + int *iomode, int *must_commit, int called_from_strategy) { struct nfsvattr nfsva; int error = 0, attrflag, ret; @@ -1315,7 +1315,7 @@ ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, *must_commit = 0; error = nfsrpc_write(vp, uiop, iomode, verf, cred, - uiop->uio_td, &nfsva, &attrflag, NULL); + uiop->uio_td, &nfsva, &attrflag, NULL, called_from_strategy); NFSLOCKMNT(nmp); if (!error && NFSHASWRITEVERF(nmp) && NFSBCMP(verf, nmp->nm_verf, NFSX_VERF)) { @@ -2473,7 +2473,7 @@ nfs_strategy(struct vop_strategy_args *ap) */ if ((bp->b_flags & B_ASYNC) == 0 || ncl_asyncio(VFSTONFS(ap->a_vp->v_mount), bp, NOCRED, curthread)) - (void)ncl_doio(ap->a_vp, bp, cr, curthread); + (void) ncl_doio(ap->a_vp, bp, cr, curthread, 1); return (0); } @@ -2484,17 +2484,20 @@ nfs_strategy(struct vop_strategy_args *ap) static int nfs_fsync(struct vop_fsync_args *ap) { - return (ncl_flush(ap->a_vp, ap->a_waitfor, NULL, ap->a_td, 1)); + return (ncl_flush(ap->a_vp, ap->a_waitfor, NULL, ap->a_td, 1, 0)); } /* * Flush all the blocks associated with a vnode. * Walk through the buffer pool and push any dirty pages * associated with the vnode. + * If the called_from_renewthread argument is TRUE, it has been called + * from the NFSv4 renew thread and, as such, cannot block indefinitely + * waiting for a buffer write to complete. */ int ncl_flush(struct vnode *vp, int waitfor, struct ucred *cred, struct thread *td, - int commit) + int commit, int called_from_renewthread) { struct nfsnode *np = VTONFS(vp); struct buf *bp; @@ -2513,6 +2516,8 @@ ncl_flush(struct vnode *vp, int waitfor, struct ucred *cred, struct thread *td, struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; int bvecsize = 0, bveccount; + if (called_from_renewthread != 0) + slptimeo = hz; if (nmp->nm_flag & NFSMNT_INT) slpflag = NFS_PCATCH; if (!commit) @@ -2708,6 +2713,14 @@ loop: error = 0; goto loop; } + if (called_from_renewthread != 0) { + /* + * Return EIO so the flush will be retried + * later. + */ + error = EIO; + goto done; + } if (newnfs_sigintr(nmp, td)) { error = EINTR; goto done; @@ -2747,6 +2760,14 @@ loop: error = bufobj_wwait(bo, slpflag, slptimeo); if (error) { BO_UNLOCK(bo); + if (called_from_renewthread != 0) { + /* + * Return EIO so that the flush will be + * retried later. + */ + error = EIO; + goto done; + } error = newnfs_sigintr(nmp, td); if (error) goto done; @@ -2838,7 +2859,7 @@ nfs_advlock(struct vop_advlock_args *ap) */ if (ap->a_op == F_UNLCK && nfscl_checkwritelocked(vp, ap->a_fl, cred, td)) - (void) ncl_flush(vp, MNT_WAIT, cred, td, 1); + (void) ncl_flush(vp, MNT_WAIT, cred, td, 1, 0); /* * Loop around doing the lock op, while a blocking lock @@ -2850,7 +2871,8 @@ nfs_advlock(struct vop_advlock_args *ap) if (ret == NFSERR_DENIED && (ap->a_flags & F_WAIT) && ap->a_op == F_SETLK) { VOP_UNLOCK(vp, 0); - error = nfs_catnap(PZERO | PCATCH, "ncladvl"); + error = nfs_catnap(PZERO | PCATCH, ret, + "ncladvl"); if (error) return (EINTR); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 3b7f8d0..ba367e3 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -869,6 +869,7 @@ nfsvno_mkdir(struct nameidata *ndp, struct nfsvattr *nvap, uid_t saved_uid, else vput(ndp->ni_dvp); vrele(ndp->ni_vp); + nfsvno_relpathbuf(ndp); return (EEXIST); } error = VOP_MKDIR(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, @@ -1396,24 +1397,16 @@ nfsvno_fillattr(struct nfsrv_descript *nd, struct vnode *vp, * nfs readdir service * - mallocs what it thinks is enough to read * count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR - * - calls nfsvno_readdir() + * - calls VOP_READDIR() * - loops around building the reply * if the output generated exceeds count break out of loop * The NFSM_CLGET macro is used here so that the reply will be packed * tightly in mbuf clusters. - * - it only knows that it has encountered eof when the nfsvno_readdir() - * reads nothing - * - as such one readdir rpc will return eof false although you are there - * and then the next will return eof * - it trims out records with d_fileno == 0 * this doesn't matter for Unix clients, but they might confuse clients * for other os'. * - it trims out records with d_type == DT_WHT * these cannot be seen through NFS (unless we extend the protocol) - * NB: It is tempting to set eof to true if the nfsvno_readdir() reads less - * than requested, but this may not apply to all filesystems. For - * example, client NFS does not { although it is never remote mounted - * anyhow } * The alternate call nfsrvd_readdirplus() does lookups as well. * PS: The NFS protocol spec. does not clarify what the "count" byte * argument is a count of.. just name strings and file id's or the @@ -1455,7 +1448,7 @@ nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram, } toff = off; cnt = fxdr_unsigned(int, *tl); - if (cnt > NFS_SRVMAXDATA(nd)) + if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0) cnt = NFS_SRVMAXDATA(nd); siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); fullsiz = siz; @@ -1473,6 +1466,13 @@ nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram, nd->nd_repstat = NFSERR_BAD_COOKIE; #endif } + if (nd->nd_repstat == 0 && cnt == 0) { + if (nd->nd_flag & ND_NFSV2) + /* NFSv2 does not have NFSERR_TOOSMALL */ + nd->nd_repstat = EPERM; + else + nd->nd_repstat = NFSERR_TOOSMALL; + } if (!nd->nd_repstat) nd->nd_repstat = nfsvno_accchk(vp, VEXEC, nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, @@ -1695,7 +1695,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, * Use the server's maximum data transfer size as the upper bound * on reply datalen. */ - if (cnt > NFS_SRVMAXDATA(nd)) + if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0) cnt = NFS_SRVMAXDATA(nd); /* @@ -1704,7 +1704,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, * so I set it to cnt for that case. I also round it up to the * next multiple of DIRBLKSIZ. */ - if (siz == 0) + if (siz <= 0) siz = cnt; siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); @@ -2443,6 +2443,9 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam, *credp = NULL; exp->nes_numsecflavor = 0; error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); + if (error != 0) + /* Make sure the server replies ESTALE to the client. */ + error = ESTALE; if (nam && !error) { error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, &exp->nes_numsecflavor, &secflavors); @@ -2671,24 +2674,23 @@ nfsrv_getsocksndseq(struct socket *so, tcp_seq *maxp, tcp_seq *unap) { struct inpcb *inp; struct tcpcb *tp; - int error = EPIPE; - INP_INFO_RLOCK(&V_tcbinfo); inp = sotoinpcb(so); - if (inp == NULL) { - INP_INFO_RUNLOCK(&V_tcbinfo); - return (error); - } + KASSERT(inp != NULL, ("nfsrv_getsocksndseq: inp == NULL")); INP_RLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); + if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { + INP_RUNLOCK(inp); + return (EPIPE); + } tp = intotcpcb(inp); - if (tp != NULL && tp->t_state == TCPS_ESTABLISHED) { - *maxp = tp->snd_max; - *unap = tp->snd_una; - error = 0; + if (tp->t_state != TCPS_ESTABLISHED) { + INP_RUNLOCK(inp); + return (EPIPE); } + *maxp = tp->snd_max; + *unap = tp->snd_una; INP_RUNLOCK(inp); - return (error); + return (0); } /* diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index e56610b..50fa822 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -1086,7 +1086,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram, case NFFIFO: break; case NFDIR: - cnflags = LOCKPARENT; + cnflags = (LOCKPARENT | SAVENAME); break; default: nd->nd_repstat = NFSERR_BADTYPE; @@ -1549,7 +1549,8 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram, NFSVOPUNLOCK(dp, 0, p); } } - NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, LOCKPARENT); + NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, + LOCKPARENT | SAVENAME); if (!nd->nd_repstat) { nfsvno_setpathbuf(&named, &bufp, &hashp); error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); @@ -1743,7 +1744,8 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram, nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); return (0); } - NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, LOCKPARENT); + NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, + LOCKPARENT | SAVENAME); nfsvno_setpathbuf(&named, &bufp, &hashp); error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); if (error) { @@ -2084,6 +2086,10 @@ nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram, if (flags & NFSLCK_OPENTOLOCK) { NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID); i = fxdr_unsigned(int, *(tl+4+(NFSX_STATEID / NFSX_UNSIGNED))); + if (i <= 0 || i > NFSV4_OPAQUELIMIT) { + nd->nd_repstat = NFSERR_BADXDR; + goto nfsmout; + } MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i, M_NFSDSTATE, M_WAITOK); stp->ls_ownerlen = i; @@ -2227,6 +2233,10 @@ nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram, NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED); i = fxdr_unsigned(int, *(tl + 7)); + if (i <= 0 || i > NFSV4_OPAQUELIMIT) { + nd->nd_repstat = NFSERR_BADXDR; + goto nfsmout; + } MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i, M_NFSDSTATE, M_WAITOK); stp->ls_ownerlen = i; @@ -2348,6 +2358,8 @@ nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram, break; default: nd->nd_repstat = NFSERR_BADXDR; + free(stp, M_NFSDSTATE); + free(lop, M_NFSDLOCK); goto nfsmout; }; stp->ls_ownerlen = 0; @@ -2437,6 +2449,14 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, named.ni_cnd.cn_nameiop = 0; NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED); i = fxdr_unsigned(int, *(tl + 5)); + if (i <= 0 || i > NFSV4_OPAQUELIMIT) { + nd->nd_repstat = NFSERR_BADXDR; + vrele(dp); +#ifdef NFS4_ACL_EXTATTR_NAME + acl_free(aclp); +#endif + return (0); + } MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i, M_NFSDSTATE, M_WAITOK); stp->ls_ownerlen = i; @@ -3389,6 +3409,10 @@ nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram, } NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); len = fxdr_unsigned(int, *(tl + 2)); + if (len <= 0 || len > NFSV4_OPAQUELIMIT) { + nd->nd_repstat = NFSERR_BADXDR; + return (0); + } MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + len, M_NFSDSTATE, M_WAITOK); stp->ls_ownerlen = len; diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index 3e38cf4..e475cb7 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -65,11 +65,11 @@ static void nfsrv_dumpaclient(struct nfsclient *clp, struct nfsd_dumpclients *dumpp); static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p); -static int nfsrv_freeopen(struct nfsstate *stp, int *freedlockp, - int cansleep, NFSPROC_T *p); -static int nfsrv_freelockowner(struct nfsstate *stp, int *freedlockp, - int cansleep, NFSPROC_T *p); -static int nfsrv_freeallnfslocks(struct nfsstate *stp, int *freedlockp, +static int nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, + NFSPROC_T *p); +static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, + NFSPROC_T *p); +static void nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p); static void nfsrv_freenfslock(struct nfslock *lop); static void nfsrv_freenfslockfile(struct nfslockfile *lfp); @@ -80,8 +80,8 @@ static void nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, struct nfsstate **stpp); static int nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile **new_lfpp, fhandle_t *nfhp, NFSPROC_T *p); -static int nfsrv_getlockfile(u_short flags, - struct nfslockfile **new_lfpp, struct nfslockfile **lfpp, fhandle_t *nfhp); +static int nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, + struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit); static void nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop, struct nfsstate *stp, struct nfslockfile *lfp); static void nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, @@ -109,9 +109,20 @@ static time_t nfsrv_leaseexpiry(void); static void nfsrv_delaydelegtimeout(struct nfsstate *stp); static int nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, struct nfsstate *stp, struct nfsrvcache *op); -static void nfsrv_locallocks(vnode_t vp, struct nfslockfile *lfp, - NFSPROC_T *p); static int nfsrv_nootherstate(struct nfsstate *stp); +static int nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, + uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p); +static void nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, + uint64_t init_first, uint64_t init_end, NFSPROC_T *p); +static int nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, + int oldflags, uint64_t first, uint64_t end, struct nfslockconflict *cfp, + NFSPROC_T *p); +static void nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, + NFSPROC_T *p); +static void nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, + uint64_t first, uint64_t end); +static void nfsrv_locklf(struct nfslockfile *lfp); +static void nfsrv_unlocklf(struct nfslockfile *lfp); /* * Scan the client list for a match and either return the current one, @@ -683,7 +694,7 @@ nfsrv_dumplocks(vnode_t vp, struct nfsd_dumplocks *ldumpp, int maxcnt, ret = nfsrv_getlockfh(vp, 0, NULL, &nfh, p); NFSLOCKSTATE(); if (!ret) - ret = nfsrv_getlockfile(0, NULL, &lfp, &nfh); + ret = nfsrv_getlockfile(0, NULL, &lfp, &nfh, 0); if (ret) { ldumpp[0].ndlck_clid.nclid_idlen = 0; NFSUNLOCKSTATE(); @@ -927,9 +938,8 @@ nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p) { struct nfsstate *stp, *nstp; - LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { + LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) nfsrv_freeopenowner(stp, 1, p); - } } /* @@ -993,7 +1003,10 @@ nfsrv_freedeleg(struct nfsstate *stp) LIST_REMOVE(stp, ls_file); lfp = stp->ls_lfp; if (LIST_EMPTY(&lfp->lf_open) && - LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg)) + LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) && + LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && + lfp->lf_usecount == 0 && + nfsv4_testlock(&lfp->lf_locallock_lck) == 0) nfsrv_freenfslockfile(lfp); FREE((caddr_t)stp, M_NFSDSTATE); newnfsstats.srvdelegates--; @@ -1031,16 +1044,14 @@ nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p) * This function frees an open (nfsstate open structure) with all associated * lock_owners and locks. It also frees the nfslockfile structure iff there * are no other opens on the file. - * Must be called with soft clock interrupts disabled. * Returns 1 if it free'd the nfslockfile, 0 otherwise. */ static int -nfsrv_freeopen(struct nfsstate *stp, int *freedlockp, int cansleep, - NFSPROC_T *p) +nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p) { struct nfsstate *nstp, *tstp; struct nfslockfile *lfp; - int ret = 0, ret2; + int ret; LIST_REMOVE(stp, ls_hash); LIST_REMOVE(stp, ls_list); @@ -1048,28 +1059,27 @@ nfsrv_freeopen(struct nfsstate *stp, int *freedlockp, int cansleep, lfp = stp->ls_lfp; /* + * Now, free all lockowners associated with this open. + */ + LIST_FOREACH_SAFE(tstp, &stp->ls_open, ls_list, nstp) + nfsrv_freelockowner(tstp, vp, cansleep, p); + + /* * The nfslockfile is freed here if there are no locks * associated with the open. * If there are locks associated with the open, the * nfslockfile structure can be freed via nfsrv_freelockowner(). * (That is why the call must be here instead of after the loop.) */ - if (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) && - LIST_EMPTY(&lfp->lf_deleg)) { + if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) && + LIST_EMPTY(&lfp->lf_deleg) && LIST_EMPTY(&lfp->lf_lock) && + LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && + lfp->lf_usecount == 0 && + (cansleep != 0 || nfsv4_testlock(&lfp->lf_locallock_lck) == 0)) { nfsrv_freenfslockfile(lfp); ret = 1; - } - /* - * Now, free all lockowners associated with this open. - */ - nstp = LIST_FIRST(&stp->ls_open); - while (nstp != LIST_END(&stp->ls_open)) { - tstp = nstp; - nstp = LIST_NEXT(nstp, ls_list); - ret2 = nfsrv_freelockowner(tstp, freedlockp, cansleep, p); - if (ret == 0 && ret2 != 0) - ret = ret2; - } + } else + ret = 0; FREE((caddr_t)stp, M_NFSDSTATE); newnfsstats.srvopens--; nfsrv_openpluslock--; @@ -1078,79 +1088,76 @@ nfsrv_freeopen(struct nfsstate *stp, int *freedlockp, int cansleep, /* * Frees a lockowner and all associated locks. - * It also frees the nfslockfile structure, if there are no more - * references to it. - * Must be called with soft clock interrupts disabled. - * Returns 1 if it free'd the nfslockfile structure, 1 otherwise. */ -static int -nfsrv_freelockowner(struct nfsstate *stp, int *freedlockp, int cansleep, +static void +nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p) { - int ret; LIST_REMOVE(stp, ls_hash); LIST_REMOVE(stp, ls_list); - ret = nfsrv_freeallnfslocks(stp, freedlockp, cansleep, p); + nfsrv_freeallnfslocks(stp, vp, cansleep, p); if (stp->ls_op) nfsrvd_derefcache(stp->ls_op); FREE((caddr_t)stp, M_NFSDSTATE); newnfsstats.srvlockowners--; nfsrv_openpluslock--; - return (ret); } /* * Free all the nfs locks on a lockowner. - * Returns 1 if it free'd the nfslockfile structure, 0 otherwise. - * If any byte range lock is free'd, *freedlockp is set to 1. */ -static int -nfsrv_freeallnfslocks(struct nfsstate *stp, int *freedlockp, int cansleep, +static void +nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p) { struct nfslock *lop, *nlop; - struct nfslockfile *lfp = NULL, *olfp = NULL; - int ret = 0; + struct nfsrollback *rlp, *nrlp; + struct nfslockfile *lfp = NULL; + int gottvp = 0; + vnode_t tvp = NULL; lop = LIST_FIRST(&stp->ls_lock); while (lop != LIST_END(&stp->ls_lock)) { nlop = LIST_NEXT(lop, lo_lckowner); /* - * Since locks off a lockowner are ordered by - * file, you should update the local locks when - * you hit the next file OR the end of the lock - * list. If there are no locks for other owners, - * it must be done before the lockowner is discarded. - * (All this only applies if cansleep == 1.) + * Since all locks should be for the same file, lfp should + * not change. */ - olfp = lfp; - lfp = lop->lo_lfp; - nfsrv_freenfslock(lop); - if (freedlockp) - *freedlockp = 1; - if (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) && - LIST_EMPTY(&lfp->lf_deleg)) { - if (cansleep) - nfsrv_locallocks(NULL, lfp, p); - nfsrv_freenfslockfile(lfp); - /* - * Set the pointer(s) to this lockowner NULL, - * to indicate it has been free'd and local - * locks discarded already. - */ - if (olfp == lfp) - olfp = NULL; - lfp = NULL; - ret = 1; + if (lfp == NULL) + lfp = lop->lo_lfp; + else if (lfp != lop->lo_lfp) + panic("allnfslocks"); + /* + * If vp is NULL and cansleep != 0, a vnode must be acquired + * from the file handle. This only occurs when called from + * nfsrv_cleanclient(). + */ + if (gottvp == 0) { + if (nfsrv_dolocallocks == 0) + tvp = NULL; + else if (vp == NULL && cansleep != 0) + tvp = nfsvno_getvp(&lfp->lf_fh); + else + tvp = vp; + gottvp = 1; + } + + if (tvp != NULL) { + if (cansleep == 0) + panic("allnfs2"); + nfsrv_localunlock(tvp, lfp, lop->lo_first, + lop->lo_end, p); + LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, + nrlp) + free(rlp, M_NFSDROLLBACK); + LIST_INIT(&lfp->lf_rollback); } - if (cansleep && olfp != lfp && olfp != NULL) - nfsrv_locallocks(NULL, olfp, p); + nfsrv_freenfslock(lop); lop = nlop; } - if (cansleep && lfp != NULL) - nfsrv_locallocks(NULL, olfp, p); - return (ret); + if (vp == NULL && tvp != NULL) + vput(tvp); } /* @@ -1161,11 +1168,13 @@ static void nfsrv_freenfslock(struct nfslock *lop) { - LIST_REMOVE(lop, lo_lckfile); + if (lop->lo_lckfile.le_prev != NULL) { + LIST_REMOVE(lop, lo_lckfile); + newnfsstats.srvlocks--; + nfsrv_openpluslock--; + } LIST_REMOVE(lop, lo_lckowner); FREE((caddr_t)lop, M_NFSDLOCK); - newnfsstats.srvlocks--; - nfsrv_openpluslock--; } /* @@ -1240,7 +1249,8 @@ nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, APPLESTATIC int nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp, struct nfslock **new_lopp, struct nfslockconflict *cfp, - nfsquad_t clientid, nfsv4stateid_t *stateidp, __unused struct nfsexstuff *exp, + nfsquad_t clientid, nfsv4stateid_t *stateidp, + __unused struct nfsexstuff *exp, struct nfsrv_descript *nd, NFSPROC_T *p) { struct nfslock *lop; @@ -1253,9 +1263,11 @@ nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp, struct nfsstate *stp, *lckstp = NULL; struct nfsclient *clp = NULL; u_int32_t bits; - int error = 0, haslock = 0, ret; - int getlckret, delegation = 0; + int error = 0, haslock = 0, ret, reterr; + int getlckret, delegation = 0, filestruct_locked; fhandle_t nfh; + uint64_t first, end; + uint32_t lock_flags; if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_SETATTR)) { /* @@ -1290,23 +1302,6 @@ nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp, return (NFSERR_RESOURCE); /* - * For Lock, check for a conflict with a lock held by - * a process running locally on the server now, before - * monkeying with nfsd state. Since the vp is locked, any - * other local calls are blocked during this Op. - */ - if (new_stp->ls_flags & NFSLCK_LOCK) { - if (new_lop->lo_flags & NFSLCK_WRITE) - error = nfsvno_localconflict(vp, F_WRLCK, - new_lop->lo_first, new_lop->lo_end, cfp, p); - else - error = nfsvno_localconflict(vp, F_RDLCK, - new_lop->lo_first, new_lop->lo_end, cfp, p); - if (error) - return (error); - } - - /* * For the lock case, get another nfslock structure, * just in case we need it. * Malloc now, before we start sifting through the linked lists, @@ -1316,6 +1311,9 @@ tryagain: if (new_stp->ls_flags & NFSLCK_LOCK) MALLOC(other_lop, struct nfslock *, sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK); + filestruct_locked = 0; + reterr = 0; + lfp = NULL; /* * Get the lockfile structure for CFH now, so we can do a sanity @@ -1324,22 +1322,41 @@ tryagain: * shouldn't be incremented for this case. * If nfsrv_getlockfile() returns -1, it means "not found", which * will be handled later. + * If we are doing Lock/LockU and local locking is enabled, sleep + * lock the nfslockfile structure. */ getlckret = nfsrv_getlockfh(vp, new_stp->ls_flags, NULL, &nfh, p); NFSLOCKSTATE(); - if (!getlckret) - getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, - &lfp, &nfh); - if (getlckret != 0 && getlckret != -1) { - NFSUNLOCKSTATE(); - if (other_lop) - FREE((caddr_t)other_lop, M_NFSDLOCK); - if (haslock) { - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + if (getlckret == 0) { + if ((new_stp->ls_flags & (NFSLCK_LOCK | NFSLCK_UNLOCK)) != 0 && + nfsrv_dolocallocks != 0 && nd->nd_repstat == 0) { + getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, + &lfp, &nfh, 1); + if (getlckret == 0) + filestruct_locked = 1; + } else + getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, + &lfp, &nfh, 0); + } + if (getlckret != 0 && getlckret != -1) + reterr = getlckret; + + if (filestruct_locked != 0) { + LIST_INIT(&lfp->lf_rollback); + if ((new_stp->ls_flags & NFSLCK_LOCK)) { + /* + * For local locking, do the advisory locking now, so + * that any conflict can be detected. A failure later + * can be rolled back locally. If an error is returned, + * struct nfslockfile has been unlocked and any local + * locking rolled back. + */ + NFSUNLOCKSTATE(); + reterr = nfsrv_locallock(vp, lfp, + (new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)), + new_lop->lo_first, new_lop->lo_end, cfp, p); + NFSLOCKSTATE(); } - return (getlckret); } /* @@ -1381,11 +1398,11 @@ tryagain: */ if (error == 0 && (stp->ls_flags & NFSLCK_OPEN) && ((stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM) || - (getlckret != -1 && stp->ls_lfp != lfp))) + (getlckret == 0 && stp->ls_lfp != lfp))) error = NFSERR_BADSTATEID; if (error == 0 && (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) && - getlckret != -1 && stp->ls_lfp != lfp) + getlckret == 0 && stp->ls_lfp != lfp) error = NFSERR_BADSTATEID; /* @@ -1398,7 +1415,7 @@ tryagain: */ if (error == 0 && (stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 && - getlckret != -1 && stp->ls_lfp != lfp) { + getlckret == 0 && stp->ls_lfp != lfp) { #ifdef DIAGNOSTIC printf("Got a lock statid for different file open\n"); #endif @@ -1478,12 +1495,30 @@ tryagain: nfsrv_markstable(clp); /* - * If nd_repstat is set, we can return that now, since the - * seqid# has been incremented. + * At this point, either error == NFSERR_BADSTATEID or the + * seqid# has been updated, so we can return any error. + * If error == 0, there may be an error in: + * nd_repstat - Set by the calling function. + * reterr - Set above, if getting the nfslockfile structure + * or acquiring the local lock failed. + * (If both of these are set, nd_repstat should probably be + * returned, since that error was detected before this + * function call.) */ - if (nd->nd_repstat && !error) - error = nd->nd_repstat; - if (error) { + if (error != 0 || nd->nd_repstat != 0 || reterr != 0) { + if (error == 0) { + if (nd->nd_repstat != 0) + error = nd->nd_repstat; + else + error = reterr; + } + if (filestruct_locked != 0) { + /* Roll back local locks. */ + NFSUNLOCKSTATE(); + nfsrv_locallock_rollback(vp, lfp, p); + NFSLOCKSTATE(); + nfsrv_unlocklf(lfp); + } NFSUNLOCKSTATE(); if (other_lop) FREE((caddr_t)other_lop, M_NFSDLOCK); @@ -1569,6 +1604,13 @@ tryagain: ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) == (NFSLCK_CHECK | NFSLCK_WRITEACCESS) && !(mystp->ls_flags & NFSLCK_WRITEACCESS))) { + if (filestruct_locked != 0) { + /* Roll back local locks. */ + NFSUNLOCKSTATE(); + nfsrv_locallock_rollback(vp, lfp, p); + NFSLOCKSTATE(); + nfsrv_unlocklf(lfp); + } NFSUNLOCKSTATE(); if (other_lop) FREE((caddr_t)other_lop, M_NFSDLOCK); @@ -1680,11 +1722,18 @@ tryagain: (new_lop->lo_flags & NFSLCK_WRITE) && (clp != tstp->ls_clp || (tstp->ls_flags & NFSLCK_DELEGREAD)))) { + if (filestruct_locked != 0) { + /* Roll back local locks. */ + NFSUNLOCKSTATE(); + nfsrv_locallock_rollback(vp, lfp, p); + NFSLOCKSTATE(); + nfsrv_unlocklf(lfp); + } ret = nfsrv_delegconflict(tstp, &haslock, p, vp); if (ret) { /* * nfsrv_delegconflict unlocks state when it - * returns non-zero. + * returns non-zero, which it always does. */ if (other_lop) { FREE((caddr_t)other_lop, M_NFSDLOCK); @@ -1696,6 +1745,7 @@ tryagain: } return (ret); } + /* Never gets here. */ } tstp = nstp; } @@ -1706,32 +1756,21 @@ tryagain: * just let it happen.) */ if (new_stp->ls_flags & NFSLCK_UNLOCK) { + first = new_lop->lo_first; + end = new_lop->lo_end; nfsrv_updatelock(stp, new_lopp, &other_lop, lfp); stateidp->seqid = ++(stp->ls_stateid.seqid); stateidp->other[0] = stp->ls_stateid.other[0]; stateidp->other[1] = stp->ls_stateid.other[1]; stateidp->other[2] = stp->ls_stateid.other[2]; - /* - * For a non-empty flp->lf_lock list, I believe - * nfsrv_locallocks() can safely traverse the list, including - * sleeping, for two reasons: - * 1 - The Lock/LockU/Close Ops all require a locked - * vnode for the file and we currently have that. - * 2 - The only other thing that modifies a non-empty - * list is nfsrv_cleanclient() and it is always - * done with the exclusive nfsv4rootfs_lock held. - * Since this Op in progress holds either a shared or - * exclusive lock on nfsv4rootfs_lock, that can't - * happen now. - * However, the structure pointed to by lfp can go - * in many places for an empty list, so that is handled - * by passing a NULL pointer to nfsrv_locallocks(). - * Do that check now, while we are still SMP safe. - */ - if (LIST_EMPTY(&lfp->lf_lock)) - lfp = NULL; + if (filestruct_locked != 0) { + NFSUNLOCKSTATE(); + /* Update the local locks. */ + nfsrv_localunlock(vp, lfp, first, end, p); + NFSLOCKSTATE(); + nfsrv_unlocklf(lfp); + } NFSUNLOCKSTATE(); - nfsrv_locallocks(vp, lfp, p); if (haslock) { NFSLOCKV4ROOTMUTEX(); nfsv4_unlock(&nfsv4rootfs_lock, 1); @@ -1763,6 +1802,13 @@ tryagain: } ret = nfsrv_clientconflict(lop->lo_stp->ls_clp,&haslock,vp,p); if (ret) { + if (filestruct_locked != 0) { + /* Roll back local locks. */ + nfsrv_locallock_rollback(vp, lfp, p); + NFSLOCKSTATE(); + nfsrv_unlocklf(lfp); + NFSUNLOCKSTATE(); + } /* * nfsrv_clientconflict() unlocks state when it * returns non-zero. @@ -1790,6 +1836,13 @@ tryagain: error = NFSERR_LOCKED; else error = NFSERR_DENIED; + if (filestruct_locked != 0) { + /* Roll back local locks. */ + NFSUNLOCKSTATE(); + nfsrv_locallock_rollback(vp, lfp, p); + NFSLOCKSTATE(); + nfsrv_unlocklf(lfp); + } NFSUNLOCKSTATE(); if (haslock) { NFSLOCKV4ROOTMUTEX(); @@ -1820,6 +1873,9 @@ tryagain: * - exist_lock_owner where lock_owner exists * - open_to_lock_owner with new lock_owner */ + first = new_lop->lo_first; + end = new_lop->lo_end; + lock_flags = new_lop->lo_flags; if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) { nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp); stateidp->seqid = ++(lckstp->ls_stateid.seqid); @@ -1854,11 +1910,13 @@ tryagain: newnfsstats.srvlockowners++; nfsrv_openpluslock++; } - /* See comment above, w.r.t. nfsrv_locallocks(). */ - if (LIST_EMPTY(&lfp->lf_lock)) - lfp = NULL; + if (filestruct_locked != 0) { + NFSUNLOCKSTATE(); + nfsrv_locallock_commit(lfp, lock_flags, first, end); + NFSLOCKSTATE(); + nfsrv_unlocklf(lfp); + } NFSUNLOCKSTATE(); - nfsrv_locallocks(vp, lfp, p); if (haslock) { NFSLOCKV4ROOTMUTEX(); nfsv4_unlock(&nfsv4rootfs_lock, 1); @@ -1984,7 +2042,7 @@ tryagain: error = getfhret; else error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, - NULL); + NULL, 0); if (new_lfp) FREE((caddr_t)new_lfp, M_NFSDLOCKFILE); if (error) { @@ -2227,7 +2285,7 @@ tryagain: error = getfhret; else error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, - NULL); + NULL, 0); if (new_lfp) FREE((caddr_t)new_lfp, M_NFSDLOCKFILE); if (error) { @@ -2775,7 +2833,7 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid, struct nfsclient *clp; struct nfslockfile *lfp; u_int32_t bits; - int error, gotstate = 0, len = 0, ret, freedlock; + int error, gotstate = 0, len = 0; u_char client[NFSV4_OPAQUELIMIT]; /* @@ -2863,26 +2921,19 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid, } else if (new_stp->ls_flags & NFSLCK_CLOSE) { ownerstp = stp->ls_openowner; lfp = stp->ls_lfp; - freedlock = 0; - ret = nfsrv_freeopen(stp, &freedlock, 0, p); - /* See comment on nfsrv_lockctrl() w.r.t. locallocks. */ - if (ret) { - lfp = NULL; + if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) { + /* Get the lf lock */ + nfsrv_locklf(lfp); + NFSUNLOCKSTATE(); + if (nfsrv_freeopen(stp, vp, 1, p) == 0) { + NFSLOCKSTATE(); + nfsrv_unlocklf(lfp); + NFSUNLOCKSTATE(); + } } else { - if (LIST_EMPTY(&lfp->lf_lock)) - lfp = NULL; - } - /* - * For now, I won't do this. The openowner should be - * free'd in NFSNOOPEN seconds and it will be deref'd then. - if (LIST_EMPTY(&ownerstp->ls_open) && ownerstp->ls_op) { - nfsrvd_derefcache(ownerstp->ls_op); - ownerstp->ls_op = NULL; + (void) nfsrv_freeopen(stp, NULL, 0, p); + NFSUNLOCKSTATE(); } - */ - NFSUNLOCKSTATE(); - if (freedlock && lfp != NULL) - nfsrv_locallocks(vp, lfp, p); } else { /* * Update the share bits, making sure that the new set are a @@ -3024,7 +3075,7 @@ nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid, !NFSBCMP(stp->ls_owner, new_stp->ls_owner, stp->ls_ownerlen)){ if (LIST_EMPTY(&stp->ls_lock)) { - (void) nfsrv_freelockowner(stp, NULL, 0, p); + nfsrv_freelockowner(stp, NULL, 0, p); } else { NFSUNLOCKSTATE(); return (NFSERR_LOCKSHELD); @@ -3072,7 +3123,7 @@ nfsrv_getlockfh(vnode_t vp, u_short flags, */ static int nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, - struct nfslockfile **lfpp, fhandle_t *nfhp) + struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit) { struct nfslockfile *lfp; fhandle_t *fhp = NULL, *tfhp; @@ -3096,6 +3147,8 @@ nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, LIST_FOREACH(lfp, hp, lf_hash) { tfhp = &lfp->lf_fh; if (NFSVNO_CMPFH(fhp, tfhp)) { + if (lockit) + nfsrv_locklf(lfp); *lfpp = lfp; return (0); } @@ -3109,6 +3162,11 @@ nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, LIST_INIT(&new_lfp->lf_open); LIST_INIT(&new_lfp->lf_lock); LIST_INIT(&new_lfp->lf_deleg); + LIST_INIT(&new_lfp->lf_locallock); + LIST_INIT(&new_lfp->lf_rollback); + new_lfp->lf_locallock_lck.nfslock_usecnt = 0; + new_lfp->lf_locallock_lck.nfslock_lock = 0; + new_lfp->lf_usecount = 0; LIST_INSERT_HEAD(hp, new_lfp, lf_hash); *lfpp = new_lfp; *new_lfpp = NULL; @@ -3130,31 +3188,39 @@ nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop, new_lop->lo_stp = stp; new_lop->lo_lfp = lfp; - /* Insert in increasing lo_first order */ - lop = LIST_FIRST(&lfp->lf_lock); - if (lop == LIST_END(&lfp->lf_lock) || - new_lop->lo_first <= lop->lo_first) { - LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile); - } else { - nlop = LIST_NEXT(lop, lo_lckfile); - while (nlop != LIST_END(&lfp->lf_lock) && - nlop->lo_first < new_lop->lo_first) { - lop = nlop; + if (stp != NULL) { + /* Insert in increasing lo_first order */ + lop = LIST_FIRST(&lfp->lf_lock); + if (lop == LIST_END(&lfp->lf_lock) || + new_lop->lo_first <= lop->lo_first) { + LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile); + } else { nlop = LIST_NEXT(lop, lo_lckfile); + while (nlop != LIST_END(&lfp->lf_lock) && + nlop->lo_first < new_lop->lo_first) { + lop = nlop; + nlop = LIST_NEXT(lop, lo_lckfile); + } + LIST_INSERT_AFTER(lop, new_lop, lo_lckfile); } - LIST_INSERT_AFTER(lop, new_lop, lo_lckfile); + } else { + new_lop->lo_lckfile.le_prev = NULL; /* list not used */ } /* - * Insert after insert_lop, which is overloaded as stp for + * Insert after insert_lop, which is overloaded as stp or lfp for * an empty list. */ - if ((struct nfsstate *)insert_lop == stp) + if (stp == NULL && (struct nfslockfile *)insert_lop == lfp) + LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner); + else if ((struct nfsstate *)insert_lop == stp) LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner); else LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner); - newnfsstats.srvlocks++; - nfsrv_openpluslock++; + if (stp != NULL) { + newnfsstats.srvlocks++; + nfsrv_openpluslock++; + } } /* @@ -3180,9 +3246,14 @@ nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, */ if (new_lop->lo_flags & NFSLCK_UNLOCK) unlock = 1; - ilop = (struct nfslock *)stp; - lop = LIST_FIRST(&stp->ls_lock); - while (lop != LIST_END(&stp->ls_lock)) { + if (stp != NULL) { + ilop = (struct nfslock *)stp; + lop = LIST_FIRST(&stp->ls_lock); + } else { + ilop = (struct nfslock *)lfp; + lop = LIST_FIRST(&lfp->lf_locallock); + } + while (lop != NULL) { /* * Only check locks for this file that aren't before the start of * new lock's range. @@ -3278,8 +3349,7 @@ nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, } ilop = lop; lop = LIST_NEXT(lop, lo_lckowner); - if (myfile && (lop == LIST_END(&stp->ls_lock) || - lop->lo_lfp != lfp)) + if (myfile && (lop == NULL || lop->lo_lfp != lfp)) break; } @@ -4362,7 +4432,7 @@ nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p) tryagain: NFSLOCKSTATE(); if (!error) - error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh); + error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); if (error) { NFSUNLOCKSTATE(); if (haslock) { @@ -4508,7 +4578,7 @@ nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p) 100000) return; /* Sleep for a short period of time */ - (void) nfs_catnap(PZERO, "nfsremove"); + (void) nfs_catnap(PZERO, 0, "nfsremove"); } } while (error == NFSERR_DELAY); } @@ -4612,7 +4682,7 @@ nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp, error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); NFSLOCKSTATE(); if (!error) - error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh); + error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); if (error) { NFSUNLOCKSTATE(); if (error == -1) @@ -4783,112 +4853,252 @@ nfsrv_delaydelegtimeout(struct nfsstate *stp) } /* - * Go through a lock list and set local locks for all ranges. - * This assumes that the lock list is sorted on increasing - * lo_first and that the list won't change, despite the possibility - * of sleeps. + * This function checks to see if there is any other state associated + * with the openowner for this Open. + * It returns 1 if there is no other state, 0 otherwise. */ -static void -nfsrv_locallocks(vnode_t vp, struct nfslockfile *lfp, - NFSPROC_T *p) +static int +nfsrv_nootherstate(struct nfsstate *stp) { - struct nfslock *lop, *nlop; - vnode_t tvp; - int newcollate, flags = 0; - u_int64_t first = 0x0ull, end = 0x0ull; + struct nfsstate *tstp; - if (!nfsrv_dolocallocks) - return; - /* - * If vp is NULL, a vnode must be aquired from the file - * handle. - */ - if (vp == NULL) { - if (lfp == NULL) - panic("nfsrv_locallocks"); - tvp = nfsvno_getvp(&lfp->lf_fh); - if (tvp == NULL) - return; - } else { - tvp = vp; + LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) { + if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock)) + return (0); } + return (1); +} - /* - * If lfp == NULL, the lock list is empty, so just unlock - * everything. - */ - if (lfp == NULL) { - (void) nfsvno_advlock(tvp, F_UNLCK, (u_int64_t)0, - NFS64BITSSET, p); - /* vp can't be NULL */ - return; - } +/* + * Create a list of lock deltas (changes to local byte range locking + * that can be rolled back using the list) and apply the changes via + * nfsvno_advlock(). Optionally, lock the list. It is expected that either + * the rollback or update function will be called after this. + * It returns an error (and rolls back, as required), if any nfsvno_advlock() + * call fails. If it returns an error, it will unlock the list. + */ +static int +nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, + uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) +{ + struct nfslock *lop, *nlop; + int error = 0; - /* handle whole file case first */ - lop = LIST_FIRST(&lfp->lf_lock); - if (lop != LIST_END(&lfp->lf_lock) && - lop->lo_first == (u_int64_t)0 && - lop->lo_end == NFS64BITSSET) { - if (lop->lo_flags & NFSLCK_WRITE) - (void) nfsvno_advlock(tvp, F_WRLCK, lop->lo_first, - lop->lo_end, p); - else - (void) nfsvno_advlock(tvp, F_RDLCK, lop->lo_first, - lop->lo_end, p); - if (vp == NULL) - vput(tvp); - return; + /* Loop through the list of locks. */ + lop = LIST_FIRST(&lfp->lf_locallock); + while (first < end && lop != NULL) { + nlop = LIST_NEXT(lop, lo_lckowner); + if (first >= lop->lo_end) { + /* not there yet */ + lop = nlop; + } else if (first < lop->lo_first) { + /* new one starts before entry in list */ + if (end <= lop->lo_first) { + /* no overlap between old and new */ + error = nfsrv_dolocal(vp, lfp, flags, + NFSLCK_UNLOCK, first, end, cfp, p); + if (error != 0) + break; + first = end; + } else { + /* handle fragment overlapped with new one */ + error = nfsrv_dolocal(vp, lfp, flags, + NFSLCK_UNLOCK, first, lop->lo_first, cfp, + p); + if (error != 0) + break; + first = lop->lo_first; + } + } else { + /* new one overlaps this entry in list */ + if (end <= lop->lo_end) { + /* overlaps all of new one */ + error = nfsrv_dolocal(vp, lfp, flags, + lop->lo_flags, first, end, cfp, p); + if (error != 0) + break; + first = end; + } else { + /* handle fragment overlapped with new one */ + error = nfsrv_dolocal(vp, lfp, flags, + lop->lo_flags, first, lop->lo_end, cfp, p); + if (error != 0) + break; + first = lop->lo_end; + lop = nlop; + } + } } + if (first < end && error == 0) + /* handle fragment past end of list */ + error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first, + end, cfp, p); + return (error); +} - /* - * Now, handle the separate byte ranges cases. - */ - (void) nfsvno_advlock(tvp, F_UNLCK, (u_int64_t)0, - NFS64BITSSET, p); - newcollate = 1; - while (lop != LIST_END(&lfp->lf_lock)) { - nlop = LIST_NEXT(lop, lo_lckfile); - if (newcollate) { - first = lop->lo_first; - end = lop->lo_end; - flags = lop->lo_flags; - newcollate = 0; +/* + * Local lock unlock. Unlock all byte ranges that are no longer locked + * by NFSv4. + */ +static void +nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first, + uint64_t init_end, NFSPROC_T *p) +{ + struct nfslock *lop; + + uint64_t first, end; + + first = init_first; + end = init_end; + while (first < init_end) { + /* Loop through all nfs locks, adjusting first and end */ + LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { + if (first >= lop->lo_first && + first < lop->lo_end) + /* Overlaps initial part */ + first = lop->lo_end; + else if (end > lop->lo_first && + lop->lo_first >= first) + /* Begins before end and past first */ + end = lop->lo_first; + if (first >= end) + /* shrunk to 0 so this iteration is done */ + break; } - if (nlop != LIST_END(&lfp->lf_lock) && - flags == nlop->lo_flags && - end >= nlop->lo_first) { - /* can collate this one */ - end = nlop->lo_end; - } else { - /* do the local lock and start again */ - if (flags & NFSLCK_WRITE) - (void) nfsvno_advlock(tvp, F_WRLCK, first, - end, p); - else - (void) nfsvno_advlock(tvp, F_RDLCK, first, - end, p); - newcollate = 1; + if (first < end) { + /* Unlock this segment */ + (void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK, + NFSLCK_READ, first, end, NULL, p); + nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK, + first, end); } - lop = nlop; + /* and move on to the rest of the range */ + first = end; + end = init_end; } - if (vp == NULL) - vput(tvp); } /* - * This function checks to see if there is any other state associated - * with the openowner for this Open. - * It returns 1 if there is no other state, 0 otherwise. + * Do the local lock operation and update the rollback list, as required. + * Perform the rollback and return the error if nfsvno_advlock() fails. */ static int -nfsrv_nootherstate(struct nfsstate *stp) +nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags, + uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) { - struct nfsstate *tstp; + struct nfsrollback *rlp; + int error, ltype, oldltype; - LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) { - if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock)) - return (0); + if (flags & NFSLCK_WRITE) + ltype = F_WRLCK; + else if (flags & NFSLCK_READ) + ltype = F_RDLCK; + else + ltype = F_UNLCK; + if (oldflags & NFSLCK_WRITE) + oldltype = F_WRLCK; + else if (oldflags & NFSLCK_READ) + oldltype = F_RDLCK; + else + oldltype = F_UNLCK; + if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK)) + /* nothing to do */ + return (0); + error = nfsvno_advlock(vp, ltype, first, end, p); + if (error != 0) { + if (cfp != NULL) { + cfp->cl_clientid.lval[0] = 0; + cfp->cl_clientid.lval[1] = 0; + cfp->cl_first = 0; + cfp->cl_end = NFS64BITSSET; + cfp->cl_flags = NFSLCK_WRITE; + cfp->cl_ownerlen = 5; + NFSBCOPY("LOCAL", cfp->cl_owner, 5); + } + nfsrv_locallock_rollback(vp, lfp, p); + } else if (ltype != F_UNLCK) { + rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK, + M_WAITOK); + rlp->rlck_first = first; + rlp->rlck_end = end; + rlp->rlck_type = oldltype; + LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list); } - return (1); + return (error); +} + +/* + * Roll back local lock changes and free up the rollback list. + */ +static void +nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p) +{ + struct nfsrollback *rlp, *nrlp; + + LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) { + (void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first, + rlp->rlck_end, p); + free(rlp, M_NFSDROLLBACK); + } + LIST_INIT(&lfp->lf_rollback); +} + +/* + * Update local lock list and delete rollback list (ie now committed to the + * local locks). Most of the work is done by the internal function. + */ +static void +nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first, + uint64_t end) +{ + struct nfsrollback *rlp, *nrlp; + struct nfslock *new_lop, *other_lop; + + new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK); + if (flags & (NFSLCK_READ | NFSLCK_WRITE)) + other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, + M_WAITOK); + else + other_lop = NULL; + new_lop->lo_flags = flags; + new_lop->lo_first = first; + new_lop->lo_end = end; + nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp); + if (new_lop != NULL) + free(new_lop, M_NFSDLOCK); + if (other_lop != NULL) + free(other_lop, M_NFSDLOCK); + + /* and get rid of the rollback list */ + LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) + free(rlp, M_NFSDROLLBACK); + LIST_INIT(&lfp->lf_rollback); +} + +/* + * Lock the struct nfslockfile for local lock updating. + */ +static void +nfsrv_locklf(struct nfslockfile *lfp) +{ + int gotlock; + + /* lf_usecount ensures *lfp won't be free'd */ + lfp->lf_usecount++; + do { + gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL, + NFSSTATEMUTEXPTR); + } while (gotlock == 0); + lfp->lf_usecount--; +} + +/* + * Unlock the struct nfslockfile after local lock updating. + */ +static void +nfsrv_unlocklf(struct nfslockfile *lfp) +{ + + nfsv4_unlock(&lfp->lf_locallock_lck, 0); } diff --git a/sys/fs/nwfs/nwfs.h b/sys/fs/nwfs/nwfs.h index d7b2f62..af71724 100644 --- a/sys/fs/nwfs/nwfs.h +++ b/sys/fs/nwfs/nwfs.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999, Boris Popov + * Copyright (c) 1999 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_io.c b/sys/fs/nwfs/nwfs_io.c index 2f9ac01..75b1c18 100644 --- a/sys/fs/nwfs/nwfs_io.c +++ b/sys/fs/nwfs/nwfs_io.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999, Boris Popov + * Copyright (c) 1999 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_ioctl.c b/sys/fs/nwfs/nwfs_ioctl.c index 0fd5531..35fe93e 100644 --- a/sys/fs/nwfs/nwfs_ioctl.c +++ b/sys/fs/nwfs/nwfs_ioctl.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999, Boris Popov + * Copyright (c) 1999 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_mount.h b/sys/fs/nwfs/nwfs_mount.h index a6f9568..a1670942 100644 --- a/sys/fs/nwfs/nwfs_mount.h +++ b/sys/fs/nwfs/nwfs_mount.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999, Boris Popov + * Copyright (c) 1999 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_node.c b/sys/fs/nwfs/nwfs_node.c index 1e044c66..fc9b41b 100644 --- a/sys/fs/nwfs/nwfs_node.c +++ b/sys/fs/nwfs/nwfs_node.c @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_node.h b/sys/fs/nwfs/nwfs_node.h index f2e0ada..89545eb 100644 --- a/sys/fs/nwfs/nwfs_node.h +++ b/sys/fs/nwfs/nwfs_node.h @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_subr.c b/sys/fs/nwfs/nwfs_subr.c index 732651f..cb85450 100644 --- a/sys/fs/nwfs/nwfs_subr.c +++ b/sys/fs/nwfs/nwfs_subr.c @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_subr.h b/sys/fs/nwfs/nwfs_subr.h index 683a943..e571349 100644 --- a/sys/fs/nwfs/nwfs_subr.h +++ b/sys/fs/nwfs/nwfs_subr.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999, Boris Popov + * Copyright (c) 1999 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_vfsops.c b/sys/fs/nwfs/nwfs_vfsops.c index eed51c6..497414e 100644 --- a/sys/fs/nwfs/nwfs_vfsops.c +++ b/sys/fs/nwfs/nwfs_vfsops.c @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/nwfs/nwfs_vnops.c b/sys/fs/nwfs/nwfs_vnops.c index e63df80..e4f42b1 100644 --- a/sys/fs/nwfs/nwfs_vnops.c +++ b/sys/fs/nwfs/nwfs_vnops.c @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/procfs/procfs_dbregs.c b/sys/fs/procfs/procfs_dbregs.c index efa4e14..68945ef 100644 --- a/sys/fs/procfs/procfs_dbregs.c +++ b/sys/fs/procfs/procfs_dbregs.c @@ -59,10 +59,9 @@ #include <fs/pseudofs/pseudofs.h> #include <fs/procfs/procfs.h> -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 #include <sys/procfs.h> #include <machine/fpu.h> -#include <compat/ia32/ia32_reg.h> /* * PROC(write, dbregs, td2, &r) becomes @@ -90,7 +89,7 @@ procfs_doprocdbregs(PFS_FILL_ARGS) int error; struct dbreg r; struct thread *td2; -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 struct dbreg32 r32; int wrap32 = 0; #endif @@ -106,7 +105,7 @@ procfs_doprocdbregs(PFS_FILL_ARGS) } td2 = FIRST_THREAD_IN_PROC(p); -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 if (SV_CURPROC_FLAG(SV_ILP32)) { if ((td2->td_proc->p_sysent->sv_flags & SV_ILP32) == 0) { PROC_UNLOCK(p); diff --git a/sys/fs/procfs/procfs_fpregs.c b/sys/fs/procfs/procfs_fpregs.c index 43af53e..c35b066 100644 --- a/sys/fs/procfs/procfs_fpregs.c +++ b/sys/fs/procfs/procfs_fpregs.c @@ -53,10 +53,9 @@ #include <fs/pseudofs/pseudofs.h> #include <fs/procfs/procfs.h> -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 #include <sys/procfs.h> #include <machine/fpu.h> -#include <compat/ia32/ia32_reg.h> /* * PROC(write, fpregs, td2, &r) becomes @@ -84,7 +83,7 @@ procfs_doprocfpregs(PFS_FILL_ARGS) int error; struct fpreg r; struct thread *td2; -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 struct fpreg32 r32; int wrap32 = 0; #endif @@ -101,7 +100,7 @@ procfs_doprocfpregs(PFS_FILL_ARGS) /* XXXKSE: */ td2 = FIRST_THREAD_IN_PROC(p); -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 if (SV_CURPROC_FLAG(SV_ILP32)) { if ((td2->td_proc->p_sysent->sv_flags & SV_ILP32) == 0) { PROC_UNLOCK(p); diff --git a/sys/fs/procfs/procfs_ioctl.c b/sys/fs/procfs/procfs_ioctl.c index ccff555..4b45af6 100644 --- a/sys/fs/procfs/procfs_ioctl.c +++ b/sys/fs/procfs/procfs_ioctl.c @@ -42,7 +42,7 @@ #include <fs/pseudofs/pseudofs.h> #include <fs/procfs/procfs.h> -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 struct procfs_status32 { int state; /* Running, stopped, something else? */ int flags; /* Any flags */ @@ -62,7 +62,7 @@ int procfs_ioctl(PFS_IOCTL_ARGS) { struct procfs_status *ps; -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 struct procfs_status32 *ps32; #endif int error, flags, sig; @@ -142,7 +142,7 @@ procfs_ioctl(PFS_IOCTL_ARGS) ps->why = p->p_step ? p->p_stype : 0; ps->val = p->p_step ? p->p_xstat : 0; break; -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 case PIOCWAIT32: while (p->p_step == 0 && (p->p_flag & P_WEXIT) == 0) { /* sleep until p stops */ diff --git a/sys/fs/procfs/procfs_map.c b/sys/fs/procfs/procfs_map.c index 878e2d5..2622d1e 100644 --- a/sys/fs/procfs/procfs_map.c +++ b/sys/fs/procfs/procfs_map.c @@ -47,7 +47,7 @@ #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/sbuf.h> -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 #include <sys/sysent.h> #endif #include <sys/uio.h> @@ -86,7 +86,7 @@ procfs_doprocmap(PFS_FILL_ARGS) struct uidinfo *uip; int error, vfslocked; unsigned int last_timestamp; -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 int wrap32 = 0; #endif @@ -99,7 +99,7 @@ procfs_doprocmap(PFS_FILL_ARGS) if (uio->uio_rw != UIO_READ) return (EOPNOTSUPP); -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 if (curproc->p_sysent->sv_flags & SV_ILP32) { if (!(p->p_sysent->sv_flags & SV_ILP32)) return (EOPNOTSUPP); @@ -209,7 +209,7 @@ procfs_doprocmap(PFS_FILL_ARGS) "0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s %s %s %d\n", (u_long)e_start, (u_long)e_end, resident, privateresident, -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 wrap32 ? NULL : obj, /* Hide 64 bit value */ #else obj, diff --git a/sys/fs/procfs/procfs_regs.c b/sys/fs/procfs/procfs_regs.c index 82922fb..5bf1c0a 100644 --- a/sys/fs/procfs/procfs_regs.c +++ b/sys/fs/procfs/procfs_regs.c @@ -53,10 +53,9 @@ #include <fs/pseudofs/pseudofs.h> #include <fs/procfs/procfs.h> -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 #include <sys/procfs.h> #include <machine/fpu.h> -#include <compat/ia32/ia32_reg.h> /* * PROC(write, regs, td2, &r) becomes @@ -84,7 +83,7 @@ procfs_doprocregs(PFS_FILL_ARGS) int error; struct reg r; struct thread *td2; -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 struct reg32 r32; int wrap32 = 0; #endif @@ -101,7 +100,7 @@ procfs_doprocregs(PFS_FILL_ARGS) /* XXXKSE: */ td2 = FIRST_THREAD_IN_PROC(p); -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 if (SV_CURPROC_FLAG(SV_ILP32)) { if ((td2->td_proc->p_sysent->sv_flags & SV_ILP32) == 0) { PROC_UNLOCK(p); diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c index 5854378..f8343a9 100644 --- a/sys/fs/pseudofs/pseudofs_vnops.c +++ b/sys/fs/pseudofs/pseudofs_vnops.c @@ -542,7 +542,7 @@ pfs_lookup(struct vop_cachedlookup_args *va) if (cnp->cn_flags & ISDOTDOT) vn_lock(vn, LK_EXCLUSIVE|LK_RETRY); - if (cnp->cn_flags & MAKEENTRY) + if (cnp->cn_flags & MAKEENTRY && !(vn->v_iflag & VI_DOOMED)) cache_enter(vn, *vpp, cnp); PFS_RETURN (0); failed: diff --git a/sys/fs/smbfs/smbfs.h b/sys/fs/smbfs/smbfs.h index bdecd99..4be0a55 100644 --- a/sys/fs/smbfs/smbfs.h +++ b/sys/fs/smbfs/smbfs.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2001, Boris Popov + * Copyright (c) 2000-2001 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c index 8ff8266..df779a6 100644 --- a/sys/fs/smbfs/smbfs_io.c +++ b/sys/fs/smbfs/smbfs_io.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2001, Boris Popov + * Copyright (c) 2000-2001 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/smbfs/smbfs_node.c b/sys/fs/smbfs/smbfs_node.c index 38464cd..a0543e2 100644 --- a/sys/fs/smbfs/smbfs_node.c +++ b/sys/fs/smbfs/smbfs_node.c @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/smbfs/smbfs_node.h b/sys/fs/smbfs/smbfs_node.h index f9c08cf..ed1c17d 100644 --- a/sys/fs/smbfs/smbfs_node.h +++ b/sys/fs/smbfs/smbfs_node.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2001, Boris Popov + * Copyright (c) 2000-2001 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/smbfs/smbfs_smb.c b/sys/fs/smbfs/smbfs_smb.c index 3a89a9c..f58f7de 100644 --- a/sys/fs/smbfs/smbfs_smb.c +++ b/sys/fs/smbfs/smbfs_smb.c @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/smbfs/smbfs_subr.c b/sys/fs/smbfs/smbfs_subr.c index 68ed0b1..b775dff 100644 --- a/sys/fs/smbfs/smbfs_subr.c +++ b/sys/fs/smbfs/smbfs_subr.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2001, Boris Popov + * Copyright (c) 2000-2001 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/smbfs/smbfs_subr.h b/sys/fs/smbfs/smbfs_subr.h index a72b9e6..1511290 100644 --- a/sys/fs/smbfs/smbfs_subr.h +++ b/sys/fs/smbfs/smbfs_subr.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2001, Boris Popov + * Copyright (c) 2000-2001 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/smbfs/smbfs_vfsops.c b/sys/fs/smbfs/smbfs_vfsops.c index 2a328b3..16352d7 100644 --- a/sys/fs/smbfs/smbfs_vfsops.c +++ b/sys/fs/smbfs/smbfs_vfsops.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2001, Boris Popov + * Copyright (c) 2000-2001 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c index 0fd0233..830c249 100644 --- a/sys/fs/smbfs/smbfs_vnops.c +++ b/sys/fs/smbfs/smbfs_vnops.c @@ -10,12 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Boris Popov. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |