drivers/s390/char/hmcdrv_cache.c

Source file repositories/reference/linux-study-clean/drivers/s390/char/hmcdrv_cache.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/char/hmcdrv_cache.c
Extension
.c
Size
6672 bytes
Lines
253
Domain
Driver Families
Bucket
drivers/s390
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct hmcdrv_cache_entry {
	enum hmcdrv_ftp_cmdid id;
	char fname[HMCDRV_FTP_FIDENT_MAX];
	size_t fsize;
	loff_t ofs;
	unsigned long timeout;
	void *content;
	size_t len;
};

static int hmcdrv_cache_order; /* cache allocated page order */

static struct hmcdrv_cache_entry hmcdrv_cache_file = {
	.fsize = SIZE_MAX,
	.ofs = -1,
	.len = 0,
	.fname = {'\0'}
};

/**
 * hmcdrv_cache_get() - looks for file data/content in read cache
 * @ftp: pointer to FTP command specification
 *
 * Return: number of bytes read from cache or a negative number if nothing
 * in content cache (for the file/cmd specified in @ftp)
 */
static ssize_t hmcdrv_cache_get(const struct hmcdrv_ftp_cmdspec *ftp)
{
	loff_t pos; /* position in cache (signed) */
	ssize_t len;

	if ((ftp->id != hmcdrv_cache_file.id) ||
	    strcmp(hmcdrv_cache_file.fname, ftp->fname))
		return -1;

	if (ftp->ofs >= hmcdrv_cache_file.fsize) /* EOF ? */
		return 0;

	if ((hmcdrv_cache_file.ofs < 0) || /* has content? */
	    time_after(jiffies, hmcdrv_cache_file.timeout))
		return -1;

	/* there seems to be cached content - calculate the maximum number
	 * of bytes that can be returned (regarding file size and offset)
	 */
	len = hmcdrv_cache_file.fsize - ftp->ofs;

	if (len > ftp->len)
		len = ftp->len;

	/* check if the requested chunk falls into our cache (which starts
	 * at offset 'hmcdrv_cache_file.ofs' in the file of interest)
	 */
	pos = ftp->ofs - hmcdrv_cache_file.ofs;

	if ((pos >= 0) &&
	    ((pos + len) <= hmcdrv_cache_file.len)) {

		memcpy(ftp->buf,
		       hmcdrv_cache_file.content + pos,
		       len);
		pr_debug("using cached content of '%s', returning %zd/%zd bytes\n",
			 hmcdrv_cache_file.fname, len,
			 hmcdrv_cache_file.fsize);

		return len;
	}

	return -1;
}

/**
 * hmcdrv_cache_do() - do a HMC drive CD/DVD transfer with cache update
 * @ftp: pointer to FTP command specification
 * @func: FTP transfer function to be used
 *
 * Return: number of bytes read/written or a (negative) error code
 */
static ssize_t hmcdrv_cache_do(const struct hmcdrv_ftp_cmdspec *ftp,
			       hmcdrv_cache_ftpfunc func)
{
	ssize_t len;

	/* only cache content if the read/dir cache really exists
	 * (hmcdrv_cache_file.len > 0), is large enough to handle the
	 * request (hmcdrv_cache_file.len >= ftp->len) and there is a need
	 * to do so (ftp->len > 0)
	 */
	if ((ftp->len > 0) && (hmcdrv_cache_file.len >= ftp->len)) {

Annotation

Implementation Notes