📄 2.6.5-quotafix.patch
字号:
Index: linux-2.6.5-7.283/fs/ext3/super.c===================================================================--- linux-2.6.5-7.283.orig/fs/ext3/super.c+++ linux-2.6.5-7.283/fs/ext3/super.c@@ -33,6 +33,7 @@ #include <linux/vfs.h> #include <linux/random.h> #include <asm/uaccess.h>+#include <linux/quotaops.h> #include "xattr.h" #include "acl.h" @@ -505,7 +506,33 @@ static void ext3_clear_inode(struct inod ext3_discard_reservation(inode); } -static struct dquot_operations ext3_qops;+#ifdef CONFIG_QUOTA++static int ext3_dquot_initialize(struct inode *inode, int type);+static int ext3_dquot_drop(struct inode *inode);+static int ext3_write_dquot(struct dquot *dquot);+static int ext3_acquire_dquot(struct dquot *dquot);+static int ext3_release_dquot(struct dquot *dquot);+static int ext3_write_info(struct super_block *sb, int type);+static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,+ size_t len, loff_t off);+static ssize_t ext3_quota_write(struct super_block *sb, int type,+ const char *data, size_t len, loff_t off);++static struct dquot_operations ext3_quota_operations = {+ .initialize = ext3_dquot_initialize,+ .drop = ext3_dquot_drop,+ .alloc_space = dquot_alloc_space,+ .alloc_inode = dquot_alloc_inode,+ .free_space = dquot_free_space,+ .free_inode = dquot_free_inode,+ .transfer = dquot_transfer,+ .write_dquot = ext3_write_dquot,+ .acquire_dquot = ext3_acquire_dquot,+ .release_dquot = ext3_release_dquot,+ .write_info = ext3_write_info+};+#endif static struct super_operations ext3_sops = { .alloc_inode = ext3_alloc_inode,@@ -522,6 +549,10 @@ static struct super_operations ext3_sops .statfs = ext3_statfs, .remount_fs = ext3_remount, .clear_inode = ext3_clear_inode,+#ifdef CONFIG_QUOTA+ .quota_read = ext3_quota_read,+ .quota_write = ext3_quota_write,+#endif }; static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp)@@ -1377,7 +1408,9 @@ static int ext3_fill_super (struct super */ sb->s_op = &ext3_sops; sb->s_export_op = &ext3_export_ops;- sb->dq_op = &ext3_qops;+#ifdef CONFIG_QUOTA+ sb->dq_op = &ext3_quota_operations;+#endif INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ sb->s_root = 0;@@ -2040,70 +2073,200 @@ int ext3_statfs (struct super_block * sb #ifdef CONFIG_QUOTA -/* Blocks: (2 data blocks) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */-#define EXT3_OLD_QFMT_BLOCKS 11-/* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */-#define EXT3_V0_QFMT_BLOCKS 27--static int (*old_write_dquot)(struct dquot *dquot);-static void (*old_drop_dquot)(struct inode *inode);--static int fmt_to_blocks(int fmt)-{- switch (fmt) {- case QFMT_VFS_OLD:- return EXT3_OLD_QFMT_BLOCKS;- case QFMT_VFS_V0:- return EXT3_V0_QFMT_BLOCKS;- }- return EXT3_MAX_TRANS_DATA;+static inline struct inode *dquot_to_inode(struct dquot *dquot)+{+ return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];+}++static int ext3_dquot_initialize(struct inode *inode, int type)+{+ handle_t *handle;+ int ret, err;++ /* We may create quota structure so we need to reserve enough blocks */+ handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);+ if (IS_ERR(handle))+ return PTR_ERR(handle);+ ret = dquot_initialize(inode, type);+ err = ext3_journal_stop(handle);+ if (!ret)+ ret = err;+ return ret;+}++static int ext3_dquot_drop(struct inode *inode)+{+ handle_t *handle;+ int ret, err;++ /* We may delete quota structure so we need to reserve enough blocks */+ handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);+ if (IS_ERR(handle))+ return PTR_ERR(handle);+ ret = dquot_drop(inode);+ err = ext3_journal_stop(handle);+ if (!ret)+ ret = err;+ return ret; } static int ext3_write_dquot(struct dquot *dquot) {- int nblocks;- int ret;- int err;+ int ret, err; handle_t *handle;- struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);- struct inode *qinode;+ struct inode *inode; - nblocks = fmt_to_blocks(dqopt->info[dquot->dq_type].dqi_format->qf_fmt_id);- qinode = dqopt->files[dquot->dq_type]->f_dentry->d_inode;- handle = ext3_journal_start(qinode, nblocks);- if (IS_ERR(handle)) {- ret = PTR_ERR(handle);- goto out;- }- ret = old_write_dquot(dquot);+ inode = dquot_to_inode(dquot);+ handle = ext3_journal_start(inode,+ EXT3_QUOTA_TRANS_BLOCKS);+ if (IS_ERR(handle))+ return PTR_ERR(handle);+ ret = dquot_commit(dquot); err = ext3_journal_stop(handle);- if (ret == 0)+ if (!ret) ret = err;-out: return ret; } -static void ext3_drop_dquot(struct inode *inode)+static int ext3_acquire_dquot(struct dquot *dquot) {- int nblocks, type;- struct quota_info *dqopt = sb_dqopt(inode->i_sb);+ int ret, err; handle_t *handle; - for (type = 0; type < MAXQUOTAS; type++) {- if (sb_has_quota_enabled(inode->i_sb, type))- break;- }- if (type < MAXQUOTAS)- nblocks = fmt_to_blocks(dqopt->info[type].dqi_format->qf_fmt_id);- else- nblocks = 0; /* No quota => no drop */ - handle = ext3_journal_start(inode, 2*nblocks);+ handle = ext3_journal_start(dquot_to_inode(dquot),+ EXT3_QUOTA_INIT_BLOCKS); if (IS_ERR(handle))- return;- old_drop_dquot(inode);- ext3_journal_stop(handle);- return;+ return PTR_ERR(handle);+ ret = dquot_acquire(dquot);+ err = ext3_journal_stop(handle);+ if (!ret)+ ret = err;+ return ret; }++static int ext3_release_dquot(struct dquot *dquot)+{+ int ret, err;+ handle_t *handle;++ handle = ext3_journal_start(dquot_to_inode(dquot),+ EXT3_QUOTA_INIT_BLOCKS);+ if (IS_ERR(handle))+ return PTR_ERR(handle);+ ret = dquot_release(dquot);+ err = ext3_journal_stop(handle);+ if (!ret)+ ret = err;+ return ret;+}++static int ext3_write_info(struct super_block *sb, int type)+{+ int ret, err;+ handle_t *handle;++ /* Data block + inode block */+ handle = ext3_journal_start(sb->s_root->d_inode, 2);+ if (IS_ERR(handle))+ return PTR_ERR(handle);+ ret = dquot_commit_info(sb, type);+ err = ext3_journal_stop(handle);+ if (!ret)+ ret = err;+ return ret;+}++/* Read data from quotafile - avoid pagecache and such because we cannot afford+ * acquiring the locks... As quota files are never truncated and quota code+ * itself serializes the operations (and noone else should touch the files)+ * we don't have to be afraid of races */+static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,+ size_t len, loff_t off)+{+ struct inode *inode = sb_dqopt(sb)->files[type];+ sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);+ int err = 0;+ int offset = off & (sb->s_blocksize - 1);+ int tocopy;+ size_t toread;+ struct buffer_head *bh;+ loff_t i_size = i_size_read(inode);++ if (off > i_size)+ return 0;+ if (off+len > i_size)+ len = i_size-off;+ toread = len;+ while (toread > 0) {+ tocopy = sb->s_blocksize - offset < toread ?+ sb->s_blocksize - offset : toread;+ bh = ext3_bread(NULL, inode, blk, 0, &err);+ if (err)+ return err;+ if (!bh) /* A hole? */+ memset(data, 0, tocopy);+ else+ memcpy(data, bh->b_data+offset, tocopy);+ brelse(bh);+ offset = 0;+ toread -= tocopy;+ data += tocopy;+ blk++;+ }+ return len;+}++/* Write to quotafile (we know the transaction is already started and has+ * enough credits) */+static ssize_t ext3_quota_write(struct super_block *sb, int type,+ const char *data, size_t len, loff_t off)+{+ struct inode *inode = sb_dqopt(sb)->files[type];+ sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);+ int err = 0;+ int offset = off & (sb->s_blocksize - 1);+ int tocopy;+ size_t towrite = len;+ struct buffer_head *bh;+ handle_t *handle = journal_current_handle();++ down(&inode->i_sem);+ while (towrite > 0) {+ tocopy = sb->s_blocksize - offset < towrite ?+ sb->s_blocksize - offset : towrite;+ bh = ext3_bread(handle, inode, blk, 1, &err);+ if (!bh)+ goto out;+ + lock_buffer(bh);+ memcpy(bh->b_data+offset, data, tocopy);+ flush_dcache_page(bh->b_page);+ unlock_buffer(bh);+ /* Always do at least ordered writes for quotas */+ err = ext3_journal_dirty_data(handle, bh);+ mark_buffer_dirty(bh);+ brelse(bh);+ if (err)+ goto out;+ offset = 0;+ towrite -= tocopy;+ data += tocopy;+ blk++;+ }+out:+ if (len == towrite)+ return err;+ if (inode->i_size < off+len-towrite) {+ i_size_write(inode, off+len-towrite);+ EXT3_I(inode)->i_disksize = inode->i_size;+ }+ inode->i_version++;+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;+ ext3_mark_inode_dirty(handle, inode);+ up(&inode->i_sem);+ return len - towrite;+}+ #endif static struct super_block *ext3_get_sb(struct file_system_type *fs_type,@@ -2128,13 +2291,7 @@ static int __init init_ext3_fs(void) err = init_inodecache(); if (err) goto out1;-#ifdef CONFIG_QUOTA- init_dquot_operations(&ext3_qops);- old_write_dquot = ext3_qops.write_dquot;- old_drop_dquot = ext3_qops.drop;- ext3_qops.write_dquot = ext3_write_dquot;- ext3_qops.drop = ext3_drop_dquot;-#endif+ err = register_filesystem_lifo(&ext3_fs_type); if (err) goto out;Index: linux-2.6.5-7.283/fs/quota_v1.c===================================================================--- linux-2.6.5-7.283.orig/fs/quota_v1.c+++ linux-2.6.5-7.283/fs/quota_v1.c@@ -7,7 +7,6 @@ #include <linux/init.h> #include <linux/module.h> -#include <asm/uaccess.h> #include <asm/byteorder.h> MODULE_AUTHOR("Jan Kara");@@ -41,23 +40,14 @@ static void v1_mem2disk_dqblk(struct v1_ static int v1_read_dqblk(struct dquot *dquot) { int type = dquot->dq_type;- struct file *filp;- mm_segment_t fs;- loff_t offset; struct v1_disk_dqblk dqblk; - filp = sb_dqopt(dquot->dq_sb)->files[type];- if (filp == (struct file *)NULL)+ if (!sb_dqopt(dquot->dq_sb)->files[type]) return -EINVAL; - /* Now we are sure filp is valid */- offset = v1_dqoff(dquot->dq_id); /* Set structure to 0s in case read fails/is after end of file */ memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));- fs = get_fs();- set_fs(KERNEL_DS);- filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);- set_fs(fs);+ dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id)); v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk); if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&@@ -71,17 +61,9 @@ static int v1_read_dqblk(struct dquot *d static int v1_commit_dqblk(struct dquot *dquot) { short type = dquot->dq_type;- struct file *filp;- mm_segment_t fs;- loff_t offset; ssize_t ret; struct v1_disk_dqblk dqblk; - filp = sb_dqopt(dquot->dq_sb)->files[type];- offset = v1_dqoff(dquot->dq_id);- fs = get_fs();- set_fs(KERNEL_DS);- /* * Note: clear the DQ_MOD flag unconditionally, * so we don't loop forever on failure.@@ -93,9 +75,10 @@ static int v1_commit_dqblk(struct dquot dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace; } ret = 0;- if (filp)- ret = filp->f_op->write(filp, (char *)&dqblk,- sizeof(struct v1_disk_dqblk), &off
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -