summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/coda/cnode.h5
-rw-r--r--sys/fs/coda/coda.h132
-rw-r--r--sys/fs/coda/coda_subr.c2
-rw-r--r--sys/fs/coda/coda_subr.h2
-rw-r--r--sys/fs/coda/coda_venus.c60
-rw-r--r--sys/fs/coda/coda_venus.h65
-rw-r--r--sys/fs/coda/coda_vfsops.c12
-rw-r--r--sys/fs/coda/coda_vfsops.h2
-rw-r--r--sys/fs/coda/coda_vnops.c8
-rw-r--r--sys/fs/deadfs/dead_vnops.c10
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c29
-rw-r--r--sys/fs/msdosfs/msdosfs_lookup.c9
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c6
-rw-r--r--sys/fs/nfs/nfs_commonkrpc.c2
-rw-r--r--sys/fs/nfs/nfs_commonport.c26
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c13
-rw-r--r--sys/fs/nfs/nfs_var.h7
-rw-r--r--sys/fs/nfs/nfsclstate.h2
-rw-r--r--sys/fs/nfs/nfsport.h11
-rw-r--r--sys/fs/nfs/nfsrvstate.h15
-rw-r--r--sys/fs/nfsclient/nfs.h6
-rw-r--r--sys/fs/nfsclient/nfs_clbio.c31
-rw-r--r--sys/fs/nfsclient/nfs_clnfsiod.c6
-rw-r--r--sys/fs/nfsclient/nfs_clnode.c2
-rw-r--r--sys/fs/nfsclient/nfs_clport.c2
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c50
-rw-r--r--sys/fs/nfsclient/nfs_clstate.c108
-rw-r--r--sys/fs/nfsclient/nfs_clvfsops.c6
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c40
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c50
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c30
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c766
-rw-r--r--sys/fs/nwfs/nwfs.h8
-rw-r--r--sys/fs/nwfs/nwfs_io.c8
-rw-r--r--sys/fs/nwfs/nwfs_ioctl.c8
-rw-r--r--sys/fs/nwfs/nwfs_mount.h8
-rw-r--r--sys/fs/nwfs/nwfs_node.c6
-rw-r--r--sys/fs/nwfs/nwfs_node.h6
-rw-r--r--sys/fs/nwfs/nwfs_subr.c6
-rw-r--r--sys/fs/nwfs/nwfs_subr.h8
-rw-r--r--sys/fs/nwfs/nwfs_vfsops.c6
-rw-r--r--sys/fs/nwfs/nwfs_vnops.c6
-rw-r--r--sys/fs/procfs/procfs_dbregs.c7
-rw-r--r--sys/fs/procfs/procfs_fpregs.c7
-rw-r--r--sys/fs/procfs/procfs_ioctl.c6
-rw-r--r--sys/fs/procfs/procfs_map.c8
-rw-r--r--sys/fs/procfs/procfs_regs.c7
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c2
-rw-r--r--sys/fs/smbfs/smbfs.h8
-rw-r--r--sys/fs/smbfs/smbfs_io.c8
-rw-r--r--sys/fs/smbfs/smbfs_node.c6
-rw-r--r--sys/fs/smbfs/smbfs_node.h8
-rw-r--r--sys/fs/smbfs/smbfs_smb.c6
-rw-r--r--sys/fs/smbfs/smbfs_subr.c8
-rw-r--r--sys/fs/smbfs/smbfs_subr.h8
-rw-r--r--sys/fs/smbfs/smbfs_vfsops.c8
-rw-r--r--sys/fs/smbfs/smbfs_vnops.c6
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
OpenPOWER on IntegriCloud