📄 2.6.5-quotafix.patch
字号:
Index: linux-2.6.5-7.283/include/linux/ext3_jbd.h===================================================================--- linux-2.6.5-7.283.orig/include/linux/ext3_jbd.h+++ linux-2.6.5-7.283/include/linux/ext3_jbd.h@@ -72,6 +72,19 @@ extern int ext3_writepage_trans_blocks(s #define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8 +#ifdef CONFIG_QUOTA+/* Amount of blocks needed for quota update - we know that the structure was+ * allocated so we need to update only inode+data */+#define EXT3_QUOTA_TRANS_BLOCKS 2+/* Amount of blocks needed for quota insert/delete - we do some block writes+ * but inode, sb and group updates are done only once */+#define EXT3_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*\+ (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3)+#else+#define EXT3_QUOTA_TRANS_BLOCKS 0+#define EXT3_QUOTA_INIT_BLOCKS 0+#endif+ int ext3_mark_iloc_dirty(handle_t *handle, struct inode *inode,@@ -97,6 +110,8 @@ int ext3_mark_inode_dirty(handle_t *hand void ext3_journal_abort_handle(const char *caller, const char *err_fn, struct buffer_head *bh, handle_t *handle, int err); +int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);+ static inline int __ext3_journal_get_undo_access(const char *where, handle_t *handle, struct buffer_head *bh, int *credits)Index: linux-2.6.5-7.283/include/linux/fs.h===================================================================--- linux-2.6.5-7.283.orig/include/linux/fs.h+++ linux-2.6.5-7.283/include/linux/fs.h@@ -967,6 +967,9 @@ struct super_operations { 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); }; /* Inode state bits. Protected by inode_lock. */Index: linux-2.6.5-7.283/include/linux/quota.h===================================================================--- linux-2.6.5-7.283.orig/include/linux/quota.h+++ linux-2.6.5-7.283/include/linux/quota.h@@ -138,6 +138,10 @@ struct if_dqinfo { #include <linux/dqblk_v1.h> #include <linux/dqblk_v2.h> +/* Maximal numbers of writes for quota operation (insert/delete/update)+ * (over all formats) - info block, 4 pointer blocks, data block */+#define DQUOT_MAX_WRITES 6+ /* * Data for one user/group kept in memory */@@ -168,22 +172,21 @@ struct mem_dqinfo { } u; }; +struct super_block;+ #define DQF_MASK 0xffff /* Mask for format specific flags */ #define DQF_INFO_DIRTY_B 16 #define DQF_ANY_DQUOT_DIRTY_B 17 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */ #define DQF_ANY_DQUOT_DIRTY (1 << DQF_ANY_DQUOT_DIRTY_B) /* Is any dquot dirty? */ -extern inline void mark_info_dirty(struct mem_dqinfo *info)-{- set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);-}-+extern void mark_info_dirty(struct super_block *sb, int type); #define info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags) #define info_any_dquot_dirty(info) test_bit(DQF_ANY_DQUOT_DIRTY_B, &(info)->dqi_flags) #define info_any_dirty(info) (info_dirty(info) || info_any_dquot_dirty(info)) #define sb_dqopt(sb) (&(sb)->s_dquot)+#define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type)) struct dqstats { int lookups;@@ -204,6 +207,9 @@ extern struct dqstats dqstats; #define DQ_BLKS_B 1 #define DQ_INODES_B 2 #define DQ_FAKE_B 3+#define DQ_READ_B 4 /* dquot was read into memory */+#define DQ_ACTIVE_B 5 /* dquot is active (dquot_release not called) */+#define DQ_WAITFREE_B 6 /* dquot being waited (by invalidate_dquots) */ #define DQ_MOD (1 << DQ_MOD_B) /* dquot modified since read */ #define DQ_BLKS (1 << DQ_BLKS_B) /* uid/gid has been warned about blk limit */@@ -239,18 +245,22 @@ struct quota_format_ops { int (*free_file_info)(struct super_block *sb, int type); /* Called on quotaoff() */ int (*read_dqblk)(struct dquot *dquot); /* Read structure for one user */ int (*commit_dqblk)(struct dquot *dquot); /* Write (or delete) structure for one user */+ int (*release_dqblk)(struct dquot *dquot); /* Called when last reference to dquot is being dropped */ }; /* Operations working with dquots */ struct dquot_operations {- void (*initialize) (struct inode *, int);- void (*drop) (struct inode *);+ 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_space) (struct inode *, qsize_t);- void (*free_inode) (const struct inode *, unsigned long);+ 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 *); /* Quota is going to be created on disk */+ int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */+ int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */ }; /* Operations handling requests from userspace */@@ -283,7 +293,8 @@ struct quota_info { struct semaphore dqio_sem; /* lock device while I/O in progress */ struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */ struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */- struct file *files[MAXQUOTAS]; /* fp's to quotafiles */+ struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */+ struct vfsmount *mnt[MAXQUOTAS]; /* mountpoint entries of filesystems with quota files */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ };Index: linux-2.6.5-7.283/include/linux/quotaops.h===================================================================--- linux-2.6.5-7.283.orig/include/linux/quotaops.h+++ linux-2.6.5-7.283/include/linux/quotaops.h@@ -22,17 +22,22 @@ */ extern void sync_dquots(struct super_block *sb, int type); -extern void dquot_initialize(struct inode *inode, int type);-extern void dquot_drop(struct inode *inode);+extern int dquot_initialize(struct inode *inode, int type);+extern int dquot_drop(struct inode *inode); extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc); extern int dquot_alloc_inode(const struct inode *inode, unsigned long number); -extern void dquot_free_space(struct inode *inode, qsize_t number);-extern void dquot_free_inode(const struct inode *inode, unsigned long number);+extern int dquot_free_space(struct inode *inode, qsize_t number);+extern int dquot_free_inode(const struct inode *inode, unsigned long number); extern int dquot_transfer(struct inode *inode, struct iattr *iattr); +extern int dquot_commit(struct dquot *dquot);+extern int dquot_commit_info(struct super_block *sb, int type);+extern int dquot_acquire(struct dquot *dquot);+extern int dquot_release(struct dquot *dquot);+ /* * Operations supported for diskquotas. */@@ -143,7 +148,7 @@ static __inline__ int DQUOT_OFF(struct s { int ret = -ENOSYS; - if (sb->s_qcop && sb->s_qcop->quota_off)+ if (sb_any_quota_enabled(sb) && sb->s_qcop && sb->s_qcop->quota_off) ret = sb->s_qcop->quota_off(sb, -1); return ret; }Index: linux-2.6.5-7.283/include/linux/security.h===================================================================--- linux-2.6.5-7.283.orig/include/linux/security.h+++ linux-2.6.5-7.283/include/linux/security.h@@ -1020,7 +1020,7 @@ struct security_operations { int (*sysctl) (ctl_table * table, int op); int (*capable) (struct task_struct * tsk, int cap); int (*quotactl) (int cmds, int type, int id, struct super_block * sb);- int (*quota_on) (struct file * f);+ int (*quota_on) (struct dentry * dentry); int (*syslog) (int type); int (*vm_enough_memory) (long pages); @@ -1292,9 +1292,9 @@ static inline int security_quotactl (int 0); } -static inline int security_quota_on (struct file * file)+static inline int security_quota_on (struct dentry * dentry) {- return COND_SECURITY(quota_on (file), + return COND_SECURITY(quota_on (dentry), 0); } Index: linux-2.6.5-7.283/security/dummy.c===================================================================--- linux-2.6.5-7.283.orig/security/dummy.c+++ linux-2.6.5-7.283/security/dummy.c@@ -90,7 +90,7 @@ static int dummy_quotactl (int cmds, int return 0; } -static int dummy_quota_on (struct file *f)+static int dummy_quota_on (struct dentry *dentry) { return 0; }Index: linux-2.6.5-7.283/security/selinux/hooks.c===================================================================--- linux-2.6.5-7.283.orig/security/selinux/hooks.c+++ linux-2.6.5-7.283/security/selinux/hooks.c@@ -1454,9 +1454,9 @@ static int selinux_quotactl(int cmds, in return rc; } -static int selinux_quota_on(struct file *f)+static int selinux_quota_on(struct dentry *dentry) {- return file_has_perm(current, f, FILE__QUOTAON);+ return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON); } static int selinux_syslog(int type)Index: linux-2.6.5-7.283/fs/dquot.c===================================================================--- linux-2.6.5-7.283.orig/fs/dquot.c+++ linux-2.6.5-7.283/fs/dquot.c@@ -52,6 +52,9 @@ * New SMP locking. * Jan Kara, <jack@suse.cz>, 10/2002 *+ * Fix lock inversion problems+ * Jan Kara, <jack@suse.cz>, 2003,2004+ * * (C) Copyright 1994 - 1997 Marco van Wieringen */ @@ -75,7 +78,8 @@ #include <linux/proc_fs.h> #include <linux/security.h> #include <linux/kmod.h>-#include <linux/pagemap.h>+#include <linux/namei.h>+#include <linux/buffer_head.h> #include <asm/uaccess.h> @@ -109,7 +113,7 @@ * dqget(). Write operations on dquots don't hold dq_lock as they copy data * under dq_data_lock spinlock to internal buffers before writing. *- * Lock ordering (including journal_lock) is following:+ * Lock ordering (including journal_lock) is the following: * dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > dqio_sem */ spinlock_t dq_list_lock = SPIN_LOCK_UNLOCKED;@@ -175,8 +179,7 @@ static void put_quota_format(struct quot * on all three lists, depending on its current state. * * All dquots are placed to the end of inuse_list when first created, and this- * list is used for the sync and invalidate operations, which must look- * at every dquot.+ * list is used for invalidate operation, which must look at every dquot. * * Unused dquots (dq_count == 0) are added to the free_dquots list when freed, * and this list is searched whenever we need an available dquot. Dquots are@@ -264,30 +267,105 @@ static void wait_on_dquot(struct dquot * up(&dquot->dq_lock); } -static int read_dqblk(struct dquot *dquot)+void mark_info_dirty(struct super_block *sb, int type) {- int ret;+ set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags);+}+EXPORT_SYMBOL(mark_info_dirty);++/*+ * Read dquot from disk and alloc space for it+ */++int dquot_acquire(struct dquot *dquot)+{+ int ret = 0, ret2 = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); down(&dquot->dq_lock); down(&dqopt->dqio_sem);- ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);+ if (!test_bit(DQ_READ_B, &dquot->dq_flags))+ ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);+ if (ret < 0)+ goto out_iolock;+ set_bit(DQ_READ_B, &dquot->dq_flags);+ /* Instantiate dquot if needed */+ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) {+ ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);+ /* Write the info if needed */+ if (info_dirty(&dqopt->info[dquot->dq_type]))+ ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);+ if (ret < 0)+ goto out_iolock;+ if (ret2 < 0) {+ ret = ret2;+ goto out_iolock;+ }+ }+ set_bit(DQ_ACTIVE_B, &dquot->dq_flags);+out_iolock: up(&dqopt->dqio_sem); up(&dquot->dq_lock); return ret; } -static int commit_dqblk(struct dquot *dquot)+/*+ * Write dquot to disk+ */+int dquot_commit(struct dquot *dquot) {- int ret;+ int ret = 0, ret2 = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); down(&dqopt->dqio_sem);- ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);+ spin_lock(&dq_list_lock);+ if (!test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags)) {+ spin_unlock(&dq_list_lock);+ goto out_sem;+ }+ spin_unlock(&dq_list_lock);+ /* Inactive dquot can be only if there was error during read/init+ * => we have better not writing it */+ if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {+ ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);+ if (info_dirty(&dqopt->info[dquot->dq_type]))+ ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);+ if (ret >= 0)+ ret = ret2;+ }+out_sem: up(&dqopt->dqio_sem); return ret; } +/*+ * Release dquot+ */+int dquot_release(struct dquot *dquot)+{+ int ret = 0, ret2 = 0;+ struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);++ down(&dquot->dq_lock);+ /* Check whether we are not racing with some other dqget() */+ if (atomic_read(&dquot->dq_count) > 1)+ goto out_dqlock;+ down(&dqopt->dqio_sem);+ if (dqopt->ops[dquot->dq_type]->release_dqblk) {+ ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot);+ /* Write the info */+ if (info_dirty(&dqopt->info[dquot->dq_type]))+ ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type);+ if (ret >= 0)+ ret = ret2;+ }+ clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);+ up(&dqopt->dqio_sem);+out_dqlock:+ up(&dquot->dq_lock);+ return ret;+}+ /* Invalidate all dquots on the list. Note that this function is called after * quota is disabled so no new quota might be created. Because we hold * dqonoff_sem and pointers were already removed from inodes we actually know@@ -343,6 +421,11 @@ restart: continue; if (!dquot_dirty(dquot)) continue;+ /* Dirty and inactive can be only bad dquot... */+ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {+ test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags);+ continue;+ } atomic_inc(&dquot->dq_count); dqstats.lookups++; spin_unlock(&dq_list_lock);@@ -353,11 +436,9 @@ restart:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -