Seeking a Device
The difficult part of the chapter is over; now we’ll quickly detail the llseek method, which is useful and easy to implement.
The llseek Implementation
The llseek method implements the
lseek and llseek system
calls. We have already stated that if the llseek
method is missing from the device’s operations, the default
implementation in the kernel performs seeks from the beginning of the
file and from the current position by modifying
filp->f_pos, the current reading/writing
position within the file. Please note that for the
lseek system call to work correctly, the
read and write methods must
cooperate by updating the offset item they receive as argument (the
argument is usually a pointer to filp->f_pos).
You may need to provide your own llseek method if the seek operation corresponds to a physical operation on the device or if seeking from end-of-file, which is not implemented by the default method, makes sense. A simple example can be seen in the scull driver:
loff_t scull_llseek(struct file *filp, loff_t off, int whence)
{
Scull_Dev *dev = filp->private_data;
loff_t newpos;
switch(whence) {
case 0: /* SEEK_SET */
newpos = off;
break;
case 1: /* SEEK_CUR */
newpos = filp->f_pos + off;
break;
case 2: /* SEEK_END */
newpos = dev->size + off;
break;
default: /* can't happen */
return -EINVAL;
}
if (newpos<0) return -EINVAL;
filp->f_pos = newpos;
return newpos;
}The only device-specific operation here is retrieving the file length from the device. In scull
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access