1
Commit Graph

157 Commits

Author SHA1 Message Date
Linus Torvalds
0c21e3aaf6 Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus:
  hfsplus: %L-to-%ll, macro correction, and remove unneeded braces
  hfsplus: spaces/indentation clean-up
  hfsplus: C99 comments clean-up
  hfsplus: over 80 character lines clean-up
  hfsplus: fix an artifact in ioctl flag checking
  hfsplus: flush disk caches in sync and fsync
  hfsplus: optimize fsync
  hfsplus: split up inode flags
  hfsplus: write up fsync for directories
  hfsplus: simplify fsync
  hfsplus: avoid useless work in hfsplus_sync_fs
  hfsplus: make sure sync writes out all metadata
  hfsplus: use raw bio access for partition tables
  hfsplus: use raw bio access for the volume headers
  hfsplus: always use hfsplus_sync_fs to write the volume header
  hfsplus: silence a few debug printks
  hfsplus: fix option parsing during remount

Fix up conflicts due to VFS changes in fs/hfsplus/{hfsplus_fs.h,unicode.c}
2011-01-07 17:16:27 -08:00
Nick Piggin
fb045adb99 fs: dcache reduce branches in lookup path
Reduce some branches and memory accesses in dcache lookup by adding dentry
flags to indicate common d_ops are set, rather than having to check them.
This saves a pointer memory access (dentry->d_op) in common path lookup
situations, and saves another pointer load and branch in cases where we
have d_op but not the particular operation.

Patched with:

git grep -E '[.>]([[:space:]])*d_op([[:space:]])*=' | xargs sed -e 's/\([^\t ]*\)->d_op = \(.*\);/d_set_d_op(\1, \2);/' -e 's/\([^\t ]*\)\.d_op = \(.*\);/d_set_d_op(\&\1, \2);/' -i

Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 17:50:28 +11:00
Nick Piggin
fa0d7e3de6 fs: icache RCU free inodes
RCU free the struct inode. This will allow:

- Subsequent store-free path walking patch. The inode must be consulted for
  permissions when walking, so an RCU inode reference is a must.
- sb_inode_list_lock to be moved inside i_lock because sb list walkers who want
  to take i_lock no longer need to take sb_inode_list_lock to walk the list in
  the first place. This will simplify and optimize locking.
- Could remove some nested trylock loops in dcache code
- Could potentially simplify things a bit in VM land. Do not need to take the
  page lock to follow page->mapping.

The downsides of this is the performance cost of using RCU. In a simple
creat/unlink microbenchmark, performance drops by about 10% due to inability to
reuse cache-hot slab objects. As iterations increase and RCU freeing starts
kicking over, this increases to about 20%.

In cases where inode lifetimes are longer (ie. many inodes may be allocated
during the average life span of a single inode), a lot of this cache reuse is
not applicable, so the regression caused by this patch is smaller.

The cache-hot regression could largely be avoided by using SLAB_DESTROY_BY_RCU,
however this adds some complexity to list walking and store-free path walking,
so I prefer to implement this at a later date, if it is shown to be a win in
real situations. I haven't found a regression in any non-micro benchmark so I
doubt it will be a problem.

Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 17:50:26 +11:00
Nick Piggin
b1e6a015a5 fs: change d_hash for rcu-walk
Change d_hash so it may be called from lock-free RCU lookups. See similar
patch for d_compare for details.

For in-tree filesystems, this is just a mechanical change.

Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 17:50:20 +11:00
Nick Piggin
621e155a35 fs: change d_compare for rcu-walk
Change d_compare so it may be called from lock-free RCU lookups. This
does put significant restrictions on what may be done from the callback,
however there don't seem to have been any problems with in-tree fses.
If some strange use case pops up that _really_ cannot cope with the
rcu-walk rules, we can just add new rcu-unaware callbacks, which would
cause name lookup to drop out of rcu-walk mode.

For in-tree filesystems, this is just a mechanical change.

Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 17:50:19 +11:00
Anton Salikhmetov
b2837fcf49 hfsplus: %L-to-%ll, macro correction, and remove unneeded braces
Clean-up based on checkpatch.pl report against unnecessary braces
(`{' and `}'), non-standard format option %Lu (%llu recommended)
as well as one trailing statement in a macro definition which
should have been on the next line.

Signed-off-by: Anton Salikhmetov <alexo@tuxera.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-12-16 18:08:46 +01:00
Anton Salikhmetov
20b7643d8e hfsplus: spaces/indentation clean-up
Fix incorrect spaces and indentation reported by checkpatch.pl.

Signed-off-by: Anton Salikhmetov <alexo@tuxera.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-12-16 18:08:46 +01:00
Anton Salikhmetov
21f2296a59 hfsplus: C99 comments clean-up
Match coding style restriction against C99 comments where
checkpatch.pl reported errors about their usage.

Signed-off-by: Anton Salikhmetov <alexo@tuxera.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-12-16 18:08:46 +01:00
Anton Salikhmetov
2753cc281c hfsplus: over 80 character lines clean-up
Match coding style line length limitation where checkpatch.pl
reported over-80-character-line warnings.

Signed-off-by: Anton Salikhmetov <alexo@tuxera.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-12-16 18:08:45 +01:00
Anton Salikhmetov
596276c357 hfsplus: fix an artifact in ioctl flag checking
Fix a flag checking artifact in hfsplus_ioctl_getflags() routine
found while doing clean-up against assignments inside `if's.

Signed-off-by: Anton Salikhmetov <alexo@tuxera.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-12-16 18:08:43 +01:00
Christoph Hellwig
34a2d313c5 hfsplus: flush disk caches in sync and fsync
Flush the disk cache in fsync and sync to make sure data actually is
on disk on completion of these system calls.  There is a nobarrier
mount option to disable this behaviour.  It's slightly misnamed now
that barrier actually are gone, but it matches the name used by all
major filesystems.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:38:21 +01:00
Christoph Hellwig
e349470560 hfsplus: optimize fsync
Avoid doing unessecary work in fsync.  Do nothing unless the inode
was marked dirty, and only write the various metadata inodes out if
they contain any dirty state from this inode.  This is archived by
adding three new dirty bits to the hfsplus-specific inode which are
set in the correct places.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:38:15 +01:00
Christoph Hellwig
b33b7921db hfsplus: split up inode flags
Split the flags field in the hfsplus inode into an extent_state
flag that is locked by the extent_lock, and a new flags field
that uses atomic bitops.  The second will grow more flags in the
next patch.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:38:13 +01:00
Christoph Hellwig
eb29d66d4f hfsplus: write up fsync for directories
fsync is supposed to not just work on regular files, but also on
directories.  Fortunately enough hfsplus_file_fsync works just fine
for directories, so we can just wire it up.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:38:10 +01:00
Christoph Hellwig
281469766b hfsplus: simplify fsync
Remove lots of code we don't need from fsync, we just need to call
->write_inode on the inode if it's dirty, for which sync_inode_metadata
is a lot more efficient than write_inode_now, and we need to write
out the various metadata inodes, which we now do explicitly instead
of by calling ->sync_fs.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:38:06 +01:00
Christoph Hellwig
f02e26f8d9 hfsplus: avoid useless work in hfsplus_sync_fs
There is no reason to write out the metadata inodes or volume headers
during a non-blocking sync, as we are almost guaranteed to dirty them
again during the inode writeouts.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:38:02 +01:00
Christoph Hellwig
7dc4f00112 hfsplus: make sure sync writes out all metadata
hfsplus stores all metadata except for the volume headers in special
inodes.  While these are marked hashed and periodically written out
by the flusher threads, we can't rely on that for sync.  For the case
of a data integrity sync the VM has life-lock avoidance code that
avoids writing inodes again that are redirtied during the sync,
which is something that can happen easily for hfsplus.  So make sure
we explicitly write out the metadata inodes at the beginning of
hfsplus_sync_fs.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:37:57 +01:00
Christoph Hellwig
358f26d526 hfsplus: use raw bio access for partition tables
Switch the hfsplus partition table reding for cdroms to use our bio
helpers.  Again we don't rely on any caching in the buffer_heads, and
this gets rid of the last buffer_head use in hfsplus.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:37:51 +01:00
Christoph Hellwig
52399b171d hfsplus: use raw bio access for the volume headers
The hfsplus backup volume header is located two blocks from the end of
the device.  In case of device sizes that are not 4k aligned this means
we can't access it using buffer_heads when using the default 4k block
size.

Switch to using raw bios to read/write all buffer headers.  We were not
relying on any caching behaviour of the buffer heads anyway.  Additionally
always read in the backup volume header during mount to verify that we
can actually read it.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:37:47 +01:00
Christoph Hellwig
3b5ce8ae31 hfsplus: always use hfsplus_sync_fs to write the volume header
Remove opencoded writing of the volume header in hfsplus_fill_super
and hfsplus_put_super and offload it to hfsplus_sync_fs.  In the
put_super case this means we only write the superblock once instead
of twice.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:37:43 +01:00
Christoph Hellwig
6d1bbfc4c0 hfsplus: silence a few debug printks
Turn a few noisy debug printks that show up during xfstests into
complied out debug print statements.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-23 14:37:40 +01:00
Christoph Hellwig
6f80dfe55f hfsplus: fix option parsing during remount
hfsplus only actually uses the force option during remount, but it uses
the full option parser with a fake superblock to do so.  This means remount
will fail if any nls option is set (which happens frequently with older
mount tools), even if it is the same.

Fix this by adding a simpler version of the parser that only parses the force
option for remount.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-11-07 23:01:17 +01:00
Al Viro
152a083666 new helper: mount_bdev()
... and switch of the obvious get_sb_bdev() users to ->mount()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2010-10-29 04:16:13 -04:00
Linus Torvalds
11cc21f5f5 Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus:
  hfsplus: free space correcly for files unlinked while open
  hfsplus: fix double lock typo in ioctl
2010-10-28 09:32:05 -07:00
Christoph Hellwig
85b8fe8cc4 hfsplus: free space correcly for files unlinked while open
hfsplus_delete_inode only truncates away all block allocations if
i_nlink is zero.  Make sure we properly drop the unlink count even
when doing the rename hack for open but unlinked files.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-27 13:45:50 +02:00
Al Viro
7de9c6ee3e new helper: ihold()
Clones an existing reference to inode; caller must already hold one.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2010-10-25 21:26:11 -04:00
Al Viro
756acc2d61 list.h: new helper - hlist_add_fake()
Make node look as if it was on hlist, with hlist_del()
working correctly.  Usable without any locking...

Convert a couple of places where we want to do that to
inode->i_hash.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2010-10-25 21:24:15 -04:00
Dan Carpenter
e50fb58b5b hfsplus: fix double lock typo in ioctl
This was supposed to be a mutex_unlock() instead of a mutex_lock().

Signed-off-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-25 20:39:07 +02:00
Christoph Hellwig
46bf36ecec hfsplus: fix getxattr return value
We need to support -EOPNOTSUPP for attributes that are not supported to
match other filesystems and allow userspace to detect if Posix ACLs
are supported or not.  setxattr already gets this right.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-15 05:45:00 -07:00
Christoph Hellwig
32e39e19cc hfsplus: remove the unused hfsplus_kmap/hfsplus_kunmap helpers
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-14 09:54:43 -04:00
Christoph Hellwig
90e616905a hfsplus: create correct initial catalog entries for device files
Make sure the initial insertation of the catalog entry already contains
the device number by calling init_special_inode early and setting writing
out the dev field of the on-disk permission structure.  The latter is
facilitated by sharing the almost identical hfsplus_set_perms helpers
between initial catalog entry creating and ->write_inode.

Unless we crashed just after mknod this bug was harmless as the inode
is marked dirty at the end of hfsplus_mknod, and hfsplus_write_inode
will update the catalog entry to contain the correct value.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-14 09:54:39 -04:00
Christoph Hellwig
722c55d13e hfsplus: remove superflous rootflags field in hfsplus_inode_info
The rootflags field in hfsplus_inode_info only caches the immutable and
append-only flags in the VFS inode, so we can easily get rid of it.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-14 09:54:33 -04:00
Christoph Hellwig
f6089ff87d hfsplus: fix link corruption
HFS implements hardlink by using indirect catalog entries that refer to a hidden
directly.  The link target is cached in the dev field in the HFS+ specific
inode, which is also used for the device number for device files, and inside
for passing the nlink value of the indirect node from hfsplus_cat_write_inode
to a helper function.  Now if we happen to write out the indirect node while
hfsplus_link is creating the catalog entry we'll get a link pointing to the
linkid of the current nlink value.  This can easily be reproduced by a large
enough loop of local git-clone operations.

Stop abusing the dev field in the HFS+ inode for short term storage by
refactoring the way the permission structure in the catalog entry is
set up, and rename the dev field to linkid to avoid any confusion.

While we're at it also prevent creating hard links to special files, as
the HFS+ dev and linkid share the same space in the on-disk structure.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-14 09:54:28 -04:00
Christoph Hellwig
13571a6977 hfsplus: validate btree flags
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-14 09:54:23 -04:00
Eric Sandeen
9250f92597 hfsplus: handle more on-disk corruptions without oopsing
hfs seems prone to bad things when it encounters on disk corruption.  Many
values are read from disk, and used as lengths to memcpy, as an example.
This patch fixes up several of these problematic cases.

o sanity check the on-disk maximum key lengths on mount
  (these are set to a defined value at mkfs time and shouldn't differ)
o check on-disk node keylens against the maximum key length for each tree
o fix hfs_btree_open so that going out via free_tree: doesn't wind
  up in hfs_releasepage, which wants to follow the very pointer
  we were trying to set up:
	HFS_SB(sb)->cat_tree = hfs_btree_open()
    .
  failure gets to hfs_releasepage and tries to follow HFS_SB(sb)->cat_tree

Tested with the fsfuzzer; it survives more than it used to.

[hch: ported of commit cf05946250 from hfs]
[hch: added the fixes from 5581d018ed3493d226e7a4d645d9c8a5af6c36b]

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-14 09:53:48 -04:00
Al Viro
b6b41424f0 hfsplus: hfs_bnode_find() can fail, resulting in hfs_bnode_split() breakage
oops and fs corruption; the latter can happen even on valid fs in case of oom.

[hch: port of commit 3d10a15d69 from hfs]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-14 09:53:42 -04:00
Jeff Mahoney
ee52716245 hfsplus: fix oops on mount with corrupted btree extent records
A particular fsfuzzer run caused an hfs file system to crash on mount. This
is due to a corrupted MDB extent record causing a miscalculation of
HFSPLUS_I(inode)->first_blocks for the extent tree. If the extent records
are zereod out, then it won't trigger the first_blocks special case and
instead falls through to the extent code, which we're in the middle
of initializing.

This patch catches the 0 size extent records, reports the corruption,
and fails the mount.

[hch: ported of commit 47f365eb57 from hfs]

Reported-by: Ramon de Carvalho Valle <rcvalle@linux.vnet.ibm.com>
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-14 09:53:37 -04:00
Christoph Hellwig
40de9a7ceb hfsplus: fix rename over directories
When renaming over a directory we need to use hfsplus_rmdir instead of
hfsplus_unlink to evict the victim.  This makes sure we properly error out
on non-empty directory as required by Posix (BZ #16571), and it also makes
sure we do the right thing in case i_nlink will every be set correctly for
directories on hfsplus.

Reported-by: Vlado Plaga <rechner@vlado-do.de>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 09:12:08 +02:00
Thomas Gleixner
467c3d9cd5 hfsplus: convert tree_lock to mutex
tree_lock is used as mutex so make it a mutex.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:46:52 +02:00
Christoph Hellwig
7fcc99f4f2 hfsplus: add missing extent locking in hfsplus_write_inode
Most of the extent handling code already does proper SMP locking, but
hfsplus_write_inode was calling into hfsplus_ext_write_extent without
taking the extents_lock.  Fix this by splitting hfsplus_ext_write_extent
into an internal helper that expects the lock, and a public interface
that first acquires it.

Also add a few locking asserts and document the locking rules in
hfsplus_fs.h.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:46:31 +02:00
Christoph Hellwig
89755dcace hfsplus: protect readdir against removals from open_dir_list
We already have i_mutex for readdir and the namespace operations that add
entries to open_dir_list, the only thing that was missing was the removal
in hfsplus_dir_release.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:45:25 +02:00
Christoph Hellwig
84adede312 hfsplus: use atomic bitops for the superblock flags
The flags in the HFS+-specific superlock do get modified during runtime,
use atomic bitops to make the modifications SMP safe.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:45:20 +02:00
Christoph Hellwig
7ac9fb9c2a hfsplus: add per-superblock lock for volume header updates
Lock updates to the mutal fields in the volume header, and document the
locing in the hfsplus_sb_info structure.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:45:08 +02:00
Christoph Hellwig
58a818f532 hfsplus: remove the rsrc_inodes list
We never walk the list - the only reason for it is to make the resource fork
inodes appear hashed to the writeback code.  Borrow a trick from JFS to do
that without needing a list head.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:44:02 +02:00
Christoph Hellwig
66e5db05bb hfsplus: do not cache and write next_alloc
We never look at it, nor change the next_alloc field in the superblock.  So
don't bother caching it or writing it out in hfsplus_sync_fs.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:43:58 +02:00
Christoph Hellwig
f17c89bfcc hfsplus: fix error handling in hfsplus_symlink
We need to free the inode again on a hfsplus_create_cat failure.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:43:54 +02:00
Christoph Hellwig
30d3abbec7 hfsplus: merge mknod/mkdir/creat
Make hfsplus_mkdir and hfsplus_create call hfsplus_mknod instead of
duplicating the code.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:43:50 +02:00
Christoph Hellwig
b5080f77ed hfsplus: clean up hfsplus_write_inode
Add a new hfsplus_system_write_inode for writing the special system inodes
and streamline the fastpath write_inode code.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:43:43 +02:00
Christoph Hellwig
fc4fff8210 hfsplus: clean up hfsplus_iget
Add a new hfsplus_system_read_inode for reading the special system inodes
and streamline the fastpath iget code.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:43:41 +02:00
Christoph Hellwig
6af502de22 hfsplus: fix HFSPLUS_I calling convention
HFSPLUS_I doesn't return a pointer to the hfsplus-specific inode
information like all other FOO_I macros, but dereference the pointer in a way
that made it look like a direct struct derefence.  This only works as long
as the HFSPLUS_I macro is used directly and prevents us from keepig a local
hfsplus_inode_info pointer.  Fix the calling convention and introduce a local
hip variable in all functions that use it constantly.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
2010-10-01 05:43:31 +02:00