The following file operations are defined in three places by Ext3. In file.c:
struct file_operations ext3_file_operations = {
llseek: generic_file_llseek, /* BKL held */
read: generic_file_read, /* BKL not held. Don't need */
write: ext3_file_write, /* BKL not held. Don't need */
ioctl: ext3_ioctl, /* BKL held */
mmap: generic_file_mmap,
open: ext3_open_file, /* BKL not held. Don't need */
release: ext3_release_file, /* BKL not held. Don't need */
fsync: ext3_sync_file, /* BKL held */
};
And in dir.c:
struct file_operations ext3_dir_operations = {
read: generic_read_dir,
readdir: ext3_readdir, /* BKL held */
ioctl: ext3_ioctl, /* BKL held */
fsync: ext3_sync_file, /* BKL held */
};
And finally in bad_inode.c:
static struct file_operations bad_file_ops =
{
llseek: EIO_ERROR,
read: EIO_ERROR,
write: EIO_ERROR,
readdir: EIO_ERROR,
poll: EIO_ERROR,
ioctl: EIO_ERROR,
mmap: EIO_ERROR,
open: EIO_ERROR,
flush: EIO_ERROR,
release: EIO_ERROR,
fsync: EIO_ERROR,
fasync: EIO_ERROR,
lock: EIO_ERROR,
};
The following are the elements of the file_operations structure:
loff_t (*llseek) (struct file *file, loff_t offset, int origin);
The default llseek behavior is to seek to position offset
from file position origin (0 = current, 1 = beginning,
2 = end) in the file file and return the value of
the absolute position reached.
ssize_t (*read) (struct file *filp, char *buf, size_t count, loff_t *ppos);
The default read behavior uses the i_op->readpage
function for the actual low-level read.
ssize_t (*write) (struct file *filp, const char *buf, size_t count, loff_t *ppos);
The default write behavior uses the address operations
prepare_write and commit_write to do
its job.
int (*readdir) (struct file *filp, void *dirent, filldir_t filldir);
This function reads the next directory entry from the
directory whose file pointer is filp. It stores a
directory entry structure corresponding to the directory into
dirent, using the file position in filp
to keep track of how far it has gotten before this call.
The function filldir is called to fill the
dirent in a situation specific way.
typedef int (*filldir_t)(void *buf, const char *name, int namelen, loff_t offset, ino_t ino, unsigned d_type);
The filldir function is called with arguments
dirent, the entry name, the length of the entry name, the
file position of the start of this entry, the inode, and
the directory type.
unsigned int (*poll) (struct file *, struct poll_table_struct *);The poll function is called when a process wants to sleep until there is activity on a file.
int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
This performs a file system specific action, typically changing
some properties of the file system. The command values
and associated argument values are defined by the
file system. Some EXT3 ioctl commands include
GET_FLAGS, SET_FLAGS,
GET_VERSION, SET_VERSION,
WAIT_FOR_READONLY.
int (*mmap) (struct file *filp, struct vm_area_struct *vma);
This function is called to map a particular region of the file
to a specific portion of the address space. The
vma argument describes the mapping
int (*open) (struct inode *inode, struct file *filp);
This function is called by dentry_open when
a file is opened. Most file systems do not define this call.
Some, such as Coda, may attempt to cache open file information.
int (*flush) (struct file *filp);This is called whenever a file is closed (even if it's not the last close). In NFS this call flushes all dirty pages to the server. You may recall my mentioning that when writes are performed on an NFS-mounted file, the file's pages are cached until the file is closed, at which time, all dirty page updates are sent back to the server.
int (*release) (struct inode *inode, struct file *filp);
The release function is called after the last
close on a file is performed, that is, the one that brings
the f_count down to 0. Its return value is ignored.
In Ext3, this function discards any blocks that were preallocated for subsequent write commands.
int (*fsync) (struct file *filp, struct dentry *dentry, int datasync);
This writes all data buffers associated with the file to the
disk. If the datasync argument is true, then
it also completes all pending I/O operations.
(Ext3 always behaves as if datasync is true.)
int (*fasync) (int fd, struct file * filp, int on);This is called whenever asynchronous mode is enabled for a file. It's not usually defined by a file system implementation.
int (*lock) (struct file *, int, struct file_lock *);This function is called before posix_file_lock to do any file-system-specific work necessary to lock a region of the file (as requested by fcntl(2)).
ssize_t (*readv) (struct file *filp, const struct iovec *vector, unsigned long count, loff_t *fpos);
If a file-system-specific readv function is available,
it is supplied here. Otherwise, a generic readv
(which fills a number of iovec buffers upon read) is
used.
ssize_t (*writev) (struct file *filp, const struct iovec *vector, unsigned long count, loff_t *fpos);
This is the write version of readv.
A generic version of this is used if no file-system specfic
version is provided.
ssize_t (*sendpage) (struct file *filp, struct page *page, int offset, size_t size, loff_t *fpos, int count);I can only find references to sendpage in socket manipulation code. There are no disk file system bindings.
unsigned long (*get_unmapped_area)(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags);
Used for memory mapping (called in do_mmap_pgoff)
to obtain a mappable address.