aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfs
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/hfs
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'fs/hfs')
-rw-r--r--fs/hfs/dir.c12
-rw-r--r--fs/hfs/extent.c2
-rw-r--r--fs/hfs/hfs_fs.h21
-rw-r--r--fs/hfs/inode.c54
-rw-r--r--fs/hfs/mdb.c17
-rw-r--r--fs/hfs/super.c106
-rw-r--r--fs/hfs/sysdep.c4
7 files changed, 92 insertions, 124 deletions
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 422dde2ec0a..b4d70b13be9 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 unsigned int flags) 21 struct nameidata *nd)
22{ 22{
23 hfs_cat_rec rec; 23 hfs_cat_rec rec;
24 struct hfs_find_data fd; 24 struct hfs_find_data fd;
@@ -186,8 +186,8 @@ static int hfs_dir_release(struct inode *inode, struct file *file)
186 * a directory and return a corresponding inode, given the inode for 186 * a directory and return a corresponding inode, given the inode for
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, int mode,
190 bool excl) 190 struct nameidata *nd)
191{ 191{
192 struct inode *inode; 192 struct inode *inode;
193 int res; 193 int res;
@@ -198,7 +198,7 @@ static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
198 198
199 res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode); 199 res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
200 if (res) { 200 if (res) {
201 clear_nlink(inode); 201 inode->i_nlink = 0;
202 hfs_delete_inode(inode); 202 hfs_delete_inode(inode);
203 iput(inode); 203 iput(inode);
204 return res; 204 return res;
@@ -216,7 +216,7 @@ static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
216 * in a directory, given the inode for the parent directory and the 216 * in a directory, given the inode for the parent directory and the
217 * name (and its length) of the new directory. 217 * name (and its length) of the new directory.
218 */ 218 */
219static int hfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 219static int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
220{ 220{
221 struct inode *inode; 221 struct inode *inode;
222 int res; 222 int res;
@@ -227,7 +227,7 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
227 227
228 res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode); 228 res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
229 if (res) { 229 if (res) {
230 clear_nlink(inode); 230 inode->i_nlink = 0;
231 hfs_delete_inode(inode); 231 hfs_delete_inode(inode);
232 iput(inode); 232 iput(inode);
233 return res; 233 return res;
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index a67955a0c36..2c16316d291 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 hfs_mark_mdb_dirty(sb); 435 sb->s_dirt = 1;
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 693df9fe52b..ad97c2d5828 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -14,7 +14,6 @@
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>
18 17
19#include <asm/byteorder.h> 18#include <asm/byteorder.h>
20#include <asm/uaccess.h> 19#include <asm/uaccess.h>
@@ -134,19 +133,20 @@ struct hfs_sb_info {
134 permissions on all files */ 133 permissions on all files */
135 umode_t s_dir_umask; /* The umask applied to the 134 umode_t s_dir_umask; /* The umask applied to the
136 permissions on all dirs */ 135 permissions on all dirs */
137 kuid_t s_uid; /* The uid of all files */ 136 uid_t s_uid; /* The uid of all files */
138 kgid_t s_gid; /* The gid of all files */ 137 gid_t s_gid; /* The gid of all files */
139 138
140 int session, part; 139 int session, part;
140
141 struct nls_table *nls_io, *nls_disk; 141 struct nls_table *nls_io, *nls_disk;
142
142 struct mutex bitmap_lock; 143 struct mutex bitmap_lock;
144
143 unsigned long flags; 145 unsigned long flags;
146
144 u16 blockoffset; 147 u16 blockoffset;
148
145 int fs_div; 149 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
@@ -184,7 +184,7 @@ extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
184extern const struct address_space_operations hfs_aops; 184extern const struct address_space_operations hfs_aops;
185extern const struct address_space_operations hfs_btree_aops; 185extern const struct address_space_operations hfs_btree_aops;
186 186
187extern struct inode *hfs_new_inode(struct inode *, struct qstr *, umode_t); 187extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int);
188extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *); 188extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
189extern int hfs_write_inode(struct inode *, struct writeback_control *); 189extern int hfs_write_inode(struct inode *, struct writeback_control *);
190extern int hfs_inode_setattr(struct dentry *, struct iattr *); 190extern int hfs_inode_setattr(struct dentry *, struct iattr *);
@@ -226,9 +226,6 @@ 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
232extern struct timezone sys_tz; 229extern struct timezone sys_tz;
233 230
234/* 231/*
@@ -256,7 +253,7 @@ static inline const char *hfs_mdb_name(struct super_block *sb)
256static inline void hfs_bitmap_dirty(struct super_block *sb) 253static inline void hfs_bitmap_dirty(struct super_block *sb)
257{ 254{
258 set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags); 255 set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags);
259 hfs_mark_mdb_dirty(sb); 256 sb->s_dirt = 1;
260} 257}
261 258
262#define sb_bread512(sb, sec, data) ({ \ 259#define sb_bread512(sb, sec, data) ({ \
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index d47f11658c1..96a1b625fc7 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -35,16 +35,6 @@ static int hfs_readpage(struct file *file, struct page *page)
35 return block_read_full_page(page, hfs_get_block); 35 return block_read_full_page(page, hfs_get_block);
36} 36}
37 37
38static void hfs_write_failed(struct address_space *mapping, loff_t to)
39{
40 struct inode *inode = mapping->host;
41
42 if (to > inode->i_size) {
43 truncate_pagecache(inode, to, inode->i_size);
44 hfs_file_truncate(inode);
45 }
46}
47
48static int hfs_write_begin(struct file *file, struct address_space *mapping, 38static int hfs_write_begin(struct file *file, struct address_space *mapping,
49 loff_t pos, unsigned len, unsigned flags, 39 loff_t pos, unsigned len, unsigned flags,
50 struct page **pagep, void **fsdata) 40 struct page **pagep, void **fsdata)
@@ -55,8 +45,11 @@ static int hfs_write_begin(struct file *file, struct address_space *mapping,
55 ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, 45 ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
56 hfs_get_block, 46 hfs_get_block,
57 &HFS_I(mapping->host)->phys_size); 47 &HFS_I(mapping->host)->phys_size);
58 if (unlikely(ret)) 48 if (unlikely(ret)) {
59 hfs_write_failed(mapping, pos + len); 49 loff_t isize = mapping->host->i_size;
50 if (pos + len > isize)
51 vmtruncate(mapping->host, isize);
52 }
60 53
61 return ret; 54 return ret;
62} 55}
@@ -127,7 +120,6 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
127 const struct iovec *iov, loff_t offset, unsigned long nr_segs) 120 const struct iovec *iov, loff_t offset, unsigned long nr_segs)
128{ 121{
129 struct file *file = iocb->ki_filp; 122 struct file *file = iocb->ki_filp;
130 struct address_space *mapping = file->f_mapping;
131 struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; 123 struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
132 ssize_t ret; 124 ssize_t ret;
133 125
@@ -143,7 +135,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
143 loff_t end = offset + iov_length(iov, nr_segs); 135 loff_t end = offset + iov_length(iov, nr_segs);
144 136
145 if (end > isize) 137 if (end > isize)
146 hfs_write_failed(mapping, end); 138 vmtruncate(inode, isize);
147 } 139 }
148 140
149 return ret; 141 return ret;
@@ -177,7 +169,7 @@ const struct address_space_operations hfs_aops = {
177/* 169/*
178 * hfs_new_inode 170 * hfs_new_inode
179 */ 171 */
180struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode) 172struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
181{ 173{
182 struct super_block *sb = dir->i_sb; 174 struct super_block *sb = dir->i_sb;
183 struct inode *inode = new_inode(sb); 175 struct inode *inode = new_inode(sb);
@@ -191,7 +183,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)
191 inode->i_mode = mode; 183 inode->i_mode = mode;
192 inode->i_uid = current_fsuid(); 184 inode->i_uid = current_fsuid();
193 inode->i_gid = current_fsgid(); 185 inode->i_gid = current_fsgid();
194 set_nlink(inode, 1); 186 inode->i_nlink = 1;
195 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; 187 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
196 HFS_I(inode)->flags = 0; 188 HFS_I(inode)->flags = 0;
197 HFS_I(inode)->rsrc_inode = NULL; 189 HFS_I(inode)->rsrc_inode = NULL;
@@ -228,7 +220,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)
228 insert_inode_hash(inode); 220 insert_inode_hash(inode);
229 mark_inode_dirty(inode); 221 mark_inode_dirty(inode);
230 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 222 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
231 hfs_mark_mdb_dirty(sb); 223 sb->s_dirt = 1;
232 224
233 return inode; 225 return inode;
234} 226}
@@ -243,7 +235,7 @@ void hfs_delete_inode(struct inode *inode)
243 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))
244 HFS_SB(sb)->root_dirs--; 236 HFS_SB(sb)->root_dirs--;
245 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 237 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
246 hfs_mark_mdb_dirty(sb); 238 sb->s_dirt = 1;
247 return; 239 return;
248 } 240 }
249 HFS_SB(sb)->file_count--; 241 HFS_SB(sb)->file_count--;
@@ -256,7 +248,7 @@ void hfs_delete_inode(struct inode *inode)
256 } 248 }
257 } 249 }
258 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 250 set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
259 hfs_mark_mdb_dirty(sb); 251 sb->s_dirt = 1;
260} 252}
261 253
262void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext, 254void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
@@ -321,7 +313,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
321 /* Initialize the inode */ 313 /* Initialize the inode */
322 inode->i_uid = hsb->s_uid; 314 inode->i_uid = hsb->s_uid;
323 inode->i_gid = hsb->s_gid; 315 inode->i_gid = hsb->s_gid;
324 set_nlink(inode, 1); 316 inode->i_nlink = 1;
325 317
326 if (idata->key) 318 if (idata->key)
327 HFS_I(inode)->cat_key = *idata->key; 319 HFS_I(inode)->cat_key = *idata->key;
@@ -497,7 +489,7 @@ out:
497} 489}
498 490
499static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry, 491static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
500 unsigned int flags) 492 struct nameidata *nd)
501{ 493{
502 struct inode *inode = NULL; 494 struct inode *inode = NULL;
503 hfs_cat_rec rec; 495 hfs_cat_rec rec;
@@ -540,7 +532,7 @@ out:
540void hfs_evict_inode(struct inode *inode) 532void hfs_evict_inode(struct inode *inode)
541{ 533{
542 truncate_inode_pages(&inode->i_data, 0); 534 truncate_inode_pages(&inode->i_data, 0);
543 clear_inode(inode); 535 end_writeback(inode);
544 if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) { 536 if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) {
545 HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL; 537 HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL;
546 iput(HFS_I(inode)->rsrc_inode); 538 iput(HFS_I(inode)->rsrc_inode);
@@ -602,9 +594,9 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
602 594
603 /* no uig/gid changes and limit which mode bits can be set */ 595 /* no uig/gid changes and limit which mode bits can be set */
604 if (((attr->ia_valid & ATTR_UID) && 596 if (((attr->ia_valid & ATTR_UID) &&
605 (!uid_eq(attr->ia_uid, hsb->s_uid))) || 597 (attr->ia_uid != hsb->s_uid)) ||
606 ((attr->ia_valid & ATTR_GID) && 598 ((attr->ia_valid & ATTR_GID) &&
607 (!gid_eq(attr->ia_gid, hsb->s_gid))) || 599 (attr->ia_gid != hsb->s_gid)) ||
608 ((attr->ia_valid & ATTR_MODE) && 600 ((attr->ia_valid & ATTR_MODE) &&
609 ((S_ISDIR(inode->i_mode) && 601 ((S_ISDIR(inode->i_mode) &&
610 (attr->ia_mode != inode->i_mode)) || 602 (attr->ia_mode != inode->i_mode)) ||
@@ -625,12 +617,9 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
625 attr->ia_size != i_size_read(inode)) { 617 attr->ia_size != i_size_read(inode)) {
626 inode_dio_wait(inode); 618 inode_dio_wait(inode);
627 619
628 error = inode_newsize_ok(inode, attr->ia_size); 620 error = vmtruncate(inode, attr->ia_size);
629 if (error) 621 if (error)
630 return error; 622 return error;
631
632 truncate_setsize(inode, attr->ia_size);
633 hfs_file_truncate(inode);
634 } 623 }
635 624
636 setattr_copy(inode, attr); 625 setattr_copy(inode, attr);
@@ -655,7 +644,13 @@ static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
655 644
656 /* sync the superblock to buffers */ 645 /* sync the superblock to buffers */
657 sb = inode->i_sb; 646 sb = inode->i_sb;
658 flush_delayed_work(&HFS_SB(sb)->mdb_work); 647 if (sb->s_dirt) {
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 }
659 /* .. finally sync the buffers to disk */ 654 /* .. finally sync the buffers to disk */
660 err = sync_blockdev(sb->s_bdev); 655 err = sync_blockdev(sb->s_bdev);
661 if (!ret) 656 if (!ret)
@@ -679,6 +674,7 @@ static const struct file_operations hfs_file_operations = {
679 674
680static const struct inode_operations hfs_file_inode_operations = { 675static const struct inode_operations hfs_file_inode_operations = {
681 .lookup = hfs_file_lookup, 676 .lookup = hfs_file_lookup,
677 .truncate = hfs_file_truncate,
682 .setattr = hfs_inode_setattr, 678 .setattr = hfs_inode_setattr,
683 .setxattr = hfs_setxattr, 679 .setxattr = hfs_setxattr,
684 .getxattr = hfs_getxattr, 680 .getxattr = hfs_getxattr,
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index b7ec224910c..1563d5ce576 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -236,10 +236,10 @@ out:
236 * hfs_mdb_commit() 236 * hfs_mdb_commit()
237 * 237 *
238 * Description: 238 * Description:
239 * This updates the MDB on disk. 239 * This updates the MDB on disk (look also at hfs_write_super()).
240 * It does not check, if the superblock has been modified, or 240 * It does not check, if the superblock has been modified, or
241 * if the filesystem has been mounted read-only. It is mainly 241 * if the filesystem has been mounted read-only. It is mainly
242 * called by hfs_sync_fs() and flush_mdb(). 242 * called by hfs_write_super() and hfs_btree_extend().
243 * Input Variable(s): 243 * Input Variable(s):
244 * struct hfs_mdb *mdb: Pointer to the hfs MDB 244 * struct hfs_mdb *mdb: Pointer to the hfs MDB
245 * int backup; 245 * int backup;
@@ -260,10 +260,6 @@ 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);
267 if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) { 263 if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) {
268 /* These parameters may have been modified, so write them back */ 264 /* These parameters may have been modified, so write them back */
269 mdb->drLsMod = hfs_mtime(); 265 mdb->drLsMod = hfs_mtime();
@@ -287,13 +283,9 @@ void hfs_mdb_commit(struct super_block *sb)
287 &mdb->drXTFlSize, NULL); 283 &mdb->drXTFlSize, NULL);
288 hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec, 284 hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec,
289 &mdb->drCTFlSize, NULL); 285 &mdb->drCTFlSize, NULL);
290
291 lock_buffer(HFS_SB(sb)->alt_mdb_bh);
292 memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE); 286 memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE);
293 HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT); 287 HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT);
294 HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT); 288 HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT);
295 unlock_buffer(HFS_SB(sb)->alt_mdb_bh);
296
297 mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh); 289 mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh);
298 sync_dirty_buffer(HFS_SB(sb)->alt_mdb_bh); 290 sync_dirty_buffer(HFS_SB(sb)->alt_mdb_bh);
299 } 291 }
@@ -316,11 +308,7 @@ void hfs_mdb_commit(struct super_block *sb)
316 break; 308 break;
317 } 309 }
318 len = min((int)sb->s_blocksize - off, size); 310 len = min((int)sb->s_blocksize - off, size);
319
320 lock_buffer(bh);
321 memcpy(bh->b_data + off, ptr, len); 311 memcpy(bh->b_data + off, ptr, len);
322 unlock_buffer(bh);
323
324 mark_buffer_dirty(bh); 312 mark_buffer_dirty(bh);
325 brelse(bh); 313 brelse(bh);
326 block++; 314 block++;
@@ -329,7 +317,6 @@ void hfs_mdb_commit(struct super_block *sb)
329 size -= len; 317 size -= len;
330 } 318 }
331 } 319 }
332 unlock_buffer(HFS_SB(sb)->mdb_bh);
333} 320}
334 321
335void hfs_mdb_close(struct super_block *sb) 322void hfs_mdb_close(struct super_block *sb)
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index e93ddaadfd1..1b55f704fb2 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -29,9 +29,43 @@ 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
32static int hfs_sync_fs(struct super_block *sb, int wait) 62static int hfs_sync_fs(struct super_block *sb, int wait)
33{ 63{
64 lock_super(sb);
34 hfs_mdb_commit(sb); 65 hfs_mdb_commit(sb);
66 sb->s_dirt = 0;
67 unlock_super(sb);
68
35 return 0; 69 return 0;
36} 70}
37 71
@@ -44,44 +78,13 @@ static int hfs_sync_fs(struct super_block *sb, int wait)
44 */ 78 */
45static void hfs_put_super(struct super_block *sb) 79static void hfs_put_super(struct super_block *sb)
46{ 80{
47 cancel_delayed_work_sync(&HFS_SB(sb)->mdb_work); 81 if (sb->s_dirt)
82 hfs_write_super(sb);
48 hfs_mdb_close(sb); 83 hfs_mdb_close(sb);
49 /* release the MDB's resources */ 84 /* release the MDB's resources */
50 hfs_mdb_put(sb); 85 hfs_mdb_put(sb);
51} 86}
52 87
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
85/* 88/*
86 * hfs_statfs() 89 * hfs_statfs()
87 * 90 *
@@ -130,17 +133,15 @@ static int hfs_remount(struct super_block *sb, int *flags, char *data)
130 return 0; 133 return 0;
131} 134}
132 135
133static int hfs_show_options(struct seq_file *seq, struct dentry *root) 136static int hfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
134{ 137{
135 struct hfs_sb_info *sbi = HFS_SB(root->d_sb); 138 struct hfs_sb_info *sbi = HFS_SB(mnt->mnt_sb);
136 139
137 if (sbi->s_creator != cpu_to_be32(0x3f3f3f3f)) 140 if (sbi->s_creator != cpu_to_be32(0x3f3f3f3f))
138 seq_printf(seq, ",creator=%.4s", (char *)&sbi->s_creator); 141 seq_printf(seq, ",creator=%.4s", (char *)&sbi->s_creator);
139 if (sbi->s_type != cpu_to_be32(0x3f3f3f3f)) 142 if (sbi->s_type != cpu_to_be32(0x3f3f3f3f))
140 seq_printf(seq, ",type=%.4s", (char *)&sbi->s_type); 143 seq_printf(seq, ",type=%.4s", (char *)&sbi->s_type);
141 seq_printf(seq, ",uid=%u,gid=%u", 144 seq_printf(seq, ",uid=%u,gid=%u", sbi->s_uid, sbi->s_gid);
142 from_kuid_munged(&init_user_ns, sbi->s_uid),
143 from_kgid_munged(&init_user_ns, sbi->s_gid));
144 if (sbi->s_file_umask != 0133) 145 if (sbi->s_file_umask != 0133)
145 seq_printf(seq, ",file_umask=%o", sbi->s_file_umask); 146 seq_printf(seq, ",file_umask=%o", sbi->s_file_umask);
146 if (sbi->s_dir_umask != 0022) 147 if (sbi->s_dir_umask != 0022)
@@ -169,6 +170,7 @@ static struct inode *hfs_alloc_inode(struct super_block *sb)
169static void hfs_i_callback(struct rcu_head *head) 170static void hfs_i_callback(struct rcu_head *head)
170{ 171{
171 struct inode *inode = container_of(head, struct inode, i_rcu); 172 struct inode *inode = container_of(head, struct inode, i_rcu);
173 INIT_LIST_HEAD(&inode->i_dentry);
172 kmem_cache_free(hfs_inode_cachep, HFS_I(inode)); 174 kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
173} 175}
174 176
@@ -183,6 +185,7 @@ static const struct super_operations hfs_super_operations = {
183 .write_inode = hfs_write_inode, 185 .write_inode = hfs_write_inode,
184 .evict_inode = hfs_evict_inode, 186 .evict_inode = hfs_evict_inode,
185 .put_super = hfs_put_super, 187 .put_super = hfs_put_super,
188 .write_super = hfs_write_super,
186 .sync_fs = hfs_sync_fs, 189 .sync_fs = hfs_sync_fs,
187 .statfs = hfs_statfs, 190 .statfs = hfs_statfs,
188 .remount_fs = hfs_remount, 191 .remount_fs = hfs_remount,
@@ -256,22 +259,14 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
256 printk(KERN_ERR "hfs: uid requires an argument\n"); 259 printk(KERN_ERR "hfs: uid requires an argument\n");
257 return 0; 260 return 0;
258 } 261 }
259 hsb->s_uid = make_kuid(current_user_ns(), (uid_t)tmp); 262 hsb->s_uid = (uid_t)tmp;
260 if (!uid_valid(hsb->s_uid)) {
261 printk(KERN_ERR "hfs: invalid uid %d\n", tmp);
262 return 0;
263 }
264 break; 263 break;
265 case opt_gid: 264 case opt_gid:
266 if (match_int(&args[0], &tmp)) { 265 if (match_int(&args[0], &tmp)) {
267 printk(KERN_ERR "hfs: gid requires an argument\n"); 266 printk(KERN_ERR "hfs: gid requires an argument\n");
268 return 0; 267 return 0;
269 } 268 }
270 hsb->s_gid = make_kgid(current_user_ns(), (gid_t)tmp); 269 hsb->s_gid = (gid_t)tmp;
271 if (!gid_valid(hsb->s_gid)) {
272 printk(KERN_ERR "hfs: invalid gid %d\n", tmp);
273 return 0;
274 }
275 break; 270 break;
276 case opt_umask: 271 case opt_umask:
277 if (match_octal(&args[0], &tmp)) { 272 if (match_octal(&args[0], &tmp)) {
@@ -393,10 +388,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
393 if (!sbi) 388 if (!sbi)
394 return -ENOMEM; 389 return -ENOMEM;
395 390
396 sbi->sb = sb;
397 sb->s_fs_info = sbi; 391 sb->s_fs_info = sbi;
398 spin_lock_init(&sbi->work_lock);
399 INIT_DELAYED_WORK(&sbi->mdb_work, flush_mdb);
400 392
401 res = -EINVAL; 393 res = -EINVAL;
402 if (!parse_options((char *)data, sbi)) { 394 if (!parse_options((char *)data, sbi)) {
@@ -439,13 +431,15 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
439 431
440 sb->s_d_op = &hfs_dentry_operations; 432 sb->s_d_op = &hfs_dentry_operations;
441 res = -ENOMEM; 433 res = -ENOMEM;
442 sb->s_root = d_make_root(root_inode); 434 sb->s_root = d_alloc_root(root_inode);
443 if (!sb->s_root) 435 if (!sb->s_root)
444 goto bail_no_root; 436 goto bail_iput;
445 437
446 /* everything's okay */ 438 /* everything's okay */
447 return 0; 439 return 0;
448 440
441bail_iput:
442 iput(root_inode);
449bail_no_root: 443bail_no_root:
450 printk(KERN_ERR "hfs: get root inode failed.\n"); 444 printk(KERN_ERR "hfs: get root inode failed.\n");
451bail: 445bail:
@@ -492,12 +486,6 @@ static int __init init_hfs_fs(void)
492static void __exit exit_hfs_fs(void) 486static void __exit exit_hfs_fs(void)
493{ 487{
494 unregister_filesystem(&hfs_fs_type); 488 unregister_filesystem(&hfs_fs_type);
495
496 /*
497 * Make sure all delayed rcu free inodes are flushed before we
498 * destroy cache.
499 */
500 rcu_barrier();
501 kmem_cache_destroy(hfs_inode_cachep); 489 kmem_cache_destroy(hfs_inode_cachep);
502} 490}
503 491
diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c
index 91b91fd3a90..19cf291eb91 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, unsigned int flags) 16static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
17{ 17{
18 struct inode *inode; 18 struct inode *inode;
19 int diff; 19 int diff;
20 20
21 if (flags & LOOKUP_RCU) 21 if (nd->flags & LOOKUP_RCU)
22 return -ECHILD; 22 return -ECHILD;
23 23
24 inode = dentry->d_inode; 24 inode = dentry->d_inode;