!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/drivers/scsi/   drwxr-xr-x
Free 318.37 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     scsi_dma.c (13.75 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 *  scsi_dma.c Copyright (C) 2000 Eric Youngdale
 *
 *  mid-level SCSI DMA bounce buffer allocator
 *
 */

#define __NO_VERSION__
#include <linux/config.h>
#include <linux/module.h>
#include <linux/blk.h>


#include "scsi.h"
#include "hosts.h"
#include "constants.h"

#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif

/*
 * PAGE_SIZE must be a multiple of the sector size (512).  True
 * for all reasonably recent architectures (even the VAX...).
 */
#define SECTOR_SIZE        512
#define SECTORS_PER_PAGE    (PAGE_SIZE/SECTOR_SIZE)

#if SECTORS_PER_PAGE <= 8
typedef unsigned char FreeSectorBitmap;
#elif SECTORS_PER_PAGE <= 32
typedef unsigned int FreeSectorBitmap;
#else
#error You lose.
#endif

/*
 * Used for access to internal allocator used for DMA safe buffers.
 */
static spinlock_t allocator_request_lock = SPIN_LOCK_UNLOCKED;

static FreeSectorBitmap *dma_malloc_freelist = NULL;
static int need_isa_bounce_buffers;
static unsigned int dma_sectors = 0;
unsigned int scsi_dma_free_sectors = 0;
unsigned int scsi_need_isa_buffer = 0;
static unsigned char **dma_malloc_pages = NULL;

/*
 * Function:    scsi_malloc
 *
 * Purpose:     Allocate memory from the DMA-safe pool.
 *
 * Arguments:   len       - amount of memory we need.
 *
 * Lock status: No locks assumed to be held.  This function is SMP-safe.
 *
 * Returns:     Pointer to memory block.
 *
 * Notes:       Prior to the new queue code, this function was not SMP-safe.
 *              This function can only allocate in units of sectors
 *              (i.e. 512 bytes).
 *
 *              We cannot use the normal system allocator becuase we need
 *              to be able to guarantee that we can process a complete disk
 *              I/O request without touching the system allocator.  Think
 *              about it - if the system were heavily swapping, and tried to
 *              write out a block of memory to disk, and the SCSI code needed
 *              to allocate more memory in order to be able to write the
 *              data to disk, you would wedge the system.
 */
void *scsi_malloc(unsigned int len)
{
    unsigned int nbits, mask;
    unsigned long flags;

    int i, j;
    if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
        return NULL;

    nbits = len >> 9;
    mask = (1 << nbits) - 1;

    spin_lock_irqsave(&allocator_request_lock, flags);

    for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++)
        for (j = 0; j <= SECTORS_PER_PAGE - nbits; j++) {
            if ((dma_malloc_freelist[i] & (mask << j)) == 0) {
                dma_malloc_freelist[i] |= (mask << j);
                scsi_dma_free_sectors -= nbits;
#ifdef DEBUG
                SCSI_LOG_MLQUEUE(3, printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9)));
                printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9));
#endif
                spin_unlock_irqrestore(&allocator_request_lock, flags);
                return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));
            }
        }
    spin_unlock_irqrestore(&allocator_request_lock, flags);
    return NULL;        /* Nope.  No more */
}

/*
 * Function:    scsi_free
 *
 * Purpose:     Free memory into the DMA-safe pool.
 *
 * Arguments:   ptr       - data block we are freeing.
 *              len       - size of block we are freeing.
 *
 * Lock status: No locks assumed to be held.  This function is SMP-safe.
 *
 * Returns:     Nothing
 *
 * Notes:       This function *must* only be used to free memory
 *              allocated from scsi_malloc().
 *
 *              Prior to the new queue code, this function was not SMP-safe.
 *              This function can only allocate in units of sectors
 *              (i.e. 512 bytes).
 */
int scsi_free(void *obj, unsigned int len)
{
    unsigned int page, sector, nbits, mask;
    unsigned long flags;

#ifdef DEBUG
    unsigned long ret = 0;

#ifdef __mips__
    __asm__ __volatile__("move\t%0,$31":"=r"(ret));
#else
    ret = __builtin_return_address(0);
#endif
    printk("scsi_free %p %d\n", obj, len);
    SCSI_LOG_MLQUEUE(3, printk("SFree: %p %d\n", obj, len));
#endif

    spin_lock_irqsave(&allocator_request_lock, flags);

    for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {
        unsigned long page_addr = (unsigned long) dma_malloc_pages[page];
        if ((unsigned long) obj >= page_addr &&
            (unsigned long) obj < page_addr + PAGE_SIZE) {
            sector = (((unsigned long) obj) - page_addr) >> 9;

            nbits = len >> 9;
            mask = (1 << nbits) - 1;

            if (sector + nbits > SECTORS_PER_PAGE)
                panic("scsi_free:Bad memory alignment");

            if ((dma_malloc_freelist[page] &
                 (mask << sector)) != (mask << sector)) {
#ifdef DEBUG
                printk("scsi_free(obj=%p, len=%d) called from %08lx\n",
                       obj, len, ret);
#endif
                panic("scsi_free:Trying to free unused memory");
            }
            scsi_dma_free_sectors += nbits;
            dma_malloc_freelist[page] &= ~(mask << sector);
            spin_unlock_irqrestore(&allocator_request_lock, flags);
            return 0;
        }
    }
    panic("scsi_free:Bad offset");
}


/*
 * Function:    scsi_resize_dma_pool
 *
 * Purpose:     Ensure that the DMA pool is sufficiently large to be
 *              able to guarantee that we can always process I/O requests
 *              without calling the system allocator.
 *
 * Arguments:   None.
 *
 * Lock status: No locks assumed to be held.  This function is SMP-safe.
 *
 * Returns:     Nothing
 *
 * Notes:       Prior to the new queue code, this function was not SMP-safe.
 *              Go through the device list and recompute the most appropriate
 *              size for the dma pool.  Then grab more memory (as required).
 */
void scsi_resize_dma_pool(void)
{
    int i, k;
    unsigned long size;
    unsigned long flags;
    struct Scsi_Host *shpnt;
    struct Scsi_Host *host = NULL;
    Scsi_Device *SDpnt;
    FreeSectorBitmap *new_dma_malloc_freelist = NULL;
    unsigned int new_dma_sectors = 0;
    unsigned int new_need_isa_buffer = 0;
    unsigned char **new_dma_malloc_pages = NULL;
    int out_of_space = 0;

    spin_lock_irqsave(&allocator_request_lock, flags);

    if (!scsi_hostlist) {
        /*
         * Free up the DMA pool.
         */
        if (scsi_dma_free_sectors != dma_sectors)
            panic("SCSI DMA pool memory leak %d %d\n", scsi_dma_free_sectors, dma_sectors);

        for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++)
            free_pages((unsigned long) dma_malloc_pages[i], 0);
        if (dma_malloc_pages)
            kfree((char *) dma_malloc_pages);
        dma_malloc_pages = NULL;
        if (dma_malloc_freelist)
            kfree((char *) dma_malloc_freelist);
        dma_malloc_freelist = NULL;
        dma_sectors = 0;
        scsi_dma_free_sectors = 0;
        spin_unlock_irqrestore(&allocator_request_lock, flags);
        return;
    }
    /* Next, check to see if we need to extend the DMA buffer pool */

    new_dma_sectors = 2 * SECTORS_PER_PAGE;        /* Base value we use */

    if (__pa(high_memory) - 1 > ISA_DMA_THRESHOLD)
        need_isa_bounce_buffers = 1;
    else
        need_isa_bounce_buffers = 0;

    if (scsi_devicelist)
        for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next)
            new_dma_sectors += SECTORS_PER_PAGE;    /* Increment for each host */

    for (host = scsi_hostlist; host; host = host->next) {
        for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
            /*
             * sd and sr drivers allocate scatterlists.
             * sr drivers may allocate for each command 1x2048 or 2x1024 extra
             * buffers for 2k sector size and 1k fs.
             * sg driver allocates buffers < 4k.
             * st driver does not need buffers from the dma pool.
             * estimate 4k buffer/command for devices of unknown type (should panic).
             */
            if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM ||
                SDpnt->type == TYPE_DISK || SDpnt->type == TYPE_MOD) {
                int nents = host->sg_tablesize;
#ifdef DMA_CHUNK_SIZE
                /* If the architecture does DMA sg merging, make sure
                   we count with at least 64 entries even for HBAs
                   which handle very few sg entries.  */
                if (nents < 64) nents = 64;
#endif
                new_dma_sectors += ((nents *
                sizeof(struct scatterlist) + 511) >> 9) *
                 SDpnt->queue_depth;
                if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM)
                    new_dma_sectors += (2048 >> 9) * SDpnt->queue_depth;
            } else if (SDpnt->type == TYPE_SCANNER ||
                   SDpnt->type == TYPE_PRINTER ||
                   SDpnt->type == TYPE_PROCESSOR ||
                   SDpnt->type == TYPE_COMM ||
                   SDpnt->type == TYPE_MEDIUM_CHANGER ||
                   SDpnt->type == TYPE_ENCLOSURE) {
                new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
            } else {
                if (SDpnt->type != TYPE_TAPE) {
                    printk("resize_dma_pool: unknown device type %d\n", SDpnt->type);
                    new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
                }
            }

            if (host->unchecked_isa_dma &&
                need_isa_bounce_buffers &&
                SDpnt->type != TYPE_TAPE) {
                new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
                    SDpnt->queue_depth;
                new_need_isa_buffer++;
            }
        }
    }

#ifdef DEBUG_INIT
    printk("resize_dma_pool: needed dma sectors = %d\n", new_dma_sectors);
#endif

    /* limit DMA memory to 32MB: */
    new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;

    /*
     * We never shrink the buffers - this leads to
     * race conditions that I would rather not even think
     * about right now.
     */
#if 0                /* Why do this? No gain and risks out_of_space */
    if (new_dma_sectors < dma_sectors)
        new_dma_sectors = dma_sectors;
#endif
    if (new_dma_sectors <= dma_sectors) {
        spin_unlock_irqrestore(&allocator_request_lock, flags);
        return;        /* best to quit while we are in front */
        }

    for (k = 0; k < 20; ++k) {    /* just in case */
        out_of_space = 0;
        size = (new_dma_sectors / SECTORS_PER_PAGE) *
            sizeof(FreeSectorBitmap);
        new_dma_malloc_freelist = (FreeSectorBitmap *)
            kmalloc(size, GFP_ATOMIC);
        if (new_dma_malloc_freelist) {
                        memset(new_dma_malloc_freelist, 0, size);
            size = (new_dma_sectors / SECTORS_PER_PAGE) *
                sizeof(*new_dma_malloc_pages);
            new_dma_malloc_pages = (unsigned char **)
                kmalloc(size, GFP_ATOMIC);
            if (!new_dma_malloc_pages) {
                size = (new_dma_sectors / SECTORS_PER_PAGE) *
                    sizeof(FreeSectorBitmap);
                kfree((char *) new_dma_malloc_freelist);
                out_of_space = 1;
            } else {
                                memset(new_dma_malloc_pages, 0, size);
                        }
        } else
            out_of_space = 1;

        if ((!out_of_space) && (new_dma_sectors > dma_sectors)) {
            for (i = dma_sectors / SECTORS_PER_PAGE;
               i < new_dma_sectors / SECTORS_PER_PAGE; i++) {
                new_dma_malloc_pages[i] = (unsigned char *)
                    __get_free_pages(GFP_ATOMIC | GFP_DMA, 0);
                if (!new_dma_malloc_pages[i])
                    break;
            }
            if (i != new_dma_sectors / SECTORS_PER_PAGE) {    /* clean up */
                int k = i;

                out_of_space = 1;
                for (i = 0; i < k; ++i)
                    free_pages((unsigned long) new_dma_malloc_pages[i], 0);
            }
        }
        if (out_of_space) {    /* try scaling down new_dma_sectors request */
            printk("scsi::resize_dma_pool: WARNING, dma_sectors=%u, "
                   "wanted=%u, scaling\n", dma_sectors, new_dma_sectors);
            if (new_dma_sectors < (8 * SECTORS_PER_PAGE))
                break;    /* pretty well hopeless ... */
            new_dma_sectors = (new_dma_sectors * 3) / 4;
            new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
            if (new_dma_sectors <= dma_sectors)
                break;    /* stick with what we have got */
        } else
            break;    /* found space ... */
    }            /* end of for loop */
    if (out_of_space) {
        spin_unlock_irqrestore(&allocator_request_lock, flags);
        scsi_need_isa_buffer = new_need_isa_buffer;    /* some useful info */
        printk("      WARNING, not enough memory, pool not expanded\n");
        return;
    }
    /* When we dick with the actual DMA list, we need to
     * protect things
     */
    if (dma_malloc_freelist) {
        size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap);
        memcpy(new_dma_malloc_freelist, dma_malloc_freelist, size);
        kfree((char *) dma_malloc_freelist);
    }
    dma_malloc_freelist = new_dma_malloc_freelist;

    if (dma_malloc_pages) {
        size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages);
        memcpy(new_dma_malloc_pages, dma_malloc_pages, size);
        kfree((char *) dma_malloc_pages);
    }
    scsi_dma_free_sectors += new_dma_sectors - dma_sectors;
    dma_malloc_pages = new_dma_malloc_pages;
    dma_sectors = new_dma_sectors;
    scsi_need_isa_buffer = new_need_isa_buffer;

    spin_unlock_irqrestore(&allocator_request_lock, flags);

#ifdef DEBUG_INIT
    printk("resize_dma_pool: dma free sectors   = %d\n", scsi_dma_free_sectors);
    printk("resize_dma_pool: dma sectors        = %d\n", dma_sectors);
    printk("resize_dma_pool: need isa buffers   = %d\n", scsi_need_isa_buffer);
#endif
}

/*
 * Function:    scsi_init_minimal_dma_pool
 *
 * Purpose:     Allocate a minimal (1-page) DMA pool.
 *
 * Arguments:   None.
 *
 * Lock status: No locks assumed to be held.  This function is SMP-safe.
 *
 * Returns:     Nothing
 *
 * Notes:       
 */
int scsi_init_minimal_dma_pool(void)
{
    unsigned long size;
    unsigned long flags;
    int has_space = 0;

    spin_lock_irqsave(&allocator_request_lock, flags);

    dma_sectors = PAGE_SIZE / SECTOR_SIZE;
    scsi_dma_free_sectors = dma_sectors;
    /*
     * Set up a minimal DMA buffer list - this will be used during scan_scsis
     * in some cases.
     */

    /* One bit per sector to indicate free/busy */
    size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap);
    dma_malloc_freelist = (FreeSectorBitmap *)
        kmalloc(size, GFP_ATOMIC);
    if (dma_malloc_freelist) {
                memset(dma_malloc_freelist, 0, size);
        /* One pointer per page for the page list */
        dma_malloc_pages = (unsigned char **) kmalloc(
                        (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages),
                                 GFP_ATOMIC);
        if (dma_malloc_pages) {
                        memset(dma_malloc_pages, 0, size);
            dma_malloc_pages[0] = (unsigned char *)
                __get_free_pages(GFP_ATOMIC | GFP_DMA, 0);
            if (dma_malloc_pages[0])
                has_space = 1;
        }
    }
    if (!has_space) {
        if (dma_malloc_freelist) {
            kfree((char *) dma_malloc_freelist);
            if (dma_malloc_pages)
                kfree((char *) dma_malloc_pages);
        }
        spin_unlock_irqrestore(&allocator_request_lock, flags);
        printk("scsi::init_module: failed, out of memory\n");
        return 1;
    }

    spin_unlock_irqrestore(&allocator_request_lock, flags);
    return 0;
}

:: 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.0117 ]--