it only makes control flow in __fput() and friends more convoluted.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
CONFIG_DEBUG_HIGHMEM=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_VM=y
-CONFIG_DEBUG_WRITECOUNT=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_SG=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_LOCKDEP=y
CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_WRITECOUNT=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_LIST=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60
CONFIG_DEBUG_LOCKDEP=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
-CONFIG_DEBUG_WRITECOUNT=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_SG=y
CONFIG_DEBUG_NOTIFIERS=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_VM=y
-CONFIG_DEBUG_WRITECOUNT=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_SG=y
CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
CONFIG_DEBUG_NOMMU_REGIONS=y
-# CONFIG_DEBUG_WRITECOUNT is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
static inline void file_free(struct file *f)
{
percpu_counter_dec(&nr_files);
- file_check_state(f);
call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
}
* that we can do debugging checks at __fput()
*/
if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) {
- file_take_write(file);
WARN_ON(mnt_clone_write(path->mnt));
}
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
return;
put_write_access(inode);
- if (file_check_writeable(file) != 0)
- return;
__mnt_drop_write(mnt);
- file_release_write(file);
}
/* the real guts of fput() - releasing the last reference to file
error = __get_file_write_access(inode, f->f_path.mnt);
if (error)
goto cleanup_file;
- file_take_write(f);
}
f->f_mapping = inode->i_mapping;
fops_put(f->f_op);
if (f->f_mode & FMODE_WRITE) {
if (!special_file(inode->i_mode)) {
- /*
- * We don't consider this a real
- * mnt_want/drop_write() pair
- * because it all happenend right
- * here, so just reset the state.
- */
put_write_access(inode);
- file_reset_write(f);
__mnt_drop_write(f->f_path.mnt);
}
}
index < ra->start + ra->size);
}
-#define FILE_MNT_WRITE_TAKEN 1
-#define FILE_MNT_WRITE_RELEASED 2
-
struct file {
union {
struct llist_node fu_llist;
struct list_head f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
struct address_space *f_mapping;
-#ifdef CONFIG_DEBUG_WRITECOUNT
- unsigned long f_mnt_write_state;
-#endif
} __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
struct file_handle {
#define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1)
#define file_count(x) atomic_long_read(&(x)->f_count)
-#ifdef CONFIG_DEBUG_WRITECOUNT
-static inline void file_take_write(struct file *f)
-{
- WARN_ON(f->f_mnt_write_state != 0);
- f->f_mnt_write_state = FILE_MNT_WRITE_TAKEN;
-}
-static inline void file_release_write(struct file *f)
-{
- f->f_mnt_write_state |= FILE_MNT_WRITE_RELEASED;
-}
-static inline void file_reset_write(struct file *f)
-{
- f->f_mnt_write_state = 0;
-}
-static inline void file_check_state(struct file *f)
-{
- /*
- * At this point, either both or neither of these bits
- * should be set.
- */
- WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN);
- WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_RELEASED);
-}
-static inline int file_check_writeable(struct file *f)
-{
- if (f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN)
- return 0;
- printk(KERN_WARNING "writeable file with no "
- "mnt_want_write()\n");
- WARN_ON(1);
- return -EINVAL;
-}
-#else /* !CONFIG_DEBUG_WRITECOUNT */
-static inline void file_take_write(struct file *filp) {}
-static inline void file_release_write(struct file *filp) {}
-static inline void file_reset_write(struct file *filp) {}
-static inline void file_check_state(struct file *filp) {}
-static inline int file_check_writeable(struct file *filp)
-{
- return 0;
-}
-#endif /* CONFIG_DEBUG_WRITECOUNT */
-
#define MAX_NON_LFS ((1UL<<31) - 1)
/* Page cache limit. The filesystems should put that into their s_maxbytes
of the BUG call as well as the EIP and oops trace. This aids
debugging but costs about 70-100K of memory.
-config DEBUG_WRITECOUNT
- bool "Debug filesystem writers count"
- depends on DEBUG_KERNEL
- help
- Enable this to catch wrong use of the writers count in struct
- vfsmount. This will increase the size of each file struct by
- 32 bits.
-
- If unsure, say N.
-
config DEBUG_LIST
bool "Debug linked list manipulation"
depends on DEBUG_KERNEL