Skip site navigation (1)Skip section navigation (2)
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>