Date: Sun, 17 Aug 1997 23:53:25 +0200 From: Sebastian Lederer <lederer@bonn-online.com> To: freebsd-hackers@freebsd.org Subject: NFS locking Message-ID: <33F772D4.FB1AB014@bonn-online.com>
next in thread | raw e-mail | index | archive | help
Hi all, first the good news: I have successfully locked a file on a FreeBSD nfs server from a Solaris 2.5.1 nfs client. But that's about all right now. There are still pieces missing in the kernel and in the rpc.lockd, concering the server side. The client side of the nfs locking protocoll is yet another different story. Please see my other posting regarding the design of the rpc.lockd. There are still many unanswered questions there... But now I would like you to take a look the kernel code I've written to convert the nfs file handle to an open file. It seems to work, but since it is the very first kernel code I have ever done, I don't want to take chances (like leaking vnodes or memory). I have placed the whole thing as a subfunction of the nfssvc system call (I *know* Terry will love this), mainly because it depends on the nfs server anyway, and because it was convenient to do so (requires only 3 small patches). The new function: -- int nfssvc(NFSSVC_CNVT,struct nfs_cnvt_args *); struct nfs_cnvt_args { fhandle_t fh; /* The file handle */ struct sockaddr addr; /* Client's IP address*/ int authflag; /* Use Kerberos ? */ struct ucred cred; /* user credentials */ int exclusive; /* access mode 0=shared, 1=exclusive */ }; #define NFSSVC_CNVT 0x800 --- It returns -1 on error, and the open file descriptor on success. Strictly speaking, it does not work on nfs file handles, but on fhandle_t objects. The conversion to fhandle_t is done inside the rpc.lockd (this is just a cast for NFS Version 2). Here is the kernel code that does all the work (appended to nfs/nfs_subs.c): ------------------------------------------------------ int nfsrv_open_fh(struct proc *p, fhandle_t *fh, struct sockaddr *addr, int kerbflag, struct ucred *mycred, int exclusive, int *result_fd) { struct nfssvc_sock slp; struct vnode *vp; struct mbuf nam; /* struct filedesc *fdp = p->p_fd; */ struct file *f; int readonly; int error; int fd; int accessflags; bzero(&slp,sizeof(slp)); /* not used in nfsrv_fhtovp (?) */ bzero(&nam,sizeof(nam)); /* Put the sockaddr into the mbuf */ nam.m_data=(void *) addr; nam.m_len=addr->sa_len; /* Turn fhandle_t into locked vnode */ error=nfsrv_fhtovp(fh,TRUE,&vp,mycred,&slp,&nam,&readonly,kerbflag); if(error) { return error; } VREF(vp); /* Check permissions (mycred possibly modified by nfsrv_fhtovp) */ /* Must have read access for shared lock, write access for exclusive lock */ /* Check for read-only exports */ if(exclusive && readonly) { vput(vp); return EROFS; } accessflags = exclusive ? VREAD | VWRITE : VREAD; error = VOP_ACCESS(vp,accessflags,mycred,p); if(error) { vput(vp); return error; } /* allocate a new fd */ error=falloc(p,&f,&fd); if(error) { vput(vp); return error; } /* Tie the vnode to the fd */ f->f_flag = exclusive ? FREAD | FWRITE : FREAD; f->f_type = DTYPE_VNODE; f->f_ops = &vnops; f->f_data = (caddr_t) vp; VOP_UNLOCK(vp,0,p); *result_fd=fd; return 0; } ------------------------------------------------ There is also a diff to nfs/nfs_syscalls.c: -- *** nfs.orig/nfs_syscalls.c Wed Aug 13 13:20:47 1997 --- nfs/nfs_syscalls.c Fri Aug 15 09:54:19 1997 *************** *** 163,169 **** #endif /* NFS_NOSERVER */ /* ! * Nfs server psuedo system call for the nfsd's * Based on the flag value it either: * - adds a socket to the selection list * - remains in the kernel as an nfsd --- 163,169 ---- #endif /* NFS_NOSERVER */ /* ! * Nfs server pseudo system call for the nfsd's * Based on the flag value it either: * - adds a socket to the selection list * - remains in the kernel as an nfsd *************** *** 211,216 **** --- 211,235 ---- else error = ENXIO; #else /* !NFS_NOSERVER */ + else if (uap->flag & NFSSVC_CNVT) + { + struct nfs_cnvt_args cnvt_args; + + error = copyin(uap->argp, (caddr_t) &cnvt_args, + sizeof(cnvt_args)); + if(error) + return(error); + + error = nfsrv_open_fh(p,&cnvt_args.fh,&cnvt_args.addr, + cnvt_args.authflag, + &cnvt_args.cred, + cnvt_args.exclusive, + retval); + + return error; + } + + else if (uap->flag & NFSSVC_MNTD) { error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd)); if (error) -- That's it. Any comments welcome. Best regards, Sebastian Lederer -- Sebastian Lederer lederer@bonn-online.com
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?33F772D4.FB1AB014>