1 Index: linux-2.6.9/fs/ext3/inode.c
2 ===================================================================
3 --- linux-2.6.9.orig/fs/ext3/inode.c 2006-08-25 16:39:10.000000000 +0800
4 +++ linux-2.6.9/fs/ext3/inode.c 2006-09-14 11:44:29.000000000 +0800
11 ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
13 int err = journal_dirty_data(handle, bh);
14 Index: linux-2.6.9/fs/ext3/super.c
15 ===================================================================
16 --- linux-2.6.9.orig/fs/ext3/super.c 2006-08-25 16:39:48.000000000 +0800
17 +++ linux-2.6.9/fs/ext3/super.c 2006-09-14 11:51:48.000000000 +0800
19 static int ext3_write_info(struct super_block *sb, int type);
20 static int ext3_quota_on(struct super_block *sb, int type, int format_id, char *path);
21 static int ext3_quota_on_mount(struct super_block *sb, int type);
22 -static int ext3_quota_off_mount(struct super_block *sb, int type);
23 +static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
24 + size_t len, loff_t off);
25 +static ssize_t ext3_quota_write(struct super_block *sb, int type,
26 + const char *data, size_t len, loff_t off);
28 static struct dquot_operations ext3_quota_operations = {
29 .initialize = ext3_dquot_initialize,
31 .statfs = ext3_statfs,
32 .remount_fs = ext3_remount,
33 .clear_inode = ext3_clear_inode,
35 + .quota_read = ext3_quota_read,
36 + .quota_write = ext3_quota_write,
40 static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp)
50 "quota options when quota turned on.\n");
53 - if (sbi->s_qf_names[qtype]) {
54 + qname = match_strdup(&args[0]);
57 - "EXT3-fs: %s quota file already "
58 - "specified.\n", QTYPE2NAME(qtype));
59 + "EXT3-fs: not enough memory for "
60 + "storing quotafile name.\n");
63 - sbi->s_qf_names[qtype] = match_strdup(&args[0]);
64 - if (!sbi->s_qf_names[qtype]) {
65 + if (sbi->s_qf_names[qtype] &&
66 + strcmp(sbi->s_qf_names[qtype], qname)) {
68 - "EXT3-fs: not enough memory for "
69 - "storing quotafile name.\n");
70 + "EXT3-fs: %s quota file already "
71 + "specified.\n", QTYPE2NAME(qtype));
75 + sbi->s_qf_names[qtype] = qname;
76 if (strchr(sbi->s_qf_names[qtype], '/')) {
78 "EXT3-fs: quotafile must be on "
81 for (i = 0; i < MAXQUOTAS; i++) {
82 if (sb_dqopt(sb)->files[i])
83 - ext3_quota_off_mount(sb, i);
84 + vfs_quota_off(sb, i);
87 sb->s_flags = s_flags; /* Restore MS_RDONLY status */
90 static inline struct inode *dquot_to_inode(struct dquot *dquot)
92 - return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type]->f_dentry->d_inode;
93 + return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
96 static int ext3_dquot_initialize(struct inode *inode, int type)
97 @@ -2279,8 +2290,10 @@
101 + struct inode *inode;
103 - handle = ext3_journal_start(dquot_to_inode(dquot),
104 + inode = dquot_to_inode(dquot);
105 + handle = ext3_journal_start(inode,
106 EXT3_QUOTA_TRANS_BLOCKS);
108 return PTR_ERR(handle);
109 @@ -2367,22 +2380,9 @@
111 return PTR_ERR(dentry);
112 err = vfs_quota_on_mount(type, EXT3_SB(sb)->s_jquota_fmt, dentry);
115 - /* We keep the dentry reference if everything went ok - we drop it
116 - * on quota_off time */
120 -/* Turn quotas off during mount time */
121 -static int ext3_quota_off_mount(struct super_block *sb, int type)
124 - struct dentry *dentry;
126 - dentry = sb_dqopt(sb)->files[type]->f_dentry;
127 - err = vfs_quota_off_mount(sb, type);
128 - /* We invalidate dentry - it has at least wrong hash... */
129 + /* Now invalidate and put the dentry - quota got its own reference
130 + * to inode and dentry has at least wrong hash so we had better
132 d_invalidate(dentry);
135 @@ -2405,20 +2405,121 @@
138 /* Quotafile not on the same filesystem? */
139 - if (nd.mnt->mnt_sb != sb)
140 + if (nd.mnt->mnt_sb != sb) {
144 /* Quotafile not of fs root? */
145 if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode)
147 "EXT3-fs: Quota file not on filesystem root. "
148 "Journalled quota will not work.\n");
149 - if (!ext3_should_journal_data(nd.dentry->d_inode))
150 - printk(KERN_WARNING "EXT3-fs: Quota file does not have "
151 - "data-journalling. Journalled quota will not work.\n");
153 return vfs_quota_on(sb, type, format_id, path);
156 +/* Read data from quotafile - avoid pagecache and such because we cannot afford
157 + * acquiring the locks... As quota files are never truncated and quota code
158 + * itself serializes the operations (and noone else should touch the files)
159 + * we don't have to be afraid of races */
160 +static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
161 + size_t len, loff_t off)
163 + struct inode *inode = sb_dqopt(sb)->files[type];
164 + sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
166 + int offset = off & (sb->s_blocksize - 1);
169 + struct buffer_head *bh;
170 + loff_t i_size = i_size_read(inode);
174 + if (off+len > i_size)
177 + while (toread > 0) {
178 + tocopy = sb->s_blocksize - offset < toread ?
179 + sb->s_blocksize - offset : toread;
180 + bh = ext3_bread(NULL, inode, blk, 0, &err);
183 + if (!bh) /* A hole? */
184 + memset(data, 0, tocopy);
186 + memcpy(data, bh->b_data+offset, tocopy);
196 +/* Write to quotafile (we know the transaction is already started and has
197 + * enough credits) */
198 +static ssize_t ext3_quota_write(struct super_block *sb, int type,
199 + const char *data, size_t len, loff_t off)
201 + struct inode *inode = sb_dqopt(sb)->files[type];
202 + sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
204 + int offset = off & (sb->s_blocksize - 1);
206 + int journal_quota = EXT3_SB(sb)->s_qf_names[type] != NULL;
207 + size_t towrite = len;
208 + struct buffer_head *bh;
209 + handle_t *handle = journal_current_handle();
211 + down(&inode->i_sem);
212 + while (towrite > 0) {
213 + tocopy = sb->s_blocksize - offset < towrite ?
214 + sb->s_blocksize - offset : towrite;
215 + bh = ext3_bread(handle, inode, blk, 1, &err);
218 + if (journal_quota) {
219 + err = ext3_journal_get_write_access(handle, bh);
226 + memcpy(bh->b_data+offset, data, tocopy);
227 + flush_dcache_page(bh->b_page);
230 + err = ext3_journal_dirty_metadata(handle, bh);
232 + /* Always do at least ordered writes for quotas */
233 + err = ext3_journal_dirty_data(handle, bh);
234 + mark_buffer_dirty(bh);
245 + if (len == towrite)
247 + if (inode->i_size < off+len-towrite) {
248 + i_size_write(inode, off+len-towrite);
249 + EXT3_I(inode)->i_disksize = inode->i_size;
251 + inode->i_version++;
252 + inode->i_mtime = inode->i_ctime = CURRENT_TIME;
253 + ext3_mark_inode_dirty(handle, inode);
255 + return len - towrite;
260 static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
261 Index: linux-2.6.9/include/linux/ext3_jbd.h
262 ===================================================================
263 --- linux-2.6.9.orig/include/linux/ext3_jbd.h 2006-08-25 16:39:09.000000000 +0800
264 +++ linux-2.6.9/include/linux/ext3_jbd.h 2006-09-14 11:44:29.000000000 +0800
266 #define ext3_journal_forget(handle, bh) \
267 __ext3_journal_forget(__FUNCTION__, (handle), (bh))
269 +int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
271 handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks);
272 int __ext3_journal_stop(const char *where, handle_t *handle);