get rid of unneeded namei
[unix-history] / usr / src / sys / ufs / ffs / ffs_vnops.c
index 0d32449..492d1f5 100644 (file)
@@ -4,29 +4,29 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)ffs_vnops.c 7.51 (Berkeley) %G%
+ *     @(#)ffs_vnops.c 7.59 (Berkeley) %G%
  */
 
 #include "param.h"
 #include "systm.h"
  */
 
 #include "param.h"
 #include "systm.h"
-#include "user.h"
+#include "namei.h"
+#include "resourcevar.h"
 #include "kernel.h"
 #include "file.h"
 #include "stat.h"
 #include "buf.h"
 #include "proc.h"
 #include "kernel.h"
 #include "file.h"
 #include "stat.h"
 #include "buf.h"
 #include "proc.h"
-#include "socket.h"
-#include "socketvar.h"
 #include "conf.h"
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
 #include "fcntl.h"
 #include "malloc.h"
 #include "conf.h"
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
 #include "fcntl.h"
 #include "malloc.h"
-#include "../ufs/lockf.h"
-#include "../ufs/quota.h"
-#include "../ufs/inode.h"
-#include "../ufs/fs.h"
+
+#include "lockf.h"
+#include "quota.h"
+#include "inode.h"
+#include "fs.h"
 
 /*
  * Global vfs data structures for ufs
 
 /*
  * Global vfs data structures for ufs
@@ -112,8 +112,7 @@ int spec_lookup(),
        spec_select(),
        ufsspec_close(),
        spec_advlock(),
        spec_select(),
        ufsspec_close(),
        spec_advlock(),
-       spec_badop(),
-       spec_nullop();
+       spec_badop();
 
 struct vnodeops spec_inodeops = {
        spec_lookup,            /* lookup */
 
 struct vnodeops spec_inodeops = {
        spec_lookup,            /* lookup */
@@ -129,7 +128,7 @@ struct vnodeops spec_inodeops = {
        spec_ioctl,             /* ioctl */
        spec_select,            /* select */
        spec_badop,             /* mmap */
        spec_ioctl,             /* ioctl */
        spec_select,            /* select */
        spec_badop,             /* mmap */
-       spec_nullop,            /* fsync */
+       nullop,                 /* fsync */
        spec_badop,             /* seek */
        spec_badop,             /* remove */
        spec_badop,             /* link */
        spec_badop,             /* seek */
        spec_badop,             /* remove */
        spec_badop,             /* link */
@@ -162,8 +161,7 @@ int fifo_lookup(),
        ufsfifo_close(),
        fifo_print(),
        fifo_advlock(),
        ufsfifo_close(),
        fifo_print(),
        fifo_advlock(),
-       fifo_badop(),
-       fifo_nullop();
+       fifo_badop();
 
 struct vnodeops fifo_inodeops = {
        fifo_lookup,            /* lookup */
 
 struct vnodeops fifo_inodeops = {
        fifo_lookup,            /* lookup */
@@ -179,7 +177,7 @@ struct vnodeops fifo_inodeops = {
        fifo_ioctl,             /* ioctl */
        fifo_select,            /* select */
        fifo_badop,             /* mmap */
        fifo_ioctl,             /* ioctl */
        fifo_select,            /* select */
        fifo_badop,             /* mmap */
-       fifo_nullop,            /* fsync */
+       nullop,                 /* fsync */
        fifo_badop,             /* seek */
        fifo_badop,             /* remove */
        fifo_badop,             /* link */
        fifo_badop,             /* seek */
        fifo_badop,             /* remove */
        fifo_badop,             /* link */
@@ -402,6 +400,7 @@ ufs_setattr(vp, vap, cred)
        register struct vattr *vap;
        register struct ucred *cred;
 {
        register struct vattr *vap;
        register struct ucred *cred;
 {
+       struct proc *p = curproc;               /* XXX */
        register struct inode *ip = VTOI(vp);
        int error = 0;
 
        register struct inode *ip = VTOI(vp);
        int error = 0;
 
@@ -418,7 +417,7 @@ ufs_setattr(vp, vap, cred)
         * Go through the fields and update iff not VNOVAL.
         */
        if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
         * Go through the fields and update iff not VNOVAL.
         */
        if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
-               if (error = chown1(vp, vap->va_uid, vap->va_gid, cred))
+               if (error = chown1(vp, vap->va_uid, vap->va_gid, p))
                        return (error);
        if (vap->va_size != VNOVAL) {
                if (vp->v_type == VDIR)
                        return (error);
        if (vap->va_size != VNOVAL) {
                if (vp->v_type == VDIR)
@@ -428,7 +427,7 @@ ufs_setattr(vp, vap, cred)
        }
        if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
                if (cred->cr_uid != ip->i_uid &&
        }
        if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
                if (cred->cr_uid != ip->i_uid &&
-                   (error = suser(cred, &u.u_acflag)))
+                   (error = suser(cred, &p->p_acflag)))
                        return (error);
                if (vap->va_atime.tv_sec != VNOVAL)
                        ip->i_flag |= IACC;
                        return (error);
                if (vap->va_atime.tv_sec != VNOVAL)
                        ip->i_flag |= IACC;
@@ -439,10 +438,10 @@ ufs_setattr(vp, vap, cred)
                        return (error);
        }
        if (vap->va_mode != (u_short)VNOVAL)
                        return (error);
        }
        if (vap->va_mode != (u_short)VNOVAL)
-               error = chmod1(vp, (int)vap->va_mode, cred);
+               error = chmod1(vp, (int)vap->va_mode, p);
        if (vap->va_flags != VNOVAL) {
                if (cred->cr_uid != ip->i_uid &&
        if (vap->va_flags != VNOVAL) {
                if (cred->cr_uid != ip->i_uid &&
-                   (error = suser(cred, &u.u_acflag)))
+                   (error = suser(cred, &p->p_acflag)))
                        return (error);
                if (cred->cr_uid == 0) {
                        ip->i_flags = vap->va_flags;
                        return (error);
                if (cred->cr_uid == 0) {
                        ip->i_flags = vap->va_flags;
@@ -459,16 +458,17 @@ ufs_setattr(vp, vap, cred)
  * Change the mode on a file.
  * Inode must be locked before calling.
  */
  * Change the mode on a file.
  * Inode must be locked before calling.
  */
-chmod1(vp, mode, cred)
+chmod1(vp, mode, p)
        register struct vnode *vp;
        register int mode;
        register struct vnode *vp;
        register int mode;
-       struct ucred *cred;
+       struct proc *p;
 {
 {
+       register struct ucred *cred = p->p_ucred;
        register struct inode *ip = VTOI(vp);
        int error;
 
        if (cred->cr_uid != ip->i_uid &&
        register struct inode *ip = VTOI(vp);
        int error;
 
        if (cred->cr_uid != ip->i_uid &&
-           (error = suser(cred, &u.u_acflag)))
+           (error = suser(cred, &p->p_acflag)))
                return (error);
        if (cred->cr_uid) {
                if (vp->v_type != VDIR && (mode & ISVTX))
                return (error);
        if (cred->cr_uid) {
                if (vp->v_type != VDIR && (mode & ISVTX))
@@ -488,13 +488,14 @@ chmod1(vp, mode, cred)
  * Perform chown operation on inode ip;
  * inode must be locked prior to call.
  */
  * Perform chown operation on inode ip;
  * inode must be locked prior to call.
  */
-chown1(vp, uid, gid, cred)
+chown1(vp, uid, gid, p)
        register struct vnode *vp;
        uid_t uid;
        gid_t gid;
        register struct vnode *vp;
        uid_t uid;
        gid_t gid;
-       struct ucred *cred;
+       struct proc *p;
 {
        register struct inode *ip = VTOI(vp);
 {
        register struct inode *ip = VTOI(vp);
+       register struct ucred *cred = p->p_ucred;
        uid_t ouid;
        gid_t ogid;
        int error = 0;
        uid_t ouid;
        gid_t ogid;
        int error = 0;
@@ -514,7 +515,7 @@ chown1(vp, uid, gid, cred)
         */
        if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
            !groupmember((gid_t)gid, cred)) &&
         */
        if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
            !groupmember((gid_t)gid, cred)) &&
-           (error = suser(cred, &u.u_acflag)))
+           (error = suser(cred, &p->p_acflag)))
                return (error);
        ouid = ip->i_uid;
        ogid = ip->i_gid;
                return (error);
        ouid = ip->i_uid;
        ogid = ip->i_gid;
@@ -657,6 +658,7 @@ ufs_write(vp, uio, ioflag, cred)
        int ioflag;
        struct ucred *cred;
 {
        int ioflag;
        struct ucred *cred;
 {
+       struct proc *p = curproc;               /* XXX */
        register struct inode *ip = VTOI(vp);
        register struct fs *fs;
        struct buf *bp;
        register struct inode *ip = VTOI(vp);
        register struct fs *fs;
        struct buf *bp;
@@ -693,8 +695,8 @@ ufs_write(vp, uio, ioflag, cred)
         */
        if (vp->v_type == VREG &&
            uio->uio_offset + uio->uio_resid >
         */
        if (vp->v_type == VREG &&
            uio->uio_offset + uio->uio_resid >
-             u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
-               psignal(u.u_procp, SIGXFSZ);
+             p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
+               psignal(p, SIGXFSZ);
                return (EFBIG);
        }
        resid = uio->uio_resid;
                return (EFBIG);
        }
        resid = uio->uio_resid;
@@ -849,20 +851,18 @@ ufs_link(vp, ndp)
        register struct inode *ip = VTOI(vp);
        int error;
 
        register struct inode *ip = VTOI(vp);
        int error;
 
+       if ((unsigned short)ip->i_nlink >= LINK_MAX)
+               return (EMLINK);
        if (ndp->ni_dvp != vp)
                ILOCK(ip);
        if (ndp->ni_dvp != vp)
                ILOCK(ip);
-       if (ip->i_nlink == LINK_MAX - 1) {
-               error = EMLINK;
-               goto out;
-       }
        ip->i_nlink++;
        ip->i_flag |= ICHG;
        error = iupdat(ip, &time, &time, 1);
        if (!error)
                error = direnter(ip, ndp);
        ip->i_nlink++;
        ip->i_flag |= ICHG;
        error = iupdat(ip, &time, &time, 1);
        if (!error)
                error = direnter(ip, ndp);
-out:
        if (ndp->ni_dvp != vp)
                IUNLOCK(ip);
        if (ndp->ni_dvp != vp)
                IUNLOCK(ip);
+       vput(ndp->ni_dvp);
        if (error) {
                ip->i_nlink--;
                ip->i_flag |= ICHG;
        if (error) {
                ip->i_nlink--;
                ip->i_flag |= ICHG;
@@ -897,6 +897,7 @@ out:
 ufs_rename(fndp, tndp)
        register struct nameidata *fndp, *tndp;
 {
 ufs_rename(fndp, tndp)
        register struct nameidata *fndp, *tndp;
 {
+       struct proc *p = curproc;               /* XXX */
        register struct inode *ip, *xp, *dp;
        struct dirtemplate dirbuf;
        int doingdirectory = 0, oldparent = 0, newparent = 0;
        register struct inode *ip, *xp, *dp;
        struct dirtemplate dirbuf;
        int doingdirectory = 0, oldparent = 0, newparent = 0;
@@ -965,14 +966,15 @@ ufs_rename(fndp, tndp)
                VOP_UNLOCK(fndp->ni_vp);
                if (error)
                        goto bad;
                VOP_UNLOCK(fndp->ni_vp);
                if (error)
                        goto bad;
-               tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
+               tndp->ni_nameiop &= ~(MODMASK | OPMASK);
+               tndp->ni_nameiop |= RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
                        dp = VTOI(tndp->ni_dvp);
                        if (xp != NULL)
                                iput(xp);
                        if (error = checkpath(ip, dp, tndp->ni_cred))
                                goto out;
                do {
                        dp = VTOI(tndp->ni_dvp);
                        if (xp != NULL)
                                iput(xp);
                        if (error = checkpath(ip, dp, tndp->ni_cred))
                                goto out;
-                       if (error = namei(tndp))
+                       if (error = namei(tndp, p))
                                goto out;
                        xp = NULL;
                        if (tndp->ni_vp)
                                goto out;
                        xp = NULL;
                        if (tndp->ni_vp)
@@ -995,12 +997,24 @@ ufs_rename(fndp, tndp)
                 * parent we don't fool with the link count.
                 */
                if (doingdirectory && newparent) {
                 * parent we don't fool with the link count.
                 */
                if (doingdirectory && newparent) {
+                       if ((unsigned short)dp->i_nlink >= LINK_MAX) {
+                               error = EMLINK;
+                               goto bad;
+                       }
                        dp->i_nlink++;
                        dp->i_flag |= ICHG;
                        dp->i_nlink++;
                        dp->i_flag |= ICHG;
-                       error = iupdat(dp, &time, &time, 1);
+                       if (error = iupdat(dp, &time, &time, 1))
+                               goto bad;
+               }
+               if (error = direnter(ip, tndp)) {
+                       if (doingdirectory && newparent) {
+                               dp->i_nlink--;
+                               dp->i_flag |= ICHG;
+                               (void) iupdat(dp, &time, &time, 1);
+                       }
+                       goto bad;
                }
                }
-               if (error = direnter(ip, tndp))
-                       goto out;
+               iput(dp);
        } else {
                if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
                        panic("rename: EXDEV");
        } else {
                if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
                        panic("rename: EXDEV");
@@ -1080,8 +1094,9 @@ ufs_rename(fndp, tndp)
        /*
         * 3) Unlink the source.
         */
        /*
         * 3) Unlink the source.
         */
-       fndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
-       (void)namei(fndp);
+       fndp->ni_nameiop &= ~(MODMASK | OPMASK);
+       fndp->ni_nameiop |= DELETE | LOCKPARENT | LOCKLEAF;
+       (void)namei(fndp, p);
        if (fndp->ni_vp != NULL) {
                xp = VTOI(fndp->ni_vp);
                dp = VTOI(fndp->ni_dvp);
        if (fndp->ni_vp != NULL) {
                xp = VTOI(fndp->ni_vp);
                dp = VTOI(fndp->ni_dvp);
@@ -1187,6 +1202,10 @@ ufs_mkdir(ndp, vap)
 
        dvp = ndp->ni_dvp;
        dp = VTOI(dvp);
 
        dvp = ndp->ni_dvp;
        dp = VTOI(dvp);
+       if ((unsigned short)dp->i_nlink >= LINK_MAX) {
+               iput(dp);
+               return (EMLINK);
+       }
        dmode = vap->va_mode&0777;
        dmode |= IFDIR;
        /*
        dmode = vap->va_mode&0777;
        dmode |= IFDIR;
        /*
@@ -1226,7 +1245,8 @@ ufs_mkdir(ndp, vap)
         */
        dp->i_nlink++;
        dp->i_flag |= ICHG;
         */
        dp->i_nlink++;
        dp->i_flag |= ICHG;
-       error = iupdat(dp, &time, &time, 1);
+       if (error = iupdat(dp, &time, &time, 1))
+               goto bad;
 
        /*
         * Initialize directory with "."
 
        /*
         * Initialize directory with "."
@@ -1254,16 +1274,9 @@ ufs_mkdir(ndp, vap)
         * install the entry for it in
         * the parent directory.
         */
         * install the entry for it in
         * the parent directory.
         */
-       error = direnter(ip, ndp);
-       dp = NULL;
-       if (error) {
-               ndp->ni_nameiop = LOOKUP | NOCACHE;
-               error = namei(ndp);
-               if (!error) {
-                       dp = VTOI(ndp->ni_vp);
-                       dp->i_nlink--;
-                       dp->i_flag |= ICHG;
-               }
+       if (error = direnter(ip, ndp)) {
+               dp->i_nlink--;
+               dp->i_flag |= ICHG;
        }
 bad:
        /*
        }
 bad:
        /*
@@ -1277,8 +1290,7 @@ bad:
                iput(ip);
        } else
                ndp->ni_vp = ITOV(ip);
                iput(ip);
        } else
                ndp->ni_vp = ITOV(ip);
-       if (dp)
-               iput(dp);
+       iput(dp);
        return (error);
 }
 
        return (error);
 }
 
@@ -1709,10 +1721,9 @@ maknode(mode, ndp, ipp)
         */
        if (error = iupdat(ip, &time, &time, 1))
                goto bad;
         */
        if (error = iupdat(ip, &time, &time, 1))
                goto bad;
-       if (error = direnter(ip, ndp)) {
-               pdir = NULL;
+       if (error = direnter(ip, ndp))
                goto bad;
                goto bad;
-       }
+       iput(pdir);
        *ipp = ip;
        return (0);
 
        *ipp = ip;
        return (0);
 
@@ -1721,8 +1732,7 @@ bad:
         * Write error occurred trying to update the inode
         * or the directory so must deallocate the inode.
         */
         * Write error occurred trying to update the inode
         * or the directory so must deallocate the inode.
         */
-       if (pdir)
-               iput(pdir);
+       iput(pdir);
        ip->i_nlink = 0;
        ip->i_flag |= ICHG;
        iput(ip);
        ip->i_nlink = 0;
        ip->i_flag |= ICHG;
        iput(ip);
@@ -1779,7 +1789,7 @@ ufs_advlock(vp, id, op, fl, flags)
        if (fl->l_len == 0)
                end = -1;
        else
        if (fl->l_len == 0)
                end = -1;
        else
-               end = start + fl->l_len;
+               end = start + fl->l_len - 1;
        /*
         * Create the lockf structure
         */
        /*
         * Create the lockf structure
         */
@@ -1797,13 +1807,17 @@ ufs_advlock(vp, id, op, fl, flags)
         */
        switch(op) {
        case F_SETLK:
         */
        switch(op) {
        case F_SETLK:
-               return (ufs_setlock(lock));
+               return (lf_setlock(lock));
 
        case F_UNLCK:
 
        case F_UNLCK:
-               return (ufs_advunlock(lock));
+               error = lf_clearlock(lock);
+               FREE(lock, M_LOCKF);
+               return (error);
 
        case F_GETLK:
 
        case F_GETLK:
-               return (ufs_advgetlock(lock, fl));
+               error = lf_getlock(lock, fl);
+               FREE(lock, M_LOCKF);
+               return (error);
        
        default:
                free(lock, M_LOCKF);
        
        default:
                free(lock, M_LOCKF);
@@ -1811,163 +1825,3 @@ ufs_advlock(vp, id, op, fl, flags)
        }
        /* NOTREACHED */
 }
        }
        /* NOTREACHED */
 }
-
-/*
- * This variable controls the maximum number of processes that will
- * be checked in doing deadlock detection.
- */
-int maxlockdepth = MAXDEPTH;
-
-/*
- * Set a byte-range lock.
- */
-ufs_setlock(lock)
-       register struct lockf *lock;
-{
-       register struct inode *ip = lock->lf_inode;
-       register struct lockf *block;
-       static char lockstr[] = "lockf";
-       int priority, error;
-
-#ifdef LOCKF_DEBUG
-       if (lockf_debug & 4)
-               lf_print("ufs_setlock", lock);
-#endif /* LOCKF_DEBUG */
-
-       /*
-        * Set the priority
-        */
-       priority = PLOCK;
-       if ((lock->lf_type & F_WRLCK) == 0)
-               priority += 4;
-       priority |= PCATCH;
-       /*
-        * Scan lock list for this file looking for locks that would block us.
-        */
-       while (block = lf_getblock(lock)) {
-               /*
-                * Free the structure and return if nonblocking.
-                */
-               if ((lock->lf_flags & F_WAIT) == 0) {
-                       free(lock, M_LOCKF);
-                       return (EAGAIN);
-               }
-               /*
-                * We are blocked. Since flock style locks cover
-                * the whole file, there is no chance for deadlock.
-                * For byte-range locks we must check for deadlock.
-                *
-                * Deadlock detection is done by looking through the
-                * wait channels to see if there are any cycles that
-                * involve us. MAXDEPTH is set just to make sure we
-                * do not go off into neverland.
-                */
-               if ((lock->lf_flags & F_POSIX) &&
-                   (block->lf_flags & F_POSIX)) {
-                       register struct proc *wproc;
-                       register struct lockf *waitblock;
-                       int i = 0;
-
-                       /* The block is waiting on something */
-                       wproc = (struct proc *)block->lf_id;
-                       while (wproc->p_wchan &&
-                              (wproc->p_wmesg == lockstr) &&
-                              (i++ < maxlockdepth)) {
-                               waitblock = (struct lockf *)wproc->p_wchan;
-                               /* Get the owner of the blocking lock */
-                               waitblock = waitblock->lf_next;
-                               if ((waitblock->lf_flags & F_POSIX) == 0)
-                                       break;
-                               wproc = (struct proc *)waitblock->lf_id;
-                               if (wproc == (struct proc *)lock->lf_id) {
-                                       free(lock, M_LOCKF);
-                                       return (EDEADLK);
-                               }
-                       }
-               }
-               /*
-                * Add our lock to the blocked
-                * list and sleep until we're free.
-                */
-#ifdef LOCKF_DEBUG
-               if (lockf_debug & 4)
-                       lf_print("ufs_advlock: blocking on", block);
-#endif /* LOCKF_DEBUG */
-               /*
-                * Remember who blocked us (for deadlock detection)
-                */
-               lock->lf_next = block;
-               lf_addblock(block, lock);
-               if (error = tsleep((caddr_t *)lock, priority, lockstr, 0)) {
-                       free(lock, M_LOCKF);
-                       return (error);
-               }
-       }
-       /*
-        * No blocks!!  Add the lock.  Note that addlock will
-        * downgrade or upgrade any overlapping locks this
-        * process already owns.
-        */
-#ifdef LOCKF_DEBUG
-       if (lockf_debug & 4)
-               lf_print("ufs_advlock: got the lock", lock);
-#endif /* LOCKF_DEBUG */
-       lf_addlock(lock);
-       return (0);
-}
-
-/*
- * Remove a byte-range lock on an inode.
- */
-ufs_advunlock(lock)
-       struct lockf *lock;
-{
-       struct lockf *blocklist;
-
-       if (lock->lf_inode->i_lockf == (struct lockf *)0)
-               return (0);
-#ifdef LOCKF_DEBUG
-       if (lockf_debug & 4)
-               lf_print("ufs_advunlock", lock);
-#endif /* LOCKF_DEBUG */
-       /*
-        * Generally, find the lock (or an overlap to that lock)
-        * and remove it (or shrink it), then wakeup anyone we can.
-        */
-       blocklist = lf_remove(lock);
-       FREE(lock, M_LOCKF);
-       lf_wakelock(blocklist);
-       return (0);
-}
-
-/*
- * Return the blocking pid
- */
-ufs_advgetlock(lock, fl)
-       register struct lockf *lock;
-       register struct flock *fl;
-{
-       register struct lockf *block;
-       off_t start, end;
-
-#ifdef LOCKF_DEBUG
-       if (lockf_debug & 4)
-               lf_print("ufs_advgetlock", lock);
-#endif /* LOCKF_DEBUG */
-
-       if (block = lf_getblock(lock)) {
-               fl->l_type = block->lf_type;
-               fl->l_whence = SEEK_SET;
-               fl->l_start = block->lf_start;
-               if (block->lf_end == -1)
-                       fl->l_len = 0;
-               else
-                       fl->l_len = block->lf_end - block->lf_start;
-               if (block->lf_flags & F_POSIX)
-                       fl->l_pid = ((struct proc *)(block->lf_id))->p_pid;
-               else
-                       fl->l_pid = -1;
-       }
-       FREE(lock, M_LOCKF);
-       return (0);
-}