!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/fs/xfs_dmapi/   drwxr-xr-x
Free 318.34 GB of 458.09 GB (69.49%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     dmapi_event.c (24.84 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * 
 * Further, this software is distributed without any warranty that it is
 * free of the rightful claim of any third person regarding infringement
 * or the like.  Any license provided herein, whether implied or
 * otherwise, applies only to this software file.  Patent licenses, if
 * any, provided herein do not apply to combinations of this program with
 * other software, or any other product whatsoever.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 * 
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
 * Mountain View, CA  94043, or:
 * 
 * http://www.sgi.com 
 * 
 * For further information regarding this notice, see: 
 * 
 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 */

#include "dmapi_private.h"
#include <linux/module.h> /* for EXPORT_SYMBOL */

/* The "rights" portion of the DMAPI spec is not currently implemented.  A
   framework for rights is provided in the code, but turns out to be a noop
   in practice.  The following comments are a brain dump to serve as input to
   the poor soul that eventually has to get DMAPI rights working in IRIX.

   A DMAPI right is similar but not identical to the mrlock_t mechanism
   already used within the kernel.  The similarities are that it is a
   sleeping lock, and that a multiple-reader, single-writer protocol is used.
   How locks are obtained and dropped are different however.  With a mrlock_t,
   a thread grabs the lock, does some stuff, then drops the lock, and all other
   threads block in the meantime (assuming a write lock).  There is a one-to-
   one relationship between the lock and the thread which obtained the lock.
   Not so with DMAPI right locks.  A DMAPI lock is associated with a particular
   session/token/hanp/hlen quad; since there is a dm_tokdata_t structure for
   each such quad, you can think of it as a one-to-one relationship between the
   lock and a dm_tokdata_t.  Any application thread which presents the correct
   quad is entitled to grab or release the lock, or to use the rights 
   associated with that lock.  The thread that grabs the lock does not have to
   be the one to use the lock, nor does it have to be the thread which drops
   the lock.  The lock can be held for very long periods of time, even across
   multiple systems calls by multiple application threads.  The idea is that a
   coordinated group of DMAPI application threads can grab the lock, issue a
   series of inode accesses and/or updates, then drop the lock, and be assured
   that no other thread in the system could be modifying the inode at the same
   time.  The kernel is expected to blindly trust that the application will
   not forget to unlock inodes it has locked, and will not deadlock itself
   against the kernel.

   There are two types of DMAPI rights, file object (inode) and filesystem
   object (superblock?).  An inode right is the equivalent of the combination
   of both the XFS ilock and iolock; if held exclusively, no data or metadata
   within the file can be changed by non-lock-holding threads.  The filesystem
   object lock is a little fuzzier; I think that if it is held, things like
   unmounts can be blocked, plus there is an event mask associated with the
   filesystem which can't be updated without the lock.  (By the way, that
   event mask is supposed to be persistent in the superblock; add that to
   your worklist :-)

   All events generated by XFS currently arrive with no rights, i.e.
   DM_RIGHT_NULL, and return to the filesystem with no rights.  It would be
   smart to leave it this way if possible, because it otherwise becomes more
   likely that an application thread will deadlock against the kernel if the
   one responsible for calling dm_get_events() happens to touch a file which
   was locked at the time the event was queued.  Since the thread is blocked,
   it can't read the event in order to find and drop the lock.  Catch-22.  If
   you do have events that arrive with non-null rights, then dm_enqueue() needs
   to have code added for synchronous events which atomically switches the
   right from being a thread-based right to a dm_tokdata_t-based right without
   allowing the lock to drop in between.  You will probably have to add a new
   dm_fsys_vector entry point to do this.  The lock can't be lost during the
   switch, or other threads might change the inode or superblock in between.
   Likewise, if you need to return to the filesystem holding a right, then
   you need a DMAPI-to-thread atomic switch to occur, most likely in
   dm_change_right().  Again, the lock must not be lost during the switch; the
   DMAPI spec spends a couple of pages stressing this.  Another dm_fsys_vector
   entry point is probably the answer.

   There are several assumptions implied in the current layout of the code.
   First of all, if an event returns to the filesystem with a return value of
   zero, then the filesystem can assume that any locks (rights) held at the
   start of the event are still in effect at the end of the event.  (Note that
   the application could have temporarily dropped and reaquired the right
   while the event was outstanding, however).  If the event returns to the
   filesystem with an errno, then the filesystem must assume that it has lost
   any and all rights associated with any of the objects in the event.  This
   was done for a couple of reasons.  First of all, since an errno is being
   returned, most likely the filesystem is going to immediately drop all the
   locks anyway.  If the DMAPI code was required to unconditionally reobtain
   all locks before returning to the filesystem, then dm_pending() wouldn't
   work for NFS server threads because the process would block indefinitely
   trying to get its thread-based rights back, because the DMAPI-rights
   associated with the dm_tokdata_t in the outstanding event would prevent
   the rights from being obtained.  That would be a bad thing.  We wouldn't
   be able to let users Cntl-C out of read/write/truncate events either.

   If a case should ever surface where the thread has lost its rights even
   though it has a zero return status, or where the thread has rights even
   though it is returning with an errno, then this logic will have to be
   reworked.  This could be done by changing the 'right' parameters on all
   the event calls to (dm_right_t *), so that they could serve both as IN
   and OUT parameters.

   Some events such as DM_EVENT_DESTROY arrive without holding a vnode
   reference; if you don't have a vnode reference, you can't have a right
   on the file.

   One more quirk.  The DM_EVENT_UNMOUNT event is defined to be synchronous
   when it's behavior is asynchronous.  If an unmount event arrives with
   rights, the event should return with the same rights and should NOT leave
   any rights in the dm_tokdata_t where the application could use them.
*/


#define    GETNEXTOFF(vdat)    ((vdat).vd_offset + (vdat).vd_length)
#define    HANDLE_SIZE(tdp)    \
    ((tdp)->td_type & DM_TDT_VFS ? FSHSIZE : XFS_HSIZE((tdp)->td_handle))


/* Given a behavior descriptor pointer in a filesystem known to support DMAPI,
   build a tdp structure for the corresponding vnode.
*/

static dm_tokdata_t *
dm_bhv_data(
    bhv_desc_t      *bdp,
    dm_right_t    right,
    int        referenced)    /* != 0, caller holds vnode reference */
{
    int        error;
    dm_tokdata_t    *tdp;
    vnode_t        *vp = BHV_TO_VNODE(bdp);

    tdp = kmem_alloc(sizeof(*tdp), KM_SLEEP);

    tdp->td_next = NULL;
    tdp->td_tevp = NULL;
    tdp->td_app_ref = 0;
    tdp->td_orig_right = right;
    tdp->td_right = right;
    tdp->td_flags = DM_TDF_ORIG;
    if (referenced) {
        tdp->td_flags |= DM_TDF_EVTREF;
    }

    if (vp->v_type == VREG) {
        tdp->td_type = DM_TDT_REG;
    } else if (vp->v_type == VDIR) {
        tdp->td_type = DM_TDT_DIR;
    } else if (vp->v_type == VLNK) {
        tdp->td_type = DM_TDT_LNK;
    } else {
        tdp->td_type = DM_TDT_OTH;
    }

    if (referenced) {
        tdp->td_bdp = bdp;
    } else {
        tdp->td_bdp = 0;
    }
    tdp->td_vcount = 0;

    if ((error = dm_vp_to_handle(vp, &tdp->td_handle)) != 0) {
        panic("dm_bhv_data: dm_vp_to_handle failed for vp %p in "
            "a DMAPI filesystem, errno %d\n", vp, error);
    }

    return(tdp);
}


/* Given a vfs pointer to a filesystem known to support DMAPI, build a tdp
   structure for that vfsp.
*/
static dm_tokdata_t *
dm_vfs_data(
    vfs_t        *vfsp,
    vnode_t        *vp,        /* will be NULL for DM_EVENT_UNMOUNT */
    dm_right_t    right)
{
    dm_tokdata_t    *tdp;

    tdp = kmem_alloc(sizeof(*tdp), KM_SLEEP);

    tdp->td_next = NULL;
    tdp->td_tevp = NULL;
    tdp->td_app_ref = 0;
    tdp->td_orig_right = right;
    tdp->td_right = right;
    tdp->td_flags = DM_TDF_ORIG;
    if (vp) {
        tdp->td_flags |= DM_TDF_EVTREF;
    }
    tdp->td_type = DM_TDT_VFS;
    if (vp) {
        tdp->td_bdp = bhv_base_unlocked(VN_BHV_HEAD(vp));
    } else {
        tdp->td_bdp = 0;
    }
    tdp->td_vcount = 0;

        bcopy(vfsp->vfs_altfsid, &tdp->td_handle.ha_fsid, sizeof(fsid_t));
    bzero((char *)&tdp->td_handle.ha_fsid + sizeof(fsid_t),
        sizeof(tdp->td_handle) - sizeof(fsid_t));

    return(tdp);
}


/* Link a tdp structure into the tevp. */

static void
dm_add_handle_to_event(
    dm_tokevent_t    *tevp,
    dm_tokdata_t    *tdp)
{
    tdp->td_next = tevp->te_tdp;
    tevp->te_tdp = tdp;
    tdp->td_tevp = tevp;
}


/* Generate the given data event for the vnode, and wait for a reply.  The
   caller must guarantee that the vnode's reference count is greater than zero
   so that the filesystem can't disappear while the request is outstanding.
*/

int
dm_send_data_event(
    dm_eventtype_t    event,
    bhv_desc_t    *bdp,
    dm_right_t    vp_right,    /* current right for vp */
    off_t        offset,
    size_t        length,
    int        flags)        /* 0 or DM_FLAGS_NDELAY */
{
    dm_data_event_t    *datap;
    dm_tokevent_t    *tevp;
    dm_tokdata_t    *tdp;
    vnode_t        *vp;
    int        error;

    vp = BHV_TO_VNODE(bdp);
    tdp = dm_bhv_data(bdp, vp_right, /* reference held */ 1);

    /* Calculate the size of the event in bytes, create an event structure
       for it, and insert the file's handle into the event.
    */

    tevp = dm_evt_create_tevp(event, HANDLE_SIZE(tdp), (void **)&datap);
    dm_add_handle_to_event(tevp, tdp);

    /* Now fill in all the dm_data_event_t fields. */

    datap->de_handle.vd_offset = sizeof(*datap);
    datap->de_handle.vd_length = HANDLE_SIZE(tdp);
    bcopy(&tdp->td_handle, (char *)datap + datap->de_handle.vd_offset,
        datap->de_handle.vd_length);
    datap->de_offset = offset;
    datap->de_length = length;

    /* Queue the message and wait for the reply. */

    error = dm_enqueue_normal_event(vp->v_vfsp, tevp, flags);

    /* If no errors occurred, we must leave with the same rights we had
       upon entry.  If errors occurred, we must leave with no rights. 
    */

    dm_evt_rele_tevp(tevp, error);

    return(error);
}


/* Generate the destroy event for the vnode and wait until the request has been
   queued.  The caller does not hold a vnode reference or a right on the vnode,
   but it must otherwise lock down the vnode such that the filesystem can't
   disappear while the request is waiting to be queued.  While waiting to be
   queued, the vnode must not be referenceable either by path or by a call
   to dm_handle_to_vp().
*/

int
dm_send_destroy_event(
    bhv_desc_t    *bdp,
    dm_right_t    vp_right)    /* always DM_RIGHT_NULL */
{
    dm_fsys_vector_t *fsys_vector;
    dm_tokevent_t    *tevp;
    dm_tokdata_t    *tdp;
    dm_destroy_event_t *destp;
    dm_attrname_t    attrname;
    vnode_t        *vp;
    char        *value;
    int        value_len;
    int        error;

    vp = BHV_TO_VNODE(bdp);
    tdp = dm_bhv_data(bdp, vp_right, /* no reference held */ 0);

    if ((error = dm_waitfor_destroy_attrname(vp->v_vfsp, &attrname)) != 0)
        return(error);

    /* If a return-on-destroy attribute name exists for this filesystem,
       see if the object being deleted has this attribute.  If the object
       doesn't have the attribute or if we encounter an error, then send
       the event without the attribute.
     */

    value_len = -1;        /* because zero is a valid attribute length */
    if (attrname.an_chars[0] != '\0') {
        fsys_vector = dm_fsys_vector(bdp);
        (void)fsys_vector->get_destroy_dmattr(bdp, vp_right, &attrname,
            &value, &value_len);
    }

    /* Now that we know the size of the attribute value, if any, calculate
       the size of the event in bytes, create an event structure for it,
       and insert the handle into the event.
    */

    tevp = dm_evt_create_tevp(DM_EVENT_DESTROY,
        HANDLE_SIZE(tdp) + (value_len >= 0 ? value_len : 0),
        (void **)&destp);
    dm_add_handle_to_event(tevp, tdp);

    /* Now fill in all the dm_destroy_event_t fields. */

    destp->ds_handle.vd_offset = sizeof(*destp);
    destp->ds_handle.vd_length = HANDLE_SIZE(tdp);
    bcopy(&tdp->td_handle, (char *)destp + destp->ds_handle.vd_offset,
        destp->ds_handle.vd_length);
    if (value_len >= 0) {
        destp->ds_attrname = attrname;
        destp->ds_attrcopy.vd_length = value_len;
        if (value_len == 0) {
            destp->ds_attrcopy.vd_offset = 0;
        } else {
            destp->ds_attrcopy.vd_offset = GETNEXTOFF(destp->ds_handle);
            bcopy(value, (char *)destp + destp->ds_attrcopy.vd_offset,
                value_len);
            kmem_free(value, value_len);
        }
    }

    /* Queue the message asynchronously. */

    error = dm_enqueue_normal_event(vp->v_vfsp, tevp, 0);

    /* Since we had no rights upon entry, we have none to reobtain before
       leaving.
    */

    dm_evt_rele_tevp(tevp, 1);

    return(error);
}


/* The dm_mount_event_t event is sent in turn to all sessions that have asked
   for it until one either rejects it or accepts it.  The filesystem is not
   going anywhere because the mount is blocked until the event is answered.
*/

int
dm_send_mount_event(
    vfs_t        *vfsp,        /* filesystem being mounted */
    dm_right_t    vfsp_right,
    bhv_desc_t    *bdp,        /* mounted on directory */
    dm_right_t    vp_right,
    bhv_desc_t    *rootbdp,
    dm_right_t    rootvp_right,
    char        *name1,        /* mount path */
    char        *name2)        /* filesystem device name */
{
    int        error;
    dm_tokevent_t    *tevp;
    dm_tokdata_t    *tdp1;        /* filesystem handle for event */
    dm_tokdata_t    *tdp2 = NULL;    /* file handle for mounted-on dir. */
    dm_tokdata_t    *tdp3;        /* file handle for root vnode */
    dm_mount_event_t *mp;
    size_t        nextoff;
    vnode_t        *vp = NULL; /* mounted on directory */
    vnode_t        *rootvp = BHV_TO_VNODE(rootbdp);

    /* Convert the vfsp to a filesystem handle, and vp and rootvp into
       file handles.  vp (the mounted-on directory) may not have a handle
       if it is a different filesystem type such as EFS which does not
       support DMAPI.
    */

    if(bdp)
        vp = BHV_TO_VNODE(bdp);

    tdp1 = dm_vfs_data(vfsp, rootvp, vfsp_right);

    if ((vp == NULL) || dm_check_dmapi_vp(vp)) {
        vp = NULL;    /* assume we are mounting on non XFS */
    } else {
        tdp2 = dm_bhv_data(bdp, vp_right, /* reference held */ 1);
    }
    
    tdp3 = dm_bhv_data(rootbdp, rootvp_right, /* reference held */ 1);

    /* Calculate the size of the event in bytes, create an event structure
       for it, and insert the handles into the event.
    */

    tevp = dm_evt_create_tevp(DM_EVENT_MOUNT,
            HANDLE_SIZE(tdp1) + (vp ? HANDLE_SIZE(tdp2) : 0) +
            HANDLE_SIZE(tdp3) + strlen(name1) + 1 +
            strlen(name2) + 1, (void **)&mp);

    dm_add_handle_to_event(tevp, tdp1);
    if (vp)
        dm_add_handle_to_event(tevp, tdp2);
    dm_add_handle_to_event(tevp, tdp3);

    /* Now fill in all the dm_mount_event_t fields. */

    mp->me_handle1.vd_offset = sizeof(*mp);
    mp->me_handle1.vd_length = HANDLE_SIZE(tdp1);
    bcopy(&tdp1->td_handle, (char *) mp + mp->me_handle1.vd_offset,
            mp->me_handle1.vd_length);
    nextoff = GETNEXTOFF(mp->me_handle1);

    if (vp) {
        mp->me_handle2.vd_offset = nextoff;
        mp->me_handle2.vd_length = HANDLE_SIZE(tdp2);
        bcopy(&tdp2->td_handle, (char *)mp + mp->me_handle2.vd_offset,
            mp->me_handle2.vd_length);
        nextoff = GETNEXTOFF(mp->me_handle2);
    }

    mp->me_name1.vd_offset = nextoff;
    mp->me_name1.vd_length = strlen(name1) + 1;
    bcopy(name1, (char *)mp + mp->me_name1.vd_offset, mp->me_name1.vd_length);
    nextoff = GETNEXTOFF(mp->me_name1);

    mp->me_name2.vd_offset = nextoff;
    mp->me_name2.vd_length = strlen(name2) + 1;
    bcopy(name2, (char *)mp + mp->me_name2.vd_offset, mp->me_name2.vd_length);
    nextoff = GETNEXTOFF(mp->me_name2);

    mp->me_roothandle.vd_offset = nextoff;
    mp->me_roothandle.vd_length = HANDLE_SIZE(tdp3);
    bcopy(&tdp3->td_handle, (char *)mp + mp->me_roothandle.vd_offset,
            mp->me_roothandle.vd_length);

    mp->me_mode = (vfsp->vfs_flag & VFS_RDONLY ? DM_MOUNT_RDONLY : 0);

    /* Queue the message and wait for the reply. */

    error = dm_enqueue_mount_event(vfsp, tevp);

    /* If no errors occurred, we must leave with the same rights we had
       upon entry.  If errors occurred, we must leave with no rights. 
    */

    dm_evt_rele_tevp(tevp, error);

    return(error);
}


/* Generate an DM_EVENT_UNMOUNT event and wait for a reply.  The 'retcode'
   field indicates whether this is a successful or unsuccessful unmount.
   If successful, the filesystem is already unmounted, and any pending handle
   reference to the filesystem will be failed.  If the unmount was
   unsuccessful, then the filesystem will be placed back into full service.

   The DM_EVENT_UNMOUNT event should really be asynchronous, because the
   application has no control over whether or not the unmount succeeds.  (The
   DMAPI spec defined it that way because asynchronous events aren't always
   guaranteed to be delivered.)

   Since the filesystem is already unmounted in the successful case, the
   DM_EVENT_UNMOUNT event can't make available any vnode to be used in
   subsequent sid/hanp/hlen/token calls by the application.  The event will
   hang around until the application does a DM_RESP_CONTINUE, but the handle
   within the event is unusable by the application.
*/

void
dm_send_unmount_event(
    vfs_t        *vfsp,
    vnode_t        *vp,        /* NULL if unmount successful */
    dm_right_t    vfsp_right,
    mode_t        mode,
    int        retcode,    /* errno, if unmount failed */
    int        flags)
{
    dm_namesp_event_t    *np;
    dm_tokevent_t    *tevp;
    dm_tokdata_t    *tdp1;

    tdp1 = dm_vfs_data(vfsp, vp, vfsp_right);

    /* If the unmount failed, put the filesystem back into full service,
       allowing blocked handle references to finish.  If it succeeded, put
       the filesystem into the DM_STATE_UNMOUNTED state and fail all
       blocked DM_NO_TOKEN handle accesses.
    */

    if (retcode != 0) {    /* unmount was unsuccessful */
        dm_change_fsys_entry(vfsp, DM_STATE_MOUNTED);
    } else {
        dm_change_fsys_entry(vfsp, DM_STATE_UNMOUNTED);
    }

    /* If the event wasn't in the filesystem dm_eventset_t, just remove
       the filesystem from the list of DMAPI filesystems and return.
    */

    if (flags & DM_FLAGS_UNWANTED) {
        if (retcode == 0)
            dm_remove_fsys_entry(vfsp);
        return;
    }

    /* Calculate the size of the event in bytes and allocate zeroed memory
       for it.
    */

    tevp = dm_evt_create_tevp(DM_EVENT_UNMOUNT, HANDLE_SIZE(tdp1),
        (void **)&np);

    dm_add_handle_to_event(tevp, tdp1);

    /* Now copy in all the dm_namesp_event_t specific fields. */

    np->ne_handle1.vd_offset = sizeof(*np);
    np->ne_handle1.vd_length = HANDLE_SIZE(tdp1);
    bcopy(&tdp1->td_handle, (char *) np + np->ne_handle1.vd_offset,
            np->ne_handle1.vd_length);
    np->ne_mode = mode;
    np->ne_retcode = retcode;

    /* Since DM_EVENT_UNMOUNT is effectively asynchronous, queue the
       message and ignore any error return for DM_EVENT_UNMOUNT.
    */

    (void)dm_enqueue_normal_event(vfsp, tevp, flags);

    if (retcode == 0)
        dm_remove_fsys_entry(vfsp);

    dm_evt_rele_tevp(tevp, 0);
}


/* Generate the given namespace event and wait for a reply (if synchronous) or
   until the event has been queued (asynchronous).  The caller must guarantee
   that at least one vnode within the filesystem has had its reference count
   bumped so that the filesystem can't disappear while the event is
   outstanding.
*/

int
dm_send_namesp_event(
    dm_eventtype_t    event,
    bhv_desc_t    *bdp1,
    dm_right_t    vp1_right,
    bhv_desc_t    *bdp2,
    dm_right_t    vp2_right,
    char        *name1,
    char        *name2,
    mode_t        mode,
    int        retcode,
    int        flags)
{
    dm_namesp_event_t    *np;
    dm_tokevent_t    *tevp;
    dm_tokdata_t    *tdp1;        /* primary handle for event */
    dm_tokdata_t    *tdp2 = NULL;    /* additional handle for event */
    vfs_t        *sidvfsp;    /* vfs event must be registered on */
    size_t        nextoff;
    int        error;
    vnode_t        *vp1;

    vp1 = BHV_TO_VNODE(bdp1);
    sidvfsp = vp1->v_vfsp;

    switch (event) {
    case DM_EVENT_PREUNMOUNT:
        /*
         *  PREUNMOUNT - Send the file system handle in handle1,
         *  and the handle for the root dir in the second.  Otherwise
         *  it's a normal sync message; i.e. succeeds or fails
         *  depending on the app's return code.
         *    bdp1 and bdp2 are both the root dir of mounted FS
         *    vp1_right is the filesystem right.
         *    vp2_right is the root inode right.
         */

        tdp1 = dm_vfs_data(sidvfsp, vp1, vp1_right);
        tdp2 = dm_bhv_data(bdp2, vp2_right, /* reference held */ 1);

        if (flags & DM_FLAGS_UNWANTED) {
            dm_change_fsys_entry(sidvfsp, DM_STATE_UNMOUNTING);
            return(0);
        }
        break;

    case DM_EVENT_NOSPACE:
        /* vp1_right is the filesystem right. */

        tdp1 = dm_vfs_data(sidvfsp, vp1, vp1_right);
        tdp2 = dm_bhv_data(bdp2, vp2_right, /* reference held */ 1); /* additional info - not in the spec */
        break;

    default:
        /* All other events only pass in vnodes and don't require any
           special cases.
        */

        tdp1 = dm_bhv_data(bdp1, vp1_right, /* reference held */ 1);
        if (bdp2)
            tdp2 = dm_bhv_data(bdp2, vp2_right, /* reference held */ 1);
    }

    /* Calculate the size of the event in bytes and allocate zeroed memory
       for it.
    */

    tevp = dm_evt_create_tevp(event,
        HANDLE_SIZE(tdp1) + (bdp2 ? HANDLE_SIZE(tdp2) : 0) +
        (name1 ? strlen(name1) + 1 : 0) +
        (name2 ? strlen(name2) + 1 : 0), (void **)&np);

    dm_add_handle_to_event(tevp, tdp1);
    if (bdp2)
        dm_add_handle_to_event(tevp, tdp2);

    /* Now copy in all the dm_namesp_event_t specific fields. */

    np->ne_handle1.vd_offset = sizeof(*np);
    np->ne_handle1.vd_length = HANDLE_SIZE(tdp1);
    bcopy(&tdp1->td_handle, (char *) np + np->ne_handle1.vd_offset,
            np->ne_handle1.vd_length);
    nextoff = GETNEXTOFF(np->ne_handle1);
    if (bdp2) {
        np->ne_handle2.vd_offset = nextoff;
        np->ne_handle2.vd_length = HANDLE_SIZE(tdp2);
        bcopy(&tdp2->td_handle, (char *)np + np->ne_handle2.vd_offset,
                np->ne_handle2.vd_length);
        nextoff = GETNEXTOFF(np->ne_handle2);
    }
    if (name1) {
        np->ne_name1.vd_offset = nextoff;
        np->ne_name1.vd_length = strlen(name1) + 1;
        bcopy(name1, (char *)np + np->ne_name1.vd_offset,
                np->ne_name1.vd_length);
        nextoff = GETNEXTOFF(np->ne_name1);
    }
    if (name2) {
        np->ne_name2.vd_offset = nextoff;
        np->ne_name2.vd_length = strlen(name2) + 1;
        bcopy(name2, (char *)np + np->ne_name2.vd_offset,
                np->ne_name2.vd_length);
    }
    np->ne_mode = mode;
    np->ne_retcode = retcode;

    /* Queue the message and wait for the reply. */

    error = dm_enqueue_normal_event(sidvfsp, tevp, flags);

    /* If no errors occurred, we must leave with the same rights we had
       upon entry.  If errors occurred, we must leave with no rights. 
    */

    dm_evt_rele_tevp(tevp, error);

    if (!error && event == DM_EVENT_PREUNMOUNT) {
        dm_change_fsys_entry(sidvfsp, DM_STATE_UNMOUNTING);
    }

    return(error);
}


/*
 *  Send a message of type "DM_EVENT_USER".  Since no vnode is involved, we
 *  don't have to worry about rights here.
 */

int
dm_send_msg(
    dm_sessid_t    targetsid,
    dm_msgtype_t    msgtype,        /* SYNC or ASYNC */
    size_t        buflen,
    void        *bufp)
{
    dm_tokevent_t    *tevp;
    int        sync;
    void        *msgp;
    int        error;

    if (buflen > DM_MAX_MSG_DATA)
        return(E2BIG);
    if (msgtype == DM_MSGTYPE_ASYNC) {
        sync = 0;
    } else if (msgtype == DM_MSGTYPE_SYNC) {
        sync = 1;
    } else {
              return(EINVAL);
    }

    tevp = dm_evt_create_tevp(DM_EVENT_USER, buflen, (void **)&msgp);

    if (buflen && copy_from_user(msgp, bufp, buflen)) {
        dm_evt_rele_tevp(tevp, 0);
        return(EFAULT);
    }

    /* Enqueue the request and wait for the reply. */

    error = dm_enqueue_sendmsg_event(targetsid, tevp, sync);

    /* Destroy the tevp and return the reply.  (dm_pending is not
       supported here.)
    */

    dm_evt_rele_tevp(tevp, error);

    return(error);
}


/*
 *  Send a message of type "DM_EVENT_USER".  Since no vnode is involved, we
 *  don't have to worry about rights here.
 */

int
dm_create_userevent(
    dm_sessid_t    sid,
    size_t        msglen,
    void        *msgdatap,
    dm_token_t    *tokenp)        /* return token created */
{
    dm_tokevent_t    *tevp;
    dm_token_t    token;
    int        error;
    void        *msgp;

    if (msglen > DM_MAX_MSG_DATA)
              return(E2BIG);

    tevp = dm_evt_create_tevp(DM_EVENT_USER, msglen, (void **)&msgp);

    if (msglen && copy_from_user(msgp, msgdatap, msglen)) {
        dm_evt_rele_tevp(tevp, 0);
        return(EFAULT);
    }

    /* Queue the message.  If that didn't work, free the tevp structure. */

    if ((error = dm_enqueue_user_event(sid, tevp, &token)) != 0)
        dm_evt_rele_tevp(tevp, 0);

    if (!error && copy_to_user(tokenp, &token, sizeof(token)))
        error = EFAULT;

    return(error);
}


EXPORT_SYMBOL(dm_send_destroy_event);
EXPORT_SYMBOL(dm_send_mount_event);
EXPORT_SYMBOL(dm_send_namesp_event);
EXPORT_SYMBOL(dm_send_unmount_event);
EXPORT_SYMBOL(dm_send_data_event);

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0213 ]--