Commit 9717a91b authored by Al Viro's avatar Al Viro

hfs: switch to ->iterate_shared()

exact parallel of hfsplus analogue
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 323ee8fc
...@@ -240,10 +240,13 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, struct qstr *str) ...@@ -240,10 +240,13 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, struct qstr *str)
} }
} }
/* we only need to take spinlock for exclusion with ->release() */
spin_lock(&HFS_I(dir)->open_dir_lock);
list_for_each_entry(rd, &HFS_I(dir)->open_dir_list, list) { list_for_each_entry(rd, &HFS_I(dir)->open_dir_list, list) {
if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
rd->file->f_pos--; rd->file->f_pos--;
} }
spin_unlock(&HFS_I(dir)->open_dir_lock);
res = hfs_brec_remove(&fd); res = hfs_brec_remove(&fd);
if (res) if (res)
......
...@@ -161,8 +161,14 @@ static int hfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -161,8 +161,14 @@ static int hfs_readdir(struct file *file, struct dir_context *ctx)
} }
file->private_data = rd; file->private_data = rd;
rd->file = file; rd->file = file;
spin_lock(&HFS_I(inode)->open_dir_lock);
list_add(&rd->list, &HFS_I(inode)->open_dir_list); list_add(&rd->list, &HFS_I(inode)->open_dir_list);
spin_unlock(&HFS_I(inode)->open_dir_lock);
} }
/*
* Can be done after the list insertion; exclusion with
* hfs_delete_cat() is provided by directory lock.
*/
memcpy(&rd->key, &fd.key, sizeof(struct hfs_cat_key)); memcpy(&rd->key, &fd.key, sizeof(struct hfs_cat_key));
out: out:
hfs_find_exit(&fd); hfs_find_exit(&fd);
...@@ -173,9 +179,9 @@ static int hfs_dir_release(struct inode *inode, struct file *file) ...@@ -173,9 +179,9 @@ static int hfs_dir_release(struct inode *inode, struct file *file)
{ {
struct hfs_readdir_data *rd = file->private_data; struct hfs_readdir_data *rd = file->private_data;
if (rd) { if (rd) {
inode_lock(inode); spin_lock(&HFS_I(inode)->open_dir_lock);
list_del(&rd->list); list_del(&rd->list);
inode_unlock(inode); spin_unlock(&HFS_I(inode)->open_dir_lock);
kfree(rd); kfree(rd);
} }
return 0; return 0;
...@@ -303,7 +309,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -303,7 +309,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
const struct file_operations hfs_dir_operations = { const struct file_operations hfs_dir_operations = {
.read = generic_read_dir, .read = generic_read_dir,
.iterate = hfs_readdir, .iterate_shared = hfs_readdir,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.release = hfs_dir_release, .release = hfs_dir_release,
}; };
......
...@@ -69,6 +69,7 @@ struct hfs_inode_info { ...@@ -69,6 +69,7 @@ struct hfs_inode_info {
struct hfs_cat_key cat_key; struct hfs_cat_key cat_key;
struct list_head open_dir_list; struct list_head open_dir_list;
spinlock_t open_dir_lock;
struct inode *rsrc_inode; struct inode *rsrc_inode;
struct mutex extents_lock; struct mutex extents_lock;
......
...@@ -187,6 +187,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode) ...@@ -187,6 +187,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)
mutex_init(&HFS_I(inode)->extents_lock); mutex_init(&HFS_I(inode)->extents_lock);
INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list); INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
spin_lock_init(&HFS_I(inode)->open_dir_lock);
hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name); hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
inode->i_ino = HFS_SB(sb)->next_id++; inode->i_ino = HFS_SB(sb)->next_id++;
inode->i_mode = mode; inode->i_mode = mode;
...@@ -318,6 +319,7 @@ static int hfs_read_inode(struct inode *inode, void *data) ...@@ -318,6 +319,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
HFS_I(inode)->rsrc_inode = NULL; HFS_I(inode)->rsrc_inode = NULL;
mutex_init(&HFS_I(inode)->extents_lock); mutex_init(&HFS_I(inode)->extents_lock);
INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list); INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
spin_lock_init(&HFS_I(inode)->open_dir_lock);
/* Initialize the inode */ /* Initialize the inode */
inode->i_uid = hsb->s_uid; inode->i_uid = hsb->s_uid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment