 nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; 
st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, 	          unsigned long uaddr, size_t count, int rw,	          unsigned long max_pfn){	int res, i, j;	unsigned int nr_pages;	struct page **pages;	nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;	/* User attempted Overflow! */	if ((uaddr + count) < uaddr)		return -EINVAL;	/* Too big */        if (nr_pages > max_pages)		return -ENOMEM;	/* Hmm? */	if (count == 0)		return 0;	if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_ATOMIC)) == NULL)		return -ENOMEM;        /* Try to fault in all of the necessary pages */	down_read(&current->mm->mmap_sem);        /* rw==READ means read from drive, write into memory area */	res = get_user_pages(		current,		current->mm,		uaddr,		nr_pages,		rw == READ,		0, /* don't force */		pages,		NULL);	up_read(&current->mm->mmap_sem);	/* Errors and no page mapped should return here */	if (res < nr_pages)		goto out_unmap;        for (i=0; i < nr_pages; i++) {                /* FIXME: flush superflous for rw==READ,                 * probably wrong function for rw==WRITE                 */		flush_dcache_page(pages[i]);		if (page_to_pfn(pages[i]) > max_pfn)			goto out_unlock;		/* ?? Is locking needed? I don't think so */		/* if (TestSetPageLocked(pages[i]))		   goto out_unlock; */        }	/* Populate the scatter/gather list */	sgl[0].page = pages[0]; 	sgl[0].offset = uaddr & ~PAGE_MASK;	if (nr_pages > 1) {		sgl[0].length = PAGE_SIZE - sgl[0].offset;		count -= sgl[0].length;		for (i=1; i < nr_pages ; i++) {			sgl[i].offset = 0;			sgl[i].page = pages[i]; 			sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE;			count -= PAGE_SIZE;		}	}	else {		sgl[0].length = count;	}	kfree(pages);	return nr_pages; out_unlock:	/* for (j=0; j < i; j++)	   unlock_page(pages[j]); */	res = 0; out_unmap:	if (res > 0)		for (j=0; j < res; j++)			page_cache_release(pages[j]);	kfree(pages);	return res;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/deb92b7ee98e8e580cafaa63bd1edbe6646877bc/sg.c/clean/drivers/scsi/sg.c