Blame view
fs/hfsplus/super.c
16 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 |
/* * linux/fs/hfsplus/super.c * * Copyright (C) 2001 * Brad Boyer (flar@allandria.com) * (C) 2003 Ardis Technologies <roman@ardistech.com> * */ |
1da177e4c Linux-2.6.12-rc2 |
9 10 11 |
#include <linux/module.h> #include <linux/init.h> #include <linux/pagemap.h> |
34a2d313c hfsplus: flush di... |
12 |
#include <linux/blkdev.h> |
1da177e4c Linux-2.6.12-rc2 |
13 |
#include <linux/fs.h> |
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
15 16 17 18 19 20 21 |
#include <linux/vfs.h> #include <linux/nls.h> static struct inode *hfsplus_alloc_inode(struct super_block *sb); static void hfsplus_destroy_inode(struct inode *inode); #include "hfsplus_fs.h" |
fc4fff821 hfsplus: clean up... |
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
static int hfsplus_system_read_inode(struct inode *inode) { struct hfsplus_vh *vhdr = HFSPLUS_SB(inode->i_sb)->s_vhdr; switch (inode->i_ino) { case HFSPLUS_EXT_CNID: hfsplus_inode_read_fork(inode, &vhdr->ext_file); inode->i_mapping->a_ops = &hfsplus_btree_aops; break; case HFSPLUS_CAT_CNID: hfsplus_inode_read_fork(inode, &vhdr->cat_file); inode->i_mapping->a_ops = &hfsplus_btree_aops; break; case HFSPLUS_ALLOC_CNID: hfsplus_inode_read_fork(inode, &vhdr->alloc_file); inode->i_mapping->a_ops = &hfsplus_aops; break; case HFSPLUS_START_CNID: hfsplus_inode_read_fork(inode, &vhdr->start_file); break; case HFSPLUS_ATTR_CNID: hfsplus_inode_read_fork(inode, &vhdr->attr_file); inode->i_mapping->a_ops = &hfsplus_btree_aops; break; default: return -EIO; } return 0; } |
635253915 iget: stop HFSPLU... |
52 |
struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) |
1da177e4c Linux-2.6.12-rc2 |
53 54 |
{ struct hfs_find_data fd; |
635253915 iget: stop HFSPLU... |
55 |
struct inode *inode; |
fc4fff821 hfsplus: clean up... |
56 |
int err; |
635253915 iget: stop HFSPLU... |
57 58 59 60 61 62 |
inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; |
1da177e4c Linux-2.6.12-rc2 |
63 |
|
6af502de2 hfsplus: fix HFSP... |
64 65 66 |
INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list); mutex_init(&HFSPLUS_I(inode)->extents_lock); HFSPLUS_I(inode)->flags = 0; |
b33b7921d hfsplus: split up... |
67 |
HFSPLUS_I(inode)->extent_state = 0; |
6af502de2 hfsplus: fix HFSP... |
68 69 |
HFSPLUS_I(inode)->rsrc_inode = NULL; atomic_set(&HFSPLUS_I(inode)->opencnt, 0); |
1da177e4c Linux-2.6.12-rc2 |
70 |
|
fc4fff821 hfsplus: clean up... |
71 72 |
if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || inode->i_ino == HFSPLUS_ROOT_CNID) { |
5bd9d99d1 hfsplus: add erro... |
73 74 75 76 77 78 79 |
err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); if (!err) { err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); if (!err) err = hfsplus_cat_read_inode(inode, &fd); hfs_find_exit(&fd); } |
fc4fff821 hfsplus: clean up... |
80 81 |
} else { err = hfsplus_system_read_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
82 |
} |
fc4fff821 hfsplus: clean up... |
83 84 85 86 |
if (err) { iget_failed(inode); return ERR_PTR(err); |
1da177e4c Linux-2.6.12-rc2 |
87 |
} |
635253915 iget: stop HFSPLU... |
88 89 |
unlock_new_inode(inode); return inode; |
1da177e4c Linux-2.6.12-rc2 |
90 |
} |
b5080f77e hfsplus: clean up... |
91 |
static int hfsplus_system_write_inode(struct inode *inode) |
1da177e4c Linux-2.6.12-rc2 |
92 |
{ |
dd73a01a3 hfsplus: fix HFSP... |
93 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); |
b5080f77e hfsplus: clean up... |
94 95 96 |
struct hfsplus_vh *vhdr = sbi->s_vhdr; struct hfsplus_fork_raw *fork; struct hfs_btree *tree = NULL; |
1da177e4c Linux-2.6.12-rc2 |
97 |
|
1da177e4c Linux-2.6.12-rc2 |
98 |
switch (inode->i_ino) { |
1da177e4c Linux-2.6.12-rc2 |
99 |
case HFSPLUS_EXT_CNID: |
b5080f77e hfsplus: clean up... |
100 101 |
fork = &vhdr->ext_file; tree = sbi->ext_tree; |
1da177e4c Linux-2.6.12-rc2 |
102 103 |
break; case HFSPLUS_CAT_CNID: |
b5080f77e hfsplus: clean up... |
104 105 |
fork = &vhdr->cat_file; tree = sbi->cat_tree; |
1da177e4c Linux-2.6.12-rc2 |
106 107 |
break; case HFSPLUS_ALLOC_CNID: |
b5080f77e hfsplus: clean up... |
108 |
fork = &vhdr->alloc_file; |
1da177e4c Linux-2.6.12-rc2 |
109 110 |
break; case HFSPLUS_START_CNID: |
b5080f77e hfsplus: clean up... |
111 |
fork = &vhdr->start_file; |
1da177e4c Linux-2.6.12-rc2 |
112 113 |
break; case HFSPLUS_ATTR_CNID: |
b5080f77e hfsplus: clean up... |
114 115 116 117 118 119 120 |
fork = &vhdr->attr_file; tree = sbi->attr_tree; default: return -EIO; } if (fork->total_size != cpu_to_be64(inode->i_size)) { |
84adede31 hfsplus: use atom... |
121 |
set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); |
b5080f77e hfsplus: clean up... |
122 |
inode->i_sb->s_dirt = 1; |
1da177e4c Linux-2.6.12-rc2 |
123 |
} |
b5080f77e hfsplus: clean up... |
124 125 126 127 128 129 130 131 132 |
hfsplus_inode_write_fork(inode, fork); if (tree) hfs_btree_write(tree); return 0; } static int hfsplus_write_inode(struct inode *inode, struct writeback_control *wbc) { |
dd7f3d545 hfsplus: Add erro... |
133 |
int err; |
b5080f77e hfsplus: clean up... |
134 135 |
dprint(DBG_INODE, "hfsplus_write_inode: %lu ", inode->i_ino); |
dd7f3d545 hfsplus: Add erro... |
136 137 138 |
err = hfsplus_ext_write_extent(inode); if (err) return err; |
b5080f77e hfsplus: clean up... |
139 140 141 142 143 144 |
if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || inode->i_ino == HFSPLUS_ROOT_CNID) return hfsplus_cat_write_inode(inode); else return hfsplus_system_write_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
145 |
} |
b57922d97 convert remaining... |
146 |
static void hfsplus_evict_inode(struct inode *inode) |
1da177e4c Linux-2.6.12-rc2 |
147 |
{ |
b57922d97 convert remaining... |
148 149 150 151 |
dprint(DBG_INODE, "hfsplus_evict_inode: %lu ", inode->i_ino); truncate_inode_pages(&inode->i_data, 0); end_writeback(inode); |
1da177e4c Linux-2.6.12-rc2 |
152 |
if (HFSPLUS_IS_RSRC(inode)) { |
6af502de2 hfsplus: fix HFSP... |
153 154 |
HFSPLUS_I(HFSPLUS_I(inode)->rsrc_inode)->rsrc_inode = NULL; iput(HFSPLUS_I(inode)->rsrc_inode); |
1da177e4c Linux-2.6.12-rc2 |
155 |
} |
1da177e4c Linux-2.6.12-rc2 |
156 |
} |
b5fc510c4 get rid of file_f... |
157 |
int hfsplus_sync_fs(struct super_block *sb, int wait) |
1da177e4c Linux-2.6.12-rc2 |
158 |
{ |
dd73a01a3 hfsplus: fix HFSP... |
159 160 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); struct hfsplus_vh *vhdr = sbi->s_vhdr; |
52399b171 hfsplus: use raw ... |
161 162 |
int write_backup = 0; int error, error2; |
1da177e4c Linux-2.6.12-rc2 |
163 |
|
f02e26f8d hfsplus: avoid us... |
164 165 |
if (!wait) return 0; |
1da177e4c Linux-2.6.12-rc2 |
166 167 168 |
dprint(DBG_SUPER, "hfsplus_write_super "); |
ebc1ac164 ->write_super loc... |
169 |
|
1da177e4c Linux-2.6.12-rc2 |
170 |
sb->s_dirt = 0; |
1da177e4c Linux-2.6.12-rc2 |
171 |
|
7dc4f0011 hfsplus: make sur... |
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
/* * Explicitly write out the special metadata inodes. * * While these special inodes are marked as hashed and written * out peridocically by the flusher threads we redirty them * during writeout of normal inodes, and thus the life lock * prevents us from getting the latest state to disk. */ error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping); error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping); if (!error) error = error2; error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping); if (!error) error = error2; |
52399b171 hfsplus: use raw ... |
187 188 |
mutex_lock(&sbi->vh_mutex); mutex_lock(&sbi->alloc_mutex); |
dd73a01a3 hfsplus: fix HFSP... |
189 |
vhdr->free_blocks = cpu_to_be32(sbi->free_blocks); |
dd73a01a3 hfsplus: fix HFSP... |
190 191 192 |
vhdr->next_cnid = cpu_to_be32(sbi->next_cnid); vhdr->folder_count = cpu_to_be32(sbi->folder_count); vhdr->file_count = cpu_to_be32(sbi->file_count); |
1da177e4c Linux-2.6.12-rc2 |
193 |
|
84adede31 hfsplus: use atom... |
194 |
if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) { |
52399b171 hfsplus: use raw ... |
195 196 |
memcpy(sbi->s_backup_vhdr, sbi->s_vhdr, sizeof(*sbi->s_vhdr)); write_backup = 1; |
1da177e4c Linux-2.6.12-rc2 |
197 |
} |
52399b171 hfsplus: use raw ... |
198 |
|
6596528e3 hfsplus: ensure b... |
199 |
error2 = hfsplus_submit_bio(sb, |
52399b171 hfsplus: use raw ... |
200 |
sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, |
6596528e3 hfsplus: ensure b... |
201 |
sbi->s_vhdr_buf, NULL, WRITE_SYNC); |
7dc4f0011 hfsplus: make sur... |
202 203 |
if (!error) error = error2; |
52399b171 hfsplus: use raw ... |
204 205 |
if (!write_backup) goto out; |
6596528e3 hfsplus: ensure b... |
206 |
error2 = hfsplus_submit_bio(sb, |
52399b171 hfsplus: use raw ... |
207 |
sbi->part_start + sbi->sect_count - 2, |
6596528e3 hfsplus: ensure b... |
208 |
sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC); |
52399b171 hfsplus: use raw ... |
209 210 211 |
if (!error) error2 = error; out: |
dd73a01a3 hfsplus: fix HFSP... |
212 |
mutex_unlock(&sbi->alloc_mutex); |
7ac9fb9c2 hfsplus: add per-... |
213 |
mutex_unlock(&sbi->vh_mutex); |
34a2d313c hfsplus: flush di... |
214 215 216 |
if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags)) blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL); |
52399b171 hfsplus: use raw ... |
217 |
return error; |
7fbc6df0e hfsplus: add ->sy... |
218 219 220 221 222 223 224 225 |
} static void hfsplus_write_super(struct super_block *sb) { if (!(sb->s_flags & MS_RDONLY)) hfsplus_sync_fs(sb, 1); else sb->s_dirt = 0; |
1da177e4c Linux-2.6.12-rc2 |
226 227 228 229 |
} static void hfsplus_put_super(struct super_block *sb) { |
dd73a01a3 hfsplus: fix HFSP... |
230 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); |
1da177e4c Linux-2.6.12-rc2 |
231 232 |
dprint(DBG_SUPER, "hfsplus_put_super "); |
dd73a01a3 hfsplus: fix HFSP... |
233 |
|
945b09201 [PATCH] hfs, hfsp... |
234 235 |
if (!sb->s_fs_info) return; |
6cfd01484 push BKL down int... |
236 |
|
dd73a01a3 hfsplus: fix HFSP... |
237 238 |
if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { struct hfsplus_vh *vhdr = sbi->s_vhdr; |
1da177e4c Linux-2.6.12-rc2 |
239 240 241 242 |
vhdr->modify_date = hfsp_now2mt(); vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT); vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT); |
3b5ce8ae3 hfsplus: always u... |
243 244 |
hfsplus_sync_fs(sb, 1); |
1da177e4c Linux-2.6.12-rc2 |
245 |
} |
dd73a01a3 hfsplus: fix HFSP... |
246 247 248 249 |
hfs_btree_close(sbi->cat_tree); hfs_btree_close(sbi->ext_tree); iput(sbi->alloc_file); iput(sbi->hidden_dir); |
6596528e3 hfsplus: ensure b... |
250 251 |
kfree(sbi->s_vhdr_buf); kfree(sbi->s_backup_vhdr_buf); |
dd73a01a3 hfsplus: fix HFSP... |
252 |
unload_nls(sbi->nls); |
945b09201 [PATCH] hfs, hfsp... |
253 254 |
kfree(sb->s_fs_info); sb->s_fs_info = NULL; |
1da177e4c Linux-2.6.12-rc2 |
255 |
} |
726c33422 [PATCH] VFS: Perm... |
256 |
static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) |
1da177e4c Linux-2.6.12-rc2 |
257 |
{ |
726c33422 [PATCH] VFS: Perm... |
258 |
struct super_block *sb = dentry->d_sb; |
dd73a01a3 hfsplus: fix HFSP... |
259 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); |
25564dd86 fs/hfsplus: retur... |
260 |
u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
726c33422 [PATCH] VFS: Perm... |
261 |
|
1da177e4c Linux-2.6.12-rc2 |
262 263 |
buf->f_type = HFSPLUS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; |
dd73a01a3 hfsplus: fix HFSP... |
264 265 |
buf->f_blocks = sbi->total_blocks << sbi->fs_shift; buf->f_bfree = sbi->free_blocks << sbi->fs_shift; |
1da177e4c Linux-2.6.12-rc2 |
266 267 |
buf->f_bavail = buf->f_bfree; buf->f_files = 0xFFFFFFFF; |
dd73a01a3 hfsplus: fix HFSP... |
268 |
buf->f_ffree = 0xFFFFFFFF - sbi->next_cnid; |
25564dd86 fs/hfsplus: retur... |
269 270 |
buf->f_fsid.val[0] = (u32)id; buf->f_fsid.val[1] = (u32)(id >> 32); |
1da177e4c Linux-2.6.12-rc2 |
271 272 273 274 275 276 277 278 279 280 |
buf->f_namelen = HFSPLUS_MAX_STRLEN; return 0; } static int hfsplus_remount(struct super_block *sb, int *flags, char *data) { if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) return 0; if (!(*flags & MS_RDONLY)) { |
dd73a01a3 hfsplus: fix HFSP... |
281 |
struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr; |
6f80dfe55 hfsplus: fix opti... |
282 |
int force = 0; |
b0b623c3b [PATCH] hfsplus: ... |
283 |
|
6f80dfe55 hfsplus: fix opti... |
284 |
if (!hfsplus_parse_options_remount(data, &force)) |
b0b623c3b [PATCH] hfsplus: ... |
285 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
286 287 |
if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { |
2753cc281 hfsplus: over 80 ... |
288 289 290 291 292 |
printk(KERN_WARNING "hfs: filesystem was " "not cleanly unmounted, " "running fsck.hfsplus is recommended. " "leaving read-only. "); |
1da177e4c Linux-2.6.12-rc2 |
293 294 |
sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; |
6f80dfe55 hfsplus: fix opti... |
295 |
} else if (force) { |
b0b623c3b [PATCH] hfsplus: ... |
296 |
/* nothing */ |
2753cc281 hfsplus: over 80 ... |
297 298 299 300 301 |
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { printk(KERN_WARNING "hfs: filesystem is marked locked, " "leaving read-only. "); |
1da177e4c Linux-2.6.12-rc2 |
302 303 |
sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; |
2753cc281 hfsplus: over 80 ... |
304 305 306 307 308 309 |
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { printk(KERN_WARNING "hfs: filesystem is " "marked journaled, " "leaving read-only. "); |
b0b623c3b [PATCH] hfsplus: ... |
310 311 |
sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; |
1da177e4c Linux-2.6.12-rc2 |
312 313 314 315 |
} } return 0; } |
ee9b6d61a [PATCH] Mark stru... |
316 |
static const struct super_operations hfsplus_sops = { |
1da177e4c Linux-2.6.12-rc2 |
317 318 |
.alloc_inode = hfsplus_alloc_inode, .destroy_inode = hfsplus_destroy_inode, |
1da177e4c Linux-2.6.12-rc2 |
319 |
.write_inode = hfsplus_write_inode, |
b57922d97 convert remaining... |
320 |
.evict_inode = hfsplus_evict_inode, |
1da177e4c Linux-2.6.12-rc2 |
321 322 |
.put_super = hfsplus_put_super, .write_super = hfsplus_write_super, |
7fbc6df0e hfsplus: add ->sy... |
323 |
.sync_fs = hfsplus_sync_fs, |
1da177e4c Linux-2.6.12-rc2 |
324 325 |
.statfs = hfsplus_statfs, .remount_fs = hfsplus_remount, |
717dd80e9 [PATCH] hfs: show... |
326 |
.show_options = hfsplus_show_options, |
1da177e4c Linux-2.6.12-rc2 |
327 328 329 330 331 332 333 334 |
}; static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) { struct hfsplus_vh *vhdr; struct hfsplus_sb_info *sbi; hfsplus_cat_entry entry; struct hfs_find_data fd; |
635253915 iget: stop HFSPLU... |
335 |
struct inode *root, *inode; |
1da177e4c Linux-2.6.12-rc2 |
336 337 |
struct qstr str; struct nls_table *nls = NULL; |
f1fcd9f0e hfsplus: fix file... |
338 |
u64 last_fs_block, last_fs_page; |
c5b8d0bce hfsplus: fix fail... |
339 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
340 |
|
c5b8d0bce hfsplus: fix fail... |
341 |
err = -EINVAL; |
a5001a278 HFSPlus: change k... |
342 |
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
343 |
if (!sbi) |
c5b8d0bce hfsplus: fix fail... |
344 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
345 |
|
1da177e4c Linux-2.6.12-rc2 |
346 |
sb->s_fs_info = sbi; |
40bf48afe hfsplus: introduc... |
347 |
mutex_init(&sbi->alloc_mutex); |
7ac9fb9c2 hfsplus: add per-... |
348 |
mutex_init(&sbi->vh_mutex); |
717dd80e9 [PATCH] hfs: show... |
349 |
hfsplus_fill_defaults(sbi); |
c5b8d0bce hfsplus: fix fail... |
350 351 |
err = -EINVAL; |
717dd80e9 [PATCH] hfs: show... |
352 |
if (!hfsplus_parse_options(data, sbi)) { |
634725a92 [PATCH] hfs: clea... |
353 354 |
printk(KERN_ERR "hfs: unable to parse mount options "); |
c5b8d0bce hfsplus: fix fail... |
355 |
goto out_unload_nls; |
1da177e4c Linux-2.6.12-rc2 |
356 357 358 359 360 |
} /* temporarily use utf8 to correctly find the hidden dir below */ nls = sbi->nls; sbi->nls = load_nls("utf8"); |
bd6a59b22 [PATCH] hfsplus o... |
361 |
if (!sbi->nls) { |
634725a92 [PATCH] hfs: clea... |
362 363 |
printk(KERN_ERR "hfs: unable to load nls for utf8 "); |
c5b8d0bce hfsplus: fix fail... |
364 |
goto out_unload_nls; |
1da177e4c Linux-2.6.12-rc2 |
365 366 367 368 369 |
} /* Grab the volume header */ if (hfsplus_read_wrapper(sb)) { if (!silent) |
634725a92 [PATCH] hfs: clea... |
370 371 |
printk(KERN_WARNING "hfs: unable to find HFS+ superblock "); |
c5b8d0bce hfsplus: fix fail... |
372 |
goto out_unload_nls; |
1da177e4c Linux-2.6.12-rc2 |
373 |
} |
dd73a01a3 hfsplus: fix HFSP... |
374 |
vhdr = sbi->s_vhdr; |
1da177e4c Linux-2.6.12-rc2 |
375 376 |
/* Copy parts of the volume header into the superblock */ |
2179d372d [PATCH] hfs: add ... |
377 378 379 |
sb->s_magic = HFSPLUS_VOLHEAD_SIG; if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION || be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) { |
634725a92 [PATCH] hfs: clea... |
380 381 |
printk(KERN_ERR "hfs: wrong filesystem version "); |
c5b8d0bce hfsplus: fix fail... |
382 |
goto out_free_vhdr; |
1da177e4c Linux-2.6.12-rc2 |
383 |
} |
dd73a01a3 hfsplus: fix HFSP... |
384 385 |
sbi->total_blocks = be32_to_cpu(vhdr->total_blocks); sbi->free_blocks = be32_to_cpu(vhdr->free_blocks); |
dd73a01a3 hfsplus: fix HFSP... |
386 387 388 389 390 391 392 393 394 395 396 |
sbi->next_cnid = be32_to_cpu(vhdr->next_cnid); sbi->file_count = be32_to_cpu(vhdr->file_count); sbi->folder_count = be32_to_cpu(vhdr->folder_count); sbi->data_clump_blocks = be32_to_cpu(vhdr->data_clump_sz) >> sbi->alloc_blksz_shift; if (!sbi->data_clump_blocks) sbi->data_clump_blocks = 1; sbi->rsrc_clump_blocks = be32_to_cpu(vhdr->rsrc_clump_sz) >> sbi->alloc_blksz_shift; if (!sbi->rsrc_clump_blocks) sbi->rsrc_clump_blocks = 1; |
1da177e4c Linux-2.6.12-rc2 |
397 |
|
f1fcd9f0e hfsplus: fix file... |
398 399 400 401 402 403 404 |
err = -EFBIG; last_fs_block = sbi->total_blocks - 1; last_fs_page = (last_fs_block << sbi->alloc_blksz_shift) >> PAGE_CACHE_SHIFT; if ((last_fs_block > (sector_t)(~0ULL) >> (sbi->alloc_blksz_shift - 9)) || (last_fs_page > (pgoff_t)(~0ULL))) { |
c6d5f5fa6 hfsplus: lift the... |
405 406 407 408 |
printk(KERN_ERR "hfs: filesystem size too large. "); goto out_free_vhdr; } |
1da177e4c Linux-2.6.12-rc2 |
409 410 411 412 413 |
/* Set up operations so we can load metadata */ sb->s_op = &hfsplus_sops; sb->s_maxbytes = MAX_LFS_FILESIZE; if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { |
2753cc281 hfsplus: over 80 ... |
414 415 416 417 418 |
printk(KERN_WARNING "hfs: Filesystem was " "not cleanly unmounted, " "running fsck.hfsplus is recommended. " "mounting read-only. "); |
1da177e4c Linux-2.6.12-rc2 |
419 |
sb->s_flags |= MS_RDONLY; |
84adede31 hfsplus: use atom... |
420 |
} else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) { |
b0b623c3b [PATCH] hfsplus: ... |
421 |
/* nothing */ |
1da177e4c Linux-2.6.12-rc2 |
422 |
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
634725a92 [PATCH] hfs: clea... |
423 424 |
printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only. "); |
1da177e4c Linux-2.6.12-rc2 |
425 |
sb->s_flags |= MS_RDONLY; |
2753cc281 hfsplus: over 80 ... |
426 427 428 429 430 431 432 |
} else if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) && !(sb->s_flags & MS_RDONLY)) { printk(KERN_WARNING "hfs: write access to " "a journaled filesystem is not supported, " "use the force option at your own risk, " "mounting read-only. "); |
b0b623c3b [PATCH] hfsplus: ... |
433 |
sb->s_flags |= MS_RDONLY; |
1da177e4c Linux-2.6.12-rc2 |
434 |
} |
c6d5f5fa6 hfsplus: lift the... |
435 |
err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
436 |
/* Load metadata objects (B*Trees) */ |
dd73a01a3 hfsplus: fix HFSP... |
437 438 |
sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); if (!sbi->ext_tree) { |
634725a92 [PATCH] hfs: clea... |
439 440 |
printk(KERN_ERR "hfs: failed to load extents file "); |
c5b8d0bce hfsplus: fix fail... |
441 |
goto out_free_vhdr; |
1da177e4c Linux-2.6.12-rc2 |
442 |
} |
dd73a01a3 hfsplus: fix HFSP... |
443 444 |
sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); if (!sbi->cat_tree) { |
634725a92 [PATCH] hfs: clea... |
445 446 |
printk(KERN_ERR "hfs: failed to load catalog file "); |
c5b8d0bce hfsplus: fix fail... |
447 |
goto out_close_ext_tree; |
1da177e4c Linux-2.6.12-rc2 |
448 |
} |
635253915 iget: stop HFSPLU... |
449 450 |
inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID); if (IS_ERR(inode)) { |
634725a92 [PATCH] hfs: clea... |
451 452 |
printk(KERN_ERR "hfs: failed to load allocation file "); |
635253915 iget: stop HFSPLU... |
453 |
err = PTR_ERR(inode); |
c5b8d0bce hfsplus: fix fail... |
454 |
goto out_close_cat_tree; |
1da177e4c Linux-2.6.12-rc2 |
455 |
} |
dd73a01a3 hfsplus: fix HFSP... |
456 |
sbi->alloc_file = inode; |
1da177e4c Linux-2.6.12-rc2 |
457 458 |
/* Load the root directory */ |
635253915 iget: stop HFSPLU... |
459 460 461 462 463 |
root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID); if (IS_ERR(root)) { printk(KERN_ERR "hfs: failed to load root directory "); err = PTR_ERR(root); |
c5b8d0bce hfsplus: fix fail... |
464 |
goto out_put_alloc_file; |
1da177e4c Linux-2.6.12-rc2 |
465 466 467 468 |
} str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; str.name = HFSP_HIDDENDIR_NAME; |
5bd9d99d1 hfsplus: add erro... |
469 470 471 |
err = hfs_find_init(sbi->cat_tree, &fd); if (err) goto out_put_root; |
1da177e4c Linux-2.6.12-rc2 |
472 473 474 475 |
hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { hfs_find_exit(&fd); if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) |
c5b8d0bce hfsplus: fix fail... |
476 |
goto out_put_root; |
635253915 iget: stop HFSPLU... |
477 478 479 |
inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id)); if (IS_ERR(inode)) { err = PTR_ERR(inode); |
c5b8d0bce hfsplus: fix fail... |
480 |
goto out_put_root; |
635253915 iget: stop HFSPLU... |
481 |
} |
dd73a01a3 hfsplus: fix HFSP... |
482 |
sbi->hidden_dir = inode; |
1da177e4c Linux-2.6.12-rc2 |
483 484 |
} else hfs_find_exit(&fd); |
c5b8d0bce hfsplus: fix fail... |
485 486 487 488 489 490 491 492 493 494 495 |
if (!(sb->s_flags & MS_RDONLY)) { /* * H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused * all three are registered with Apple for our use */ vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION); vhdr->modify_date = hfsp_now2mt(); be32_add_cpu(&vhdr->write_count, 1); vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); hfsplus_sync_fs(sb, 1); |
1da177e4c Linux-2.6.12-rc2 |
496 |
|
c5b8d0bce hfsplus: fix fail... |
497 498 499 |
if (!sbi->hidden_dir) { mutex_lock(&sbi->vh_mutex); sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); |
b3f2a9244 hfsplus: creation... |
500 501 502 503 504 505 506 |
if (!sbi->hidden_dir) { mutex_unlock(&sbi->vh_mutex); err = -ENOMEM; goto out_put_root; } err = hfsplus_create_cat(sbi->hidden_dir->i_ino, root, &str, sbi->hidden_dir); |
c5b8d0bce hfsplus: fix fail... |
507 |
mutex_unlock(&sbi->vh_mutex); |
b3f2a9244 hfsplus: creation... |
508 509 |
if (err) goto out_put_hidden_dir; |
c5b8d0bce hfsplus: fix fail... |
510 511 512 513 |
hfsplus_mark_inode_dirty(sbi->hidden_dir, HFSPLUS_I_CAT_DIRTY); } |
1da177e4c Linux-2.6.12-rc2 |
514 |
} |
c5b8d0bce hfsplus: fix fail... |
515 516 517 518 519 520 521 |
sb->s_d_op = &hfsplus_dentry_operations; sb->s_root = d_alloc_root(root); if (!sb->s_root) { err = -ENOMEM; goto out_put_hidden_dir; } |
1da177e4c Linux-2.6.12-rc2 |
522 523 524 |
unload_nls(sbi->nls); sbi->nls = nls; return 0; |
c5b8d0bce hfsplus: fix fail... |
525 526 527 |
out_put_hidden_dir: iput(sbi->hidden_dir); out_put_root: |
032016a56 hfsplus: Fix doub... |
528 |
iput(root); |
c5b8d0bce hfsplus: fix fail... |
529 530 531 532 533 534 535 |
out_put_alloc_file: iput(sbi->alloc_file); out_close_cat_tree: hfs_btree_close(sbi->cat_tree); out_close_ext_tree: hfs_btree_close(sbi->ext_tree); out_free_vhdr: |
f588c960f hfsplus: Fix kfre... |
536 537 |
kfree(sbi->s_vhdr_buf); kfree(sbi->s_backup_vhdr_buf); |
c5b8d0bce hfsplus: fix fail... |
538 539 |
out_unload_nls: unload_nls(sbi->nls); |
6d729e44a fs: Make unload_n... |
540 |
unload_nls(nls); |
c5b8d0bce hfsplus: fix fail... |
541 542 |
kfree(sbi); out: |
1da177e4c Linux-2.6.12-rc2 |
543 544 545 546 547 548 |
return err; } MODULE_AUTHOR("Brad Boyer"); MODULE_DESCRIPTION("Extended Macintosh Filesystem"); MODULE_LICENSE("GPL"); |
e18b890bb [PATCH] slab: rem... |
549 |
static struct kmem_cache *hfsplus_inode_cachep; |
1da177e4c Linux-2.6.12-rc2 |
550 551 552 553 |
static struct inode *hfsplus_alloc_inode(struct super_block *sb) { struct hfsplus_inode_info *i; |
e94b17660 [PATCH] slab: rem... |
554 |
i = kmem_cache_alloc(hfsplus_inode_cachep, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
555 556 |
return i ? &i->vfs_inode : NULL; } |
fa0d7e3de fs: icache RCU fr... |
557 |
static void hfsplus_i_callback(struct rcu_head *head) |
1da177e4c Linux-2.6.12-rc2 |
558 |
{ |
fa0d7e3de fs: icache RCU fr... |
559 |
struct inode *inode = container_of(head, struct inode, i_rcu); |
6af502de2 hfsplus: fix HFSP... |
560 |
kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode)); |
1da177e4c Linux-2.6.12-rc2 |
561 |
} |
fa0d7e3de fs: icache RCU fr... |
562 563 564 565 |
static void hfsplus_destroy_inode(struct inode *inode) { call_rcu(&inode->i_rcu, hfsplus_i_callback); } |
1da177e4c Linux-2.6.12-rc2 |
566 |
#define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) |
152a08366 new helper: mount... |
567 568 |
static struct dentry *hfsplus_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) |
1da177e4c Linux-2.6.12-rc2 |
569 |
{ |
152a08366 new helper: mount... |
570 |
return mount_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super); |
1da177e4c Linux-2.6.12-rc2 |
571 572 573 574 575 |
} static struct file_system_type hfsplus_fs_type = { .owner = THIS_MODULE, .name = "hfsplus", |
152a08366 new helper: mount... |
576 |
.mount = hfsplus_mount, |
1da177e4c Linux-2.6.12-rc2 |
577 578 579 |
.kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; |
51cc50685 SL*B: drop kmem c... |
580 |
static void hfsplus_init_once(void *p) |
1da177e4c Linux-2.6.12-rc2 |
581 582 |
{ struct hfsplus_inode_info *i = p; |
a35afb830 Remove SLAB_CTOR_... |
583 |
inode_init_once(&i->vfs_inode); |
1da177e4c Linux-2.6.12-rc2 |
584 585 586 587 588 589 590 591 |
} static int __init init_hfsplus_fs(void) { int err; hfsplus_inode_cachep = kmem_cache_create("hfsplus_icache", HFSPLUS_INODE_SIZE, 0, SLAB_HWCACHE_ALIGN, |
20c2df83d mm: Remove slab d... |
592 |
hfsplus_init_once); |
1da177e4c Linux-2.6.12-rc2 |
593 594 595 596 597 598 599 600 601 602 603 |
if (!hfsplus_inode_cachep) return -ENOMEM; err = register_filesystem(&hfsplus_fs_type); if (err) kmem_cache_destroy(hfsplus_inode_cachep); return err; } static void __exit exit_hfsplus_fs(void) { unregister_filesystem(&hfsplus_fs_type); |
1a1d92c10 [PATCH] Really ig... |
604 |
kmem_cache_destroy(hfsplus_inode_cachep); |
1da177e4c Linux-2.6.12-rc2 |
605 606 607 608 |
} module_init(init_hfsplus_fs) module_exit(exit_hfsplus_fs) |