From: Jan Kara Attached patch updates documentation in Documentation/filesystems/Locking to match the current state of quota code. Also a few comments in quota code are updated. Signed-off-by: Jan Kara Signed-off-by: Andrew Morton --- 25-akpm/Documentation/filesystems/Locking | 62 ++++++++++++++++++++++-------- 25-akpm/fs/dquot.c | 5 +- 2 files changed, 50 insertions(+), 17 deletions(-) diff -puN Documentation/filesystems/Locking~update-documentation-filesystems-locking Documentation/filesystems/Locking --- 25/Documentation/filesystems/Locking~update-documentation-filesystems-locking Wed Feb 9 14:33:41 2005 +++ 25-akpm/Documentation/filesystems/Locking Wed Feb 9 14:33:41 2005 @@ -104,6 +104,8 @@ prototypes: void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); int (*show_options)(struct seq_file *, struct vfsmount *); + ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); + ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); locking rules: All may block. @@ -126,10 +128,17 @@ remount_fs: no yes maybe (see below) clear_inode: no umount_begin: yes no no show_options: no (vfsmount->sem) +quota_read: no no no (see below) +quota_write: no no no (see below) ->read_inode() is not a method - it's a callback used in iget(). ->remount_fs() will have the s_umount lock if it's already mounted. When called from get_sb_single, it does NOT have the s_umount lock. +->quota_read() and ->quota_write() functions are both guaranteed to +be the only ones operating on the quota file by the quota code (via +dqio_sem) (unless an admin really wants to screw up something and +writes to quota files with quotas on). For other details about locking +see also dquot_operations section. --------------------------- file_system_type --------------------------- prototypes: @@ -442,23 +451,46 @@ in sys_read() and friends. --------------------------- dquot_operations ------------------------------- prototypes: - void (*initialize) (struct inode *, short); - void (*drop) (struct inode *); - int (*alloc_block) (const struct inode *, unsigned long, char); + int (*initialize) (struct inode *, int); + int (*drop) (struct inode *); + int (*alloc_space) (struct inode *, qsize_t, int); 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 *); + int (*free_space) (struct inode *, qsize_t); + int (*free_inode) (const struct inode *, unsigned long); + int (*transfer) (struct inode *, struct iattr *); + int (*write_dquot) (struct dquot *); + int (*acquire_dquot) (struct dquot *); + int (*release_dquot) (struct dquot *); + int (*mark_dirty) (struct dquot *); + int (*write_info) (struct super_block *, int); + +These operations are intended to be more or less wrapping functions that ensure +a proper locking wrt the filesystem and call the generic quota operations. + +What filesystem should expect from the generic quota functions: + + FS recursion Held locks when called +initialize: yes maybe dqonoff_sem +drop: yes - +alloc_space: ->mark_dirty() - +alloc_inode: ->mark_dirty() - +free_space: ->mark_dirty() - +free_inode: ->mark_dirty() - +transfer: yes - +write_dquot: yes dqonoff_sem or dqptr_sem +acquire_dquot: yes dqonoff_sem or dqptr_sem +release_dquot: yes dqonoff_sem or dqptr_sem +mark_dirty: no - +write_info: yes dqonoff_sem + +FS recursion means calling ->quota_read() and ->quota_write() from superblock +operations. + +->alloc_space(), ->alloc_inode(), ->free_space(), ->free_inode() are called +only directly by the filesystem and do not call any fs functions only +the ->mark_dirty() operation. -locking rules: - BKL -initialize: no -drop: no -alloc_block: yes -alloc_inode: yes -free_block: yes -free_inode: yes -transfer: no +More details about quota locking can be found in fs/dquot.c. --------------------------- vm_operations_struct ----------------------------- prototypes: diff -puN fs/dquot.c~update-documentation-filesystems-locking fs/dquot.c --- 25/fs/dquot.c~update-documentation-filesystems-locking Wed Feb 9 14:33:41 2005 +++ 25-akpm/fs/dquot.c Wed Feb 9 14:33:41 2005 @@ -1092,7 +1092,7 @@ warn_put_all: } /* - * This is a non-blocking operation. + * This operation can block, but only after everything is updated */ int dquot_free_space(struct inode *inode, qsize_t number) { @@ -1128,7 +1128,7 @@ out_sub: } /* - * This is a non-blocking operation. + * This operation can block, but only after everything is updated */ int dquot_free_inode(const struct inode *inode, unsigned long number) { @@ -1163,6 +1163,7 @@ int dquot_free_inode(const struct inode * Transfer the number of inode and blocks from one diskquota to an other. * * This operation can block, but only after everything is updated + * A transaction must be started when entering this function. */ int dquot_transfer(struct inode *inode, struct iattr *iattr) { _