📄 locking
字号:
existing instances of this method ->sync_page() itself doesn't lookwell-defined... ->writepages() is used for periodic writeback and for syscall-initiatedsync operations. The address_space should start I/O against at least*nr_to_write pages. *nr_to_write must be decremented for each page which iswritten. The address_space implementation may write more (or less) pagesthan *nr_to_write asks for, but it should try to be reasonably close. Ifnr_to_write is NULL, all dirty pages must be written.writepages should _only_ write pages which are present onmapping->io_pages. ->set_page_dirty() is called from various places in the kernelwhen the target page is marked as needing writeback. It may be calledunder spinlock (it cannot block) and is sometimes called with the pagenot locked. ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by somefilesystems and by the swapper. The latter will eventually go away. Allinstances do not actually need the BKL. Please, keep it that way and don'tbreed new callers. ->invalidatepage() is called when the filesystem must attempt to dropsome or all of the buffers from the page when it is being truncated. Itreturns zero on success. If ->invalidatepage is zero, the kernel usesblock_invalidatepage() instead. ->releasepage() is called when the kernel is about to try to drop thebuffers from the page in preparation for freeing it. It returns zero toindicate that the buffers are (or may be) freeable. If ->releasepage is zero,the kernel assumes that the fs has no private interest in the buffers. Note: currently almost all instances of address_space methods areusing BKL for internal serialization and that's one of the worst sourcesof contention. Normally they are calling library functions (in fs/buffer.c)and pass foo_get_block() as a callback (on local block-based filesystems,indeed). BKL is not needed for library stuff and is usually taken byfoo_get_block(). It's an overkill, since block bitmaps can be protected byinternal fs locking and real critical areas are much smaller than the areasfilesystems protect now.----------------------- file_lock_operations ------------------------------prototypes: void (*fl_insert)(struct file_lock *); /* lock insertion callback */ void (*fl_remove)(struct file_lock *); /* lock removal callback */ void (*fl_copy_lock)(struct file_lock *, struct file_lock *); void (*fl_release_private)(struct file_lock *);locking rules: BKL may blockfl_insert: yes nofl_remove: yes nofl_copy_lock: yes nofl_release_private: yes yes----------------------- lock_manager_operations ---------------------------prototypes: int (*fl_compare_owner)(struct file_lock *, struct file_lock *); void (*fl_notify)(struct file_lock *); /* unblock callback */locking rules: BKL may blockfl_compare_owner: yes nofl_notify: yes no Currently only NLM provides instances of this class. None of thethem block. If you have out-of-tree instances - please, show up. Lockingin that area will change.--------------------------- buffer_head -----------------------------------prototypes: void (*b_end_io)(struct buffer_head *bh, int uptodate);locking rules: called from interrupts. In other words, extreme care is needed here.bh is locked, but that's all warranties we have here. Currently only RAID1,highmem and fs/buffer.c are providing these. Block devices call this methodupon the IO completion.--------------------------- block_device_operations -----------------------prototypes: int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); int (*media_changed) (struct gendisk *); int (*revalidate_disk) (struct gendisk *);locking rules: BKL bd_semopen: yes yesrelease: yes yesioctl: yes nomedia_changed: no norevalidate_disk: no noThe last two are called only from check_disk_change().--------------------------- file_operations -------------------------------prototypes: loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void __user *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*dir_notify)(struct file *, unsigned long);};locking rules: All except ->poll() may block. BKLllseek: no (see below)read: noaio_read: nowrite: noaio_write: noreaddir: nopoll: noioctl: yes (see below)mmap: noopen: maybe (see below)flush: norelease: nofsync: no (see below)aio_fsync: nofasync: yes (see below)lock: yesreadv: nowritev: nosendfile: nosendpage: noget_unmapped_area: nocheck_flags: nodir_notify: no->llseek() locking has moved from llseek to the individual llseekimplementations. If your fs is not using generic_file_llseek, youneed to acquire and release the appropriate locks in your ->llseek().For many filesystems, it is probably safe to acquire the inodesemaphore. Note some filesystems (i.e. remote ones) provide noprotection for i_size so you will need to use the BKL.->open() locking is in-transit: big lock partially moved into the methods.The only exception is ->open() in the instances of file_operations that neverend up in ->i_fop/->proc_fops, i.e. ones that belong to character devices(chrdev_open() takes lock before replacing ->f_op and calling the secondarymethod. As soon as we fix the handling of module reference counters allinstances of ->open() will be called without the BKL.Note: ext2_release() was *the* source of contention on fs-intensiveloads and dropping BKL on ->release() helps to get rid of that (we stillgrab BKL for cases when we close a file that had been opened r/w, but thatcan and should be done using the internal locking with smaller critical areas).Current worst offender is ext2_get_block()...->fasync() is a mess. This area needs a big cleanup and that will probablyaffect locking.->readdir() and ->ioctl() on directories must be changed. Ideally we wouldmove ->readdir() to inode_operations and use a separate method for directory->ioctl() or kill the latter completely. One of the problems is that foranything that resembles union-mount we won't have a struct file for allcomponents. And there are other reasons why the current interface is a mess...->read on directories probably must go away - we should just enforce -EISDIRin sys_read() and friends.->fsync() has i_sem on inode.--------------------------- dquot_operations -------------------------------prototypes: void (*initialize) (struct inode *, short); void (*drop) (struct inode *); int (*alloc_block) (const struct inode *, unsigned long, char); int (*alloc_inode) (const struct inode *, unsigned long); void (*free_block) (const struct inode *, unsigned long); void (*free_inode) (const struct inode *, unsigned long); int (*transfer) (struct dentry *, struct iattr *);locking rules: BKLinitialize: nodrop: noalloc_block: yesalloc_inode: yesfree_block: yesfree_inode: yestransfer: no--------------------------- vm_operations_struct -----------------------------prototypes: void (*open)(struct vm_area_struct*); void (*close)(struct vm_area_struct*); struct page *(*nopage)(struct vm_area_struct*, unsigned long, int *);locking rules: BKL mmap_semopen: no yesclose: no yesnopage: no yes================================================================================ Dubious stuff(if you break something or notice that it is broken and do not fix it yourself- at least put it here)ipc/shm.c::shm_delete() - may need BKL.->read() and ->write() in many drivers are (probably) missing BKL.drivers/sgi/char/graphics.c::sgi_graphics_nopage() - may need BKL.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -