aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfs
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2011-05-10 14:52:07 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2011-05-10 16:50:41 -0400
commit020abf03cd659388f94cb328e1e1df0656e0d7ff (patch)
tree40d05011708ad1b4a05928d167eb120420581aa6 /fs/hfs
parent0ff8fbc61727c926883eec381fbd3d32d1fab504 (diff)
parent693d92a1bbc9e42681c42ed190bd42b636ca876f (diff)
Merge tag 'v2.6.39-rc7'
in order to pull in changes in drivers/media/dvb/firewire/ and sound/firewire/.
Diffstat (limited to 'fs/hfs')
-rw-r--r--fs/hfs/dir.c52
-rw-r--r--fs/hfs/hfs_fs.h8
-rw-r--r--fs/hfs/inode.c2
-rw-r--r--fs/hfs/string.c17
-rw-r--r--fs/hfs/super.c12
-rw-r--r--fs/hfs/sysdep.c7
6 files changed, 43 insertions, 55 deletions
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 2b3b8611b41b..b4d70b13be92 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -25,8 +25,6 @@ static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
25 struct inode *inode = NULL; 25 struct inode *inode = NULL;
26 int res; 26 int res;
27 27
28 dentry->d_op = &hfs_dentry_operations;
29
30 hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd); 28 hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
31 hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name); 29 hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name);
32 res = hfs_brec_read(&fd, &rec, sizeof(rec)); 30 res = hfs_brec_read(&fd, &rec, sizeof(rec));
@@ -240,46 +238,22 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
240} 238}
241 239
242/* 240/*
243 * hfs_unlink() 241 * hfs_remove()
244 * 242 *
245 * This is the unlink() entry in the inode_operations structure for 243 * This serves as both unlink() and rmdir() in the inode_operations
246 * regular HFS directories. The purpose is to delete an existing 244 * structure for regular HFS directories. The purpose is to delete
247 * file, given the inode for the parent directory and the name 245 * an existing child, given the inode for the parent directory and
248 * (and its length) of the existing file. 246 * the name (and its length) of the existing directory.
249 */
250static int hfs_unlink(struct inode *dir, struct dentry *dentry)
251{
252 struct inode *inode;
253 int res;
254
255 inode = dentry->d_inode;
256 res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
257 if (res)
258 return res;
259
260 drop_nlink(inode);
261 hfs_delete_inode(inode);
262 inode->i_ctime = CURRENT_TIME_SEC;
263 mark_inode_dirty(inode);
264
265 return res;
266}
267
268/*
269 * hfs_rmdir()
270 * 247 *
271 * This is the rmdir() entry in the inode_operations structure for 248 * HFS does not have hardlinks, so both rmdir and unlink set the
272 * regular HFS directories. The purpose is to delete an existing 249 * link count to 0. The only difference is the emptiness check.
273 * directory, given the inode for the parent directory and the name
274 * (and its length) of the existing directory.
275 */ 250 */
276static int hfs_rmdir(struct inode *dir, struct dentry *dentry) 251static int hfs_remove(struct inode *dir, struct dentry *dentry)
277{ 252{
278 struct inode *inode; 253 struct inode *inode = dentry->d_inode;
279 int res; 254 int res;
280 255
281 inode = dentry->d_inode; 256 if (S_ISDIR(inode->i_mode) && inode->i_size != 2)
282 if (inode->i_size != 2)
283 return -ENOTEMPTY; 257 return -ENOTEMPTY;
284 res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); 258 res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
285 if (res) 259 if (res)
@@ -309,7 +283,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
309 283
310 /* Unlink destination if it already exists */ 284 /* Unlink destination if it already exists */
311 if (new_dentry->d_inode) { 285 if (new_dentry->d_inode) {
312 res = hfs_unlink(new_dir, new_dentry); 286 res = hfs_remove(new_dir, new_dentry);
313 if (res) 287 if (res)
314 return res; 288 return res;
315 } 289 }
@@ -334,9 +308,9 @@ const struct file_operations hfs_dir_operations = {
334const struct inode_operations hfs_dir_inode_operations = { 308const struct inode_operations hfs_dir_inode_operations = {
335 .create = hfs_create, 309 .create = hfs_create,
336 .lookup = hfs_lookup, 310 .lookup = hfs_lookup,
337 .unlink = hfs_unlink, 311 .unlink = hfs_remove,
338 .mkdir = hfs_mkdir, 312 .mkdir = hfs_mkdir,
339 .rmdir = hfs_rmdir, 313 .rmdir = hfs_remove,
340 .rename = hfs_rename, 314 .rename = hfs_rename,
341 .setattr = hfs_inode_setattr, 315 .setattr = hfs_inode_setattr,
342}; 316};
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index c8cffb81e849..ad97c2d58287 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -213,10 +213,14 @@ extern int hfs_part_find(struct super_block *, sector_t *, sector_t *);
213/* string.c */ 213/* string.c */
214extern const struct dentry_operations hfs_dentry_operations; 214extern const struct dentry_operations hfs_dentry_operations;
215 215
216extern int hfs_hash_dentry(struct dentry *, struct qstr *); 216extern int hfs_hash_dentry(const struct dentry *, const struct inode *,
217 struct qstr *);
217extern int hfs_strcmp(const unsigned char *, unsigned int, 218extern int hfs_strcmp(const unsigned char *, unsigned int,
218 const unsigned char *, unsigned int); 219 const unsigned char *, unsigned int);
219extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 220extern int hfs_compare_dentry(const struct dentry *parent,
221 const struct inode *pinode,
222 const struct dentry *dentry, const struct inode *inode,
223 unsigned int len, const char *str, const struct qstr *name);
220 224
221/* trans.c */ 225/* trans.c */
222extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *); 226extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index dffb4e996643..fff16c968e67 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -150,7 +150,6 @@ static int hfs_writepages(struct address_space *mapping,
150const struct address_space_operations hfs_btree_aops = { 150const struct address_space_operations hfs_btree_aops = {
151 .readpage = hfs_readpage, 151 .readpage = hfs_readpage,
152 .writepage = hfs_writepage, 152 .writepage = hfs_writepage,
153 .sync_page = block_sync_page,
154 .write_begin = hfs_write_begin, 153 .write_begin = hfs_write_begin,
155 .write_end = generic_write_end, 154 .write_end = generic_write_end,
156 .bmap = hfs_bmap, 155 .bmap = hfs_bmap,
@@ -160,7 +159,6 @@ const struct address_space_operations hfs_btree_aops = {
160const struct address_space_operations hfs_aops = { 159const struct address_space_operations hfs_aops = {
161 .readpage = hfs_readpage, 160 .readpage = hfs_readpage,
162 .writepage = hfs_writepage, 161 .writepage = hfs_writepage,
163 .sync_page = block_sync_page,
164 .write_begin = hfs_write_begin, 162 .write_begin = hfs_write_begin,
165 .write_end = generic_write_end, 163 .write_end = generic_write_end,
166 .bmap = hfs_bmap, 164 .bmap = hfs_bmap,
diff --git a/fs/hfs/string.c b/fs/hfs/string.c
index 927a5af79428..495a976a3cc9 100644
--- a/fs/hfs/string.c
+++ b/fs/hfs/string.c
@@ -51,7 +51,8 @@ static unsigned char caseorder[256] = {
51/* 51/*
52 * Hash a string to an integer in a case-independent way 52 * Hash a string to an integer in a case-independent way
53 */ 53 */
54int hfs_hash_dentry(struct dentry *dentry, struct qstr *this) 54int hfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
55 struct qstr *this)
55{ 56{
56 const unsigned char *name = this->name; 57 const unsigned char *name = this->name;
57 unsigned int hash, len = this->len; 58 unsigned int hash, len = this->len;
@@ -92,21 +93,21 @@ int hfs_strcmp(const unsigned char *s1, unsigned int len1,
92 * Test for equality of two strings in the HFS filename character ordering. 93 * Test for equality of two strings in the HFS filename character ordering.
93 * return 1 on failure and 0 on success 94 * return 1 on failure and 0 on success
94 */ 95 */
95int hfs_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2) 96int hfs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
97 const struct dentry *dentry, const struct inode *inode,
98 unsigned int len, const char *str, const struct qstr *name)
96{ 99{
97 const unsigned char *n1, *n2; 100 const unsigned char *n1, *n2;
98 int len;
99 101
100 len = s1->len;
101 if (len >= HFS_NAMELEN) { 102 if (len >= HFS_NAMELEN) {
102 if (s2->len < HFS_NAMELEN) 103 if (name->len < HFS_NAMELEN)
103 return 1; 104 return 1;
104 len = HFS_NAMELEN; 105 len = HFS_NAMELEN;
105 } else if (len != s2->len) 106 } else if (len != name->len)
106 return 1; 107 return 1;
107 108
108 n1 = s1->name; 109 n1 = str;
109 n2 = s2->name; 110 n2 = name->name;
110 while (len--) { 111 while (len--) {
111 if (caseorder[*n1++] != caseorder[*n2++]) 112 if (caseorder[*n1++] != caseorder[*n2++])
112 return 1; 113 return 1;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 4824c27cebb8..1b55f704fb22 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -167,11 +167,18 @@ static struct inode *hfs_alloc_inode(struct super_block *sb)
167 return i ? &i->vfs_inode : NULL; 167 return i ? &i->vfs_inode : NULL;
168} 168}
169 169
170static void hfs_destroy_inode(struct inode *inode) 170static void hfs_i_callback(struct rcu_head *head)
171{ 171{
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
177static void hfs_destroy_inode(struct inode *inode)
178{
179 call_rcu(&inode->i_rcu, hfs_i_callback);
180}
181
175static const struct super_operations hfs_super_operations = { 182static const struct super_operations hfs_super_operations = {
176 .alloc_inode = hfs_alloc_inode, 183 .alloc_inode = hfs_alloc_inode,
177 .destroy_inode = hfs_destroy_inode, 184 .destroy_inode = hfs_destroy_inode,
@@ -422,13 +429,12 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
422 if (!root_inode) 429 if (!root_inode)
423 goto bail_no_root; 430 goto bail_no_root;
424 431
432 sb->s_d_op = &hfs_dentry_operations;
425 res = -ENOMEM; 433 res = -ENOMEM;
426 sb->s_root = d_alloc_root(root_inode); 434 sb->s_root = d_alloc_root(root_inode);
427 if (!sb->s_root) 435 if (!sb->s_root)
428 goto bail_iput; 436 goto bail_iput;
429 437
430 sb->s_root->d_op = &hfs_dentry_operations;
431
432 /* everything's okay */ 438 /* everything's okay */
433 return 0; 439 return 0;
434 440
diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c
index 7478f5c219aa..19cf291eb91f 100644
--- a/fs/hfs/sysdep.c
+++ b/fs/hfs/sysdep.c
@@ -8,15 +8,20 @@
8 * This file contains the code to do various system dependent things. 8 * This file contains the code to do various system dependent things.
9 */ 9 */
10 10
11#include <linux/namei.h>
11#include "hfs_fs.h" 12#include "hfs_fs.h"
12 13
13/* dentry case-handling: just lowercase everything */ 14/* dentry case-handling: just lowercase everything */
14 15
15static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) 16static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
16{ 17{
17 struct inode *inode = dentry->d_inode; 18 struct inode *inode;
18 int diff; 19 int diff;
19 20
21 if (nd->flags & LOOKUP_RCU)
22 return -ECHILD;
23
24 inode = dentry->d_inode;
20 if(!inode) 25 if(!inode)
21 return 1; 26 return 1;
22 27