3

In following functions, taken from LDD:

ssize_t read(struct file *filp, char __user *buff, size_t count, loff_t *offp);
ssize_t write(struct file *filp, const char __user *buff, size_t count, loff_t *offp);

Why there is the need of loff_t *offp? Can't I use directly filp to update f_pos?

Moreover in page 54 the author says:

Read and write should update a position using the pointer they receive as the last argument instead of acting on filp->f_pos directly. The one exception to this...

OK, so it's better to use the offp pointer, but why?

Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
Diego A
  • 51
  • 1
  • 3

2 Answers2

2

filp->f_pos is current pointer position in file, whereas offp is where user does access to file. You advance file pointer on successful read/write operation, if you failed you should not change file pointer. Kernel does it itself, if you successfully did read/write it will change filp->f_pos to offp. Citing LDD3:

Whatever the amount of data the methods transfer, they should generally update the file position at *offp to represent the current file position after successful completion of the system call. The kernel then propagates the file position change back into the file structure when appropriate.

Alexander Dzyoba
  • 4,009
  • 1
  • 24
  • 29
  • I did not think about this, and above all, that the offp pointer is the medium to instruct the device about “where I want to read/write”. Whithout it (so with only 3 parameters), the system call container should use an intricate gear to save old f_pos, use llseek, call read/write, and then decide to accept the modified filp’s f_pos or restore the saved one. Am I right? Thanks. – Diego A May 10 '14 at 10:58
  • Yes, you're right. Also random reading would be really awkward. – Alexander Dzyoba May 10 '14 at 11:02
0

One reason could be to support the pread, pwrite, preadv, pwritev syscalls, which take an offset as one of the arguments, and are specified to NOT update the file position. It seems cleaner to have the lower layer code implement something close to the p* functions, and then have wrappers that use filp->f_pos and update the position for the plain read/write/readv/writev syscalls.

janneb
  • 36,249
  • 2
  • 81
  • 97
  • Therefore, as far as I have understood following your remark, since the write (or read) container of file_operations is just one (but the system calls are not), kernel needs a flexible way to translate the various write/read and various pwrite/pread in one single function call that therefore must have the flexibility to permit heterogeneity. Am I right? – Diego A May 10 '14 at 10:43
  • Following the same reasonment, It will be up to the container function that implements the single system call, to decide whether update or not the f_pos. Moreover, fore a simple write system call, to update the file pointer automatically, a simple call of the write function like this writefunc(&myFilp, &myBuf, xxx, &(myFilp->f_pos)) can be enough, since when writefunc updates the target of offp pointer, really updates the filp->f_pos directly. Am I following a correct reasonment? Thanks. – Diego A May 10 '14 at 10:44