diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-05-13 02:02:09 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-05-13 02:08:40 +0200 |
commit | 323ee8fc544d407eb053471b9607f95f987f5f12 (patch) | |
tree | 7185ea5c3d7b5d08492bd93bb714bc5338b5355c /fs/hfsplus/catalog.c | |
parent | hostfs: switch to ->iterate_shared() (diff) | |
download | linux-323ee8fc544d407eb053471b9607f95f987f5f12.tar.xz linux-323ee8fc544d407eb053471b9607f95f987f5f12.zip |
hfsplus: switch to ->iterate_shared()
We need to protect the list of hfsplus_readdir_data against parallel
insertions (in readdir) and removals (in release). Add a spinlock
for that. Note that it has nothing to do with protection of
hfsplus_readdir_data->key - we have an exclusion between hfsplus_readdir()
and hfsplus_delete_cat() on directory lock and between several
hfsplus_readdir() for the same struct file on ->f_pos_lock. The spinlock
is strictly for list changes.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/hfsplus/catalog.c')
-rw-r--r-- | fs/hfsplus/catalog.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index 022974ab6e3c..fb707e8f423a 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c @@ -374,12 +374,15 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC); } + /* we only need to take spinlock for exclusion with ->release() */ + spin_lock(&HFSPLUS_I(dir)->open_dir_lock); list_for_each(pos, &HFSPLUS_I(dir)->open_dir_list) { struct hfsplus_readdir_data *rd = list_entry(pos, struct hfsplus_readdir_data, list); if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) rd->file->f_pos--; } + spin_unlock(&HFSPLUS_I(dir)->open_dir_lock); err = hfs_brec_remove(&fd); if (err) |