aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hfs')
-rw-r--r--fs/hfs/dir.c4
-rw-r--r--fs/hfs/extent.c2
-rw-r--r--fs/hfs/hfs_fs.h15
-rw-r--r--fs/hfs/inode.c16
-rw-r--r--fs/hfs/mdb.c13
-rw-r--r--fs/hfs/super.c73
-rw-r--r--fs/hfs/sysdep.c4
7 files changed, 68 insertions, 59 deletions
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 62fc14ea4b73..422dde2ec0a1 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -18,7 +18,7 @@
18 * hfs_lookup() 18 * hfs_lookup()
19 */ 19 */
20static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry, 20static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
21 struct nameidata *nd) 21 unsigned int flags)
22{ 22{
23 hfs_cat_rec rec; 23 hfs_cat_rec rec;
24 struct hfs_find_data fd; 24 struct hfs_find_data fd;
@@ -187,7 +187,7 @@ static int hfs_dir_release(struct inode *inode, struct file *file)
187 * the directory and the name (and its length) of the new file. 187 * the directory and the name (and its length) of the new file.
188 */ 188 */
189static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, 189static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
190 struct nameidata *nd) 190 bool excl)
191{ 191{
192 struct inode *inode; 192 struct inode *inode;
193 int res; 193 int res;
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index 2c16316d2917..a67955a0c36f 100644
--- a/fs/hfs/extent.c
+++ b/fs/hfs/extent.c
@@ -432,7 +432,7 @@ out:
432 if (inode->i_ino < HFS_FIRSTUSER_CNID) 432 if (inode->i_ino < HFS_FIRSTUSER_CNID)
433 set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags); 433 set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags);
434 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 434 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
435 sb->s_dirt = 1; 435 hfs_mark_mdb_dirty(sb);
436 } 436 }
437 return res; 437 return res;
438 438
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 1bf967c6bfdc..8275175acf6e 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -14,6 +14,7 @@
14#include <linux/mutex.h> 14#include <linux/mutex.h>
15#include <linux/buffer_head.h> 15#include <linux/buffer_head.h>
16#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/workqueue.h>
17 18
18#include <asm/byteorder.h> 19#include <asm/byteorder.h>
19#include <asm/uaccess.h> 20#include <asm/uaccess.h>
@@ -137,16 +138,15 @@ struct hfs_sb_info {
137 gid_t s_gid; /* The gid of all files */ 138 gid_t s_gid; /* The gid of all files */
138 139
139 int session, part; 140 int session, part;
140
141 struct nls_table *nls_io, *nls_disk; 141 struct nls_table *nls_io, *nls_disk;
142
143 struct mutex bitmap_lock; 142 struct mutex bitmap_lock;
144
145 unsigned long flags; 143 unsigned long flags;
146
147 u16 blockoffset; 144 u16 blockoffset;
148
149 int fs_div; 145 int fs_div;
146 struct super_block *sb;
147 int work_queued; /* non-zero delayed work is queued */
148 struct delayed_work mdb_work; /* MDB flush delayed work */
149 spinlock_t work_lock; /* protects mdb_work and work_queued */
150}; 150};
151 151
152#define HFS_FLG_BITMAP_DIRTY 0 152#define HFS_FLG_BITMAP_DIRTY 0
@@ -226,6 +226,9 @@ extern int hfs_compare_dentry(const struct dentry *parent,
226extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *); 226extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
227extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *); 227extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
228 228
229/* super.c */
230extern void hfs_mark_mdb_dirty(struct super_block *sb);
231
229extern struct timezone sys_tz; 232extern struct timezone sys_tz;
230 233
231/* 234/*
@@ -253,7 +256,7 @@ static inline const char *hfs_mdb_name(struct super_block *sb)
253static inline void hfs_bitmap_dirty(struct super_block *sb) 256static inline void hfs_bitmap_dirty(struct super_block *sb)
254{ 257{
255 set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags); 258 set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags);
256 sb->s_dirt = 1; 259 hfs_mark_mdb_dirty(sb);
257} 260}
258 261
259#define sb_bread512(sb, sec, data) ({ \ 262#define sb_bread512(sb, sec, data) ({ \
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 761ec06354b4..ee1bc55677f1 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -220,7 +220,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)
220 insert_inode_hash(inode); 220 insert_inode_hash(inode);
221 mark_inode_dirty(inode); 221 mark_inode_dirty(inode);
222 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 222 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
223 sb->s_dirt = 1; 223 hfs_mark_mdb_dirty(sb);
224 224
225 return inode; 225 return inode;
226} 226}
@@ -235,7 +235,7 @@ void hfs_delete_inode(struct inode *inode)
235 if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID)) 235 if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
236 HFS_SB(sb)->root_dirs--; 236 HFS_SB(sb)->root_dirs--;
237 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 237 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
238 sb->s_dirt = 1; 238 hfs_mark_mdb_dirty(sb);
239 return; 239 return;
240 } 240 }
241 HFS_SB(sb)->file_count--; 241 HFS_SB(sb)->file_count--;
@@ -248,7 +248,7 @@ void hfs_delete_inode(struct inode *inode)
248 } 248 }
249 } 249 }
250 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 250 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
251 sb->s_dirt = 1; 251 hfs_mark_mdb_dirty(sb);
252} 252}
253 253
254void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext, 254void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
@@ -489,7 +489,7 @@ out:
489} 489}
490 490
491static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry, 491static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
492 struct nameidata *nd) 492 unsigned int flags)
493{ 493{
494 struct inode *inode = NULL; 494 struct inode *inode = NULL;
495 hfs_cat_rec rec; 495 hfs_cat_rec rec;
@@ -644,13 +644,7 @@ static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
644 644
645 /* sync the superblock to buffers */ 645 /* sync the superblock to buffers */
646 sb = inode->i_sb; 646 sb = inode->i_sb;
647 if (sb->s_dirt) { 647 flush_delayed_work_sync(&HFS_SB(sb)->mdb_work);
648 lock_super(sb);
649 sb->s_dirt = 0;
650 if (!(sb->s_flags & MS_RDONLY))
651 hfs_mdb_commit(sb);
652 unlock_super(sb);
653 }
654 /* .. finally sync the buffers to disk */ 648 /* .. finally sync the buffers to disk */
655 err = sync_blockdev(sb->s_bdev); 649 err = sync_blockdev(sb->s_bdev);
656 if (!ret) 650 if (!ret)
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index 1563d5ce5764..5fd51a5833ff 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -260,6 +260,10 @@ void hfs_mdb_commit(struct super_block *sb)
260{ 260{
261 struct hfs_mdb *mdb = HFS_SB(sb)->mdb; 261 struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
262 262
263 if (sb->s_flags & MS_RDONLY)
264 return;
265
266 lock_buffer(HFS_SB(sb)->mdb_bh);
263 if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) { 267 if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) {
264 /* These parameters may have been modified, so write them back */ 268 /* These parameters may have been modified, so write them back */
265 mdb->drLsMod = hfs_mtime(); 269 mdb->drLsMod = hfs_mtime();
@@ -283,9 +287,13 @@ void hfs_mdb_commit(struct super_block *sb)
283 &mdb->drXTFlSize, NULL); 287 &mdb->drXTFlSize, NULL);
284 hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec, 288 hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec,
285 &mdb->drCTFlSize, NULL); 289 &mdb->drCTFlSize, NULL);
290
291 lock_buffer(HFS_SB(sb)->alt_mdb_bh);
286 memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE); 292 memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE);
287 HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT); 293 HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT);
288 HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT); 294 HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT);
295 unlock_buffer(HFS_SB(sb)->alt_mdb_bh);
296
289 mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh); 297 mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh);
290 sync_dirty_buffer(HFS_SB(sb)->alt_mdb_bh); 298 sync_dirty_buffer(HFS_SB(sb)->alt_mdb_bh);
291 } 299 }
@@ -308,7 +316,11 @@ void hfs_mdb_commit(struct super_block *sb)
308 break; 316 break;
309 } 317 }
310 len = min((int)sb->s_blocksize - off, size); 318 len = min((int)sb->s_blocksize - off, size);
319
320 lock_buffer(bh);
311 memcpy(bh->b_data + off, ptr, len); 321 memcpy(bh->b_data + off, ptr, len);
322 unlock_buffer(bh);
323
312 mark_buffer_dirty(bh); 324 mark_buffer_dirty(bh);
313 brelse(bh); 325 brelse(bh);
314 block++; 326 block++;
@@ -317,6 +329,7 @@ void hfs_mdb_commit(struct super_block *sb)
317 size -= len; 329 size -= len;
318 } 330 }
319 } 331 }
332 unlock_buffer(HFS_SB(sb)->mdb_bh);
320} 333}
321 334
322void hfs_mdb_close(struct super_block *sb) 335void hfs_mdb_close(struct super_block *sb)
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 7b4c537d6e13..4eb873e0c07b 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -29,43 +29,9 @@ static struct kmem_cache *hfs_inode_cachep;
29 29
30MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
31 31
32/*
33 * hfs_write_super()
34 *
35 * Description:
36 * This function is called by the VFS only. When the filesystem
37 * is mounted r/w it updates the MDB on disk.
38 * Input Variable(s):
39 * struct super_block *sb: Pointer to the hfs superblock
40 * Output Variable(s):
41 * NONE
42 * Returns:
43 * void
44 * Preconditions:
45 * 'sb' points to a "valid" (struct super_block).
46 * Postconditions:
47 * The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb
48 * (hfs_put_super() must set this flag!). Some MDB fields are updated
49 * and the MDB buffer is written to disk by calling hfs_mdb_commit().
50 */
51static void hfs_write_super(struct super_block *sb)
52{
53 lock_super(sb);
54 sb->s_dirt = 0;
55
56 /* sync everything to the buffers */
57 if (!(sb->s_flags & MS_RDONLY))
58 hfs_mdb_commit(sb);
59 unlock_super(sb);
60}
61
62static int hfs_sync_fs(struct super_block *sb, int wait) 32static int hfs_sync_fs(struct super_block *sb, int wait)
63{ 33{
64 lock_super(sb);
65 hfs_mdb_commit(sb); 34 hfs_mdb_commit(sb);
66 sb->s_dirt = 0;
67 unlock_super(sb);
68
69 return 0; 35 return 0;
70} 36}
71 37
@@ -78,13 +44,44 @@ static int hfs_sync_fs(struct super_block *sb, int wait)
78 */ 44 */
79static void hfs_put_super(struct super_block *sb) 45static void hfs_put_super(struct super_block *sb)
80{ 46{
81 if (sb->s_dirt) 47 cancel_delayed_work_sync(&HFS_SB(sb)->mdb_work);
82 hfs_write_super(sb);
83 hfs_mdb_close(sb); 48 hfs_mdb_close(sb);
84 /* release the MDB's resources */ 49 /* release the MDB's resources */
85 hfs_mdb_put(sb); 50 hfs_mdb_put(sb);
86} 51}
87 52
53static void flush_mdb(struct work_struct *work)
54{
55 struct hfs_sb_info *sbi;
56 struct super_block *sb;
57
58 sbi = container_of(work, struct hfs_sb_info, mdb_work.work);
59 sb = sbi->sb;
60
61 spin_lock(&sbi->work_lock);
62 sbi->work_queued = 0;
63 spin_unlock(&sbi->work_lock);
64
65 hfs_mdb_commit(sb);
66}
67
68void hfs_mark_mdb_dirty(struct super_block *sb)
69{
70 struct hfs_sb_info *sbi = HFS_SB(sb);
71 unsigned long delay;
72
73 if (sb->s_flags & MS_RDONLY)
74 return;
75
76 spin_lock(&sbi->work_lock);
77 if (!sbi->work_queued) {
78 delay = msecs_to_jiffies(dirty_writeback_interval * 10);
79 queue_delayed_work(system_long_wq, &sbi->mdb_work, delay);
80 sbi->work_queued = 1;
81 }
82 spin_unlock(&sbi->work_lock);
83}
84
88/* 85/*
89 * hfs_statfs() 86 * hfs_statfs()
90 * 87 *
@@ -184,7 +181,6 @@ static const struct super_operations hfs_super_operations = {
184 .write_inode = hfs_write_inode, 181 .write_inode = hfs_write_inode,
185 .evict_inode = hfs_evict_inode, 182 .evict_inode = hfs_evict_inode,
186 .put_super = hfs_put_super, 183 .put_super = hfs_put_super,
187 .write_super = hfs_write_super,
188 .sync_fs = hfs_sync_fs, 184 .sync_fs = hfs_sync_fs,
189 .statfs = hfs_statfs, 185 .statfs = hfs_statfs,
190 .remount_fs = hfs_remount, 186 .remount_fs = hfs_remount,
@@ -387,7 +383,10 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
387 if (!sbi) 383 if (!sbi)
388 return -ENOMEM; 384 return -ENOMEM;
389 385
386 sbi->sb = sb;
390 sb->s_fs_info = sbi; 387 sb->s_fs_info = sbi;
388 spin_lock_init(&sbi->work_lock);
389 INIT_DELAYED_WORK(&sbi->mdb_work, flush_mdb);
391 390
392 res = -EINVAL; 391 res = -EINVAL;
393 if (!parse_options((char *)data, sbi)) { 392 if (!parse_options((char *)data, sbi)) {
diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c
index 19cf291eb91f..91b91fd3a901 100644
--- a/fs/hfs/sysdep.c
+++ b/fs/hfs/sysdep.c
@@ -13,12 +13,12 @@
13 13
14/* dentry case-handling: just lowercase everything */ 14/* dentry case-handling: just lowercase everything */
15 15
16static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) 16static int hfs_revalidate_dentry(struct dentry *dentry, unsigned int flags)
17{ 17{
18 struct inode *inode; 18 struct inode *inode;
19 int diff; 19 int diff;
20 20
21 if (nd->flags & LOOKUP_RCU) 21 if (flags & LOOKUP_RCU)
22 return -ECHILD; 22 return -ECHILD;
23 23
24 inode = dentry->d_inode; 24 inode = dentry->d_inode;