diff options
Diffstat (limited to 'fs/hfsplus/dir.c')
| -rw-r--r-- | fs/hfsplus/dir.c | 201 |
1 files changed, 96 insertions, 105 deletions
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 764fd1bdca88..d236d85ec9d7 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
| @@ -39,7 +39,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, | |||
| 39 | 39 | ||
| 40 | dentry->d_op = &hfsplus_dentry_operations; | 40 | dentry->d_op = &hfsplus_dentry_operations; |
| 41 | dentry->d_fsdata = NULL; | 41 | dentry->d_fsdata = NULL; |
| 42 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 42 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
| 43 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); | 43 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); |
| 44 | again: | 44 | again: |
| 45 | err = hfs_brec_read(&fd, &entry, sizeof(entry)); | 45 | err = hfs_brec_read(&fd, &entry, sizeof(entry)); |
| @@ -68,9 +68,9 @@ again: | |||
| 68 | cnid = be32_to_cpu(entry.file.id); | 68 | cnid = be32_to_cpu(entry.file.id); |
| 69 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && | 69 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && |
| 70 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && | 70 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && |
| 71 | (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date || | 71 | (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->create_date || |
| 72 | entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) && | 72 | entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode)->create_date) && |
| 73 | HFSPLUS_SB(sb).hidden_dir) { | 73 | HFSPLUS_SB(sb)->hidden_dir) { |
| 74 | struct qstr str; | 74 | struct qstr str; |
| 75 | char name[32]; | 75 | char name[32]; |
| 76 | 76 | ||
| @@ -86,7 +86,8 @@ again: | |||
| 86 | linkid = be32_to_cpu(entry.file.permissions.dev); | 86 | linkid = be32_to_cpu(entry.file.permissions.dev); |
| 87 | str.len = sprintf(name, "iNode%d", linkid); | 87 | str.len = sprintf(name, "iNode%d", linkid); |
| 88 | str.name = name; | 88 | str.name = name; |
| 89 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); | 89 | hfsplus_cat_build_key(sb, fd.search_key, |
| 90 | HFSPLUS_SB(sb)->hidden_dir->i_ino, &str); | ||
| 90 | goto again; | 91 | goto again; |
| 91 | } | 92 | } |
| 92 | } else if (!dentry->d_fsdata) | 93 | } else if (!dentry->d_fsdata) |
| @@ -101,7 +102,7 @@ again: | |||
| 101 | if (IS_ERR(inode)) | 102 | if (IS_ERR(inode)) |
| 102 | return ERR_CAST(inode); | 103 | return ERR_CAST(inode); |
| 103 | if (S_ISREG(inode->i_mode)) | 104 | if (S_ISREG(inode->i_mode)) |
| 104 | HFSPLUS_I(inode).dev = linkid; | 105 | HFSPLUS_I(inode)->linkid = linkid; |
| 105 | out: | 106 | out: |
| 106 | d_add(dentry, inode); | 107 | d_add(dentry, inode); |
| 107 | return NULL; | 108 | return NULL; |
| @@ -124,7 +125,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 124 | if (filp->f_pos >= inode->i_size) | 125 | if (filp->f_pos >= inode->i_size) |
| 125 | return 0; | 126 | return 0; |
| 126 | 127 | ||
| 127 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 128 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
| 128 | hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL); | 129 | hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL); |
| 129 | err = hfs_brec_find(&fd); | 130 | err = hfs_brec_find(&fd); |
| 130 | if (err) | 131 | if (err) |
| @@ -180,8 +181,9 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 180 | err = -EIO; | 181 | err = -EIO; |
| 181 | goto out; | 182 | goto out; |
| 182 | } | 183 | } |
| 183 | if (HFSPLUS_SB(sb).hidden_dir && | 184 | if (HFSPLUS_SB(sb)->hidden_dir && |
| 184 | HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id)) | 185 | HFSPLUS_SB(sb)->hidden_dir->i_ino == |
| 186 | be32_to_cpu(entry.folder.id)) | ||
| 185 | goto next; | 187 | goto next; |
| 186 | if (filldir(dirent, strbuf, len, filp->f_pos, | 188 | if (filldir(dirent, strbuf, len, filp->f_pos, |
| 187 | be32_to_cpu(entry.folder.id), DT_DIR)) | 189 | be32_to_cpu(entry.folder.id), DT_DIR)) |
| @@ -217,7 +219,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 217 | } | 219 | } |
| 218 | filp->private_data = rd; | 220 | filp->private_data = rd; |
| 219 | rd->file = filp; | 221 | rd->file = filp; |
| 220 | list_add(&rd->list, &HFSPLUS_I(inode).open_dir_list); | 222 | list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list); |
| 221 | } | 223 | } |
| 222 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); | 224 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); |
| 223 | out: | 225 | out: |
| @@ -229,38 +231,18 @@ static int hfsplus_dir_release(struct inode *inode, struct file *file) | |||
| 229 | { | 231 | { |
| 230 | struct hfsplus_readdir_data *rd = file->private_data; | 232 | struct hfsplus_readdir_data *rd = file->private_data; |
| 231 | if (rd) { | 233 | if (rd) { |
| 234 | mutex_lock(&inode->i_mutex); | ||
| 232 | list_del(&rd->list); | 235 | list_del(&rd->list); |
| 236 | mutex_unlock(&inode->i_mutex); | ||
| 233 | kfree(rd); | 237 | kfree(rd); |
| 234 | } | 238 | } |
| 235 | return 0; | 239 | return 0; |
| 236 | } | 240 | } |
| 237 | 241 | ||
| 238 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, | ||
| 239 | struct nameidata *nd) | ||
| 240 | { | ||
| 241 | struct inode *inode; | ||
| 242 | int res; | ||
| 243 | |||
| 244 | inode = hfsplus_new_inode(dir->i_sb, mode); | ||
| 245 | if (!inode) | ||
| 246 | return -ENOSPC; | ||
| 247 | |||
| 248 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
| 249 | if (res) { | ||
| 250 | inode->i_nlink = 0; | ||
| 251 | hfsplus_delete_inode(inode); | ||
| 252 | iput(inode); | ||
| 253 | return res; | ||
| 254 | } | ||
| 255 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
| 256 | mark_inode_dirty(inode); | ||
| 257 | return 0; | ||
| 258 | } | ||
| 259 | |||
| 260 | static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | 242 | static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, |
| 261 | struct dentry *dst_dentry) | 243 | struct dentry *dst_dentry) |
| 262 | { | 244 | { |
| 263 | struct super_block *sb = dst_dir->i_sb; | 245 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb); |
| 264 | struct inode *inode = src_dentry->d_inode; | 246 | struct inode *inode = src_dentry->d_inode; |
| 265 | struct inode *src_dir = src_dentry->d_parent->d_inode; | 247 | struct inode *src_dir = src_dentry->d_parent->d_inode; |
| 266 | struct qstr str; | 248 | struct qstr str; |
| @@ -270,7 +252,10 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | |||
| 270 | 252 | ||
| 271 | if (HFSPLUS_IS_RSRC(inode)) | 253 | if (HFSPLUS_IS_RSRC(inode)) |
| 272 | return -EPERM; | 254 | return -EPERM; |
| 255 | if (!S_ISREG(inode->i_mode)) | ||
| 256 | return -EPERM; | ||
| 273 | 257 | ||
| 258 | mutex_lock(&sbi->vh_mutex); | ||
| 274 | if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { | 259 | if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { |
| 275 | for (;;) { | 260 | for (;;) { |
| 276 | get_random_bytes(&id, sizeof(cnid)); | 261 | get_random_bytes(&id, sizeof(cnid)); |
| @@ -279,40 +264,41 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | |||
| 279 | str.len = sprintf(name, "iNode%d", id); | 264 | str.len = sprintf(name, "iNode%d", id); |
| 280 | res = hfsplus_rename_cat(inode->i_ino, | 265 | res = hfsplus_rename_cat(inode->i_ino, |
| 281 | src_dir, &src_dentry->d_name, | 266 | src_dir, &src_dentry->d_name, |
| 282 | HFSPLUS_SB(sb).hidden_dir, &str); | 267 | sbi->hidden_dir, &str); |
| 283 | if (!res) | 268 | if (!res) |
| 284 | break; | 269 | break; |
| 285 | if (res != -EEXIST) | 270 | if (res != -EEXIST) |
| 286 | return res; | 271 | goto out; |
| 287 | } | 272 | } |
| 288 | HFSPLUS_I(inode).dev = id; | 273 | HFSPLUS_I(inode)->linkid = id; |
| 289 | cnid = HFSPLUS_SB(sb).next_cnid++; | 274 | cnid = sbi->next_cnid++; |
| 290 | src_dentry->d_fsdata = (void *)(unsigned long)cnid; | 275 | src_dentry->d_fsdata = (void *)(unsigned long)cnid; |
| 291 | res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); | 276 | res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); |
| 292 | if (res) | 277 | if (res) |
| 293 | /* panic? */ | 278 | /* panic? */ |
| 294 | return res; | 279 | goto out; |
| 295 | HFSPLUS_SB(sb).file_count++; | 280 | sbi->file_count++; |
| 296 | } | 281 | } |
| 297 | cnid = HFSPLUS_SB(sb).next_cnid++; | 282 | cnid = sbi->next_cnid++; |
| 298 | res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); | 283 | res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); |
| 299 | if (res) | 284 | if (res) |
| 300 | return res; | 285 | goto out; |
| 301 | 286 | ||
| 302 | inc_nlink(inode); | 287 | inc_nlink(inode); |
| 303 | hfsplus_instantiate(dst_dentry, inode, cnid); | 288 | hfsplus_instantiate(dst_dentry, inode, cnid); |
| 304 | atomic_inc(&inode->i_count); | 289 | atomic_inc(&inode->i_count); |
| 305 | inode->i_ctime = CURRENT_TIME_SEC; | 290 | inode->i_ctime = CURRENT_TIME_SEC; |
| 306 | mark_inode_dirty(inode); | 291 | mark_inode_dirty(inode); |
| 307 | HFSPLUS_SB(sb).file_count++; | 292 | sbi->file_count++; |
| 308 | sb->s_dirt = 1; | 293 | dst_dir->i_sb->s_dirt = 1; |
| 309 | 294 | out: | |
| 310 | return 0; | 295 | mutex_unlock(&sbi->vh_mutex); |
| 296 | return res; | ||
| 311 | } | 297 | } |
| 312 | 298 | ||
| 313 | static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | 299 | static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) |
| 314 | { | 300 | { |
| 315 | struct super_block *sb = dir->i_sb; | 301 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
| 316 | struct inode *inode = dentry->d_inode; | 302 | struct inode *inode = dentry->d_inode; |
| 317 | struct qstr str; | 303 | struct qstr str; |
| 318 | char name[32]; | 304 | char name[32]; |
| @@ -322,21 +308,22 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
| 322 | if (HFSPLUS_IS_RSRC(inode)) | 308 | if (HFSPLUS_IS_RSRC(inode)) |
| 323 | return -EPERM; | 309 | return -EPERM; |
| 324 | 310 | ||
| 311 | mutex_lock(&sbi->vh_mutex); | ||
| 325 | cnid = (u32)(unsigned long)dentry->d_fsdata; | 312 | cnid = (u32)(unsigned long)dentry->d_fsdata; |
| 326 | if (inode->i_ino == cnid && | 313 | if (inode->i_ino == cnid && |
| 327 | atomic_read(&HFSPLUS_I(inode).opencnt)) { | 314 | atomic_read(&HFSPLUS_I(inode)->opencnt)) { |
| 328 | str.name = name; | 315 | str.name = name; |
| 329 | str.len = sprintf(name, "temp%lu", inode->i_ino); | 316 | str.len = sprintf(name, "temp%lu", inode->i_ino); |
| 330 | res = hfsplus_rename_cat(inode->i_ino, | 317 | res = hfsplus_rename_cat(inode->i_ino, |
| 331 | dir, &dentry->d_name, | 318 | dir, &dentry->d_name, |
| 332 | HFSPLUS_SB(sb).hidden_dir, &str); | 319 | sbi->hidden_dir, &str); |
| 333 | if (!res) | 320 | if (!res) |
| 334 | inode->i_flags |= S_DEAD; | 321 | inode->i_flags |= S_DEAD; |
| 335 | return res; | 322 | goto out; |
| 336 | } | 323 | } |
| 337 | res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); | 324 | res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); |
| 338 | if (res) | 325 | if (res) |
| 339 | return res; | 326 | goto out; |
| 340 | 327 | ||
| 341 | if (inode->i_nlink > 0) | 328 | if (inode->i_nlink > 0) |
| 342 | drop_nlink(inode); | 329 | drop_nlink(inode); |
| @@ -344,10 +331,10 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
| 344 | clear_nlink(inode); | 331 | clear_nlink(inode); |
| 345 | if (!inode->i_nlink) { | 332 | if (!inode->i_nlink) { |
| 346 | if (inode->i_ino != cnid) { | 333 | if (inode->i_ino != cnid) { |
| 347 | HFSPLUS_SB(sb).file_count--; | 334 | sbi->file_count--; |
| 348 | if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { | 335 | if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) { |
| 349 | res = hfsplus_delete_cat(inode->i_ino, | 336 | res = hfsplus_delete_cat(inode->i_ino, |
| 350 | HFSPLUS_SB(sb).hidden_dir, | 337 | sbi->hidden_dir, |
| 351 | NULL); | 338 | NULL); |
| 352 | if (!res) | 339 | if (!res) |
| 353 | hfsplus_delete_inode(inode); | 340 | hfsplus_delete_inode(inode); |
| @@ -356,107 +343,108 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
| 356 | } else | 343 | } else |
| 357 | hfsplus_delete_inode(inode); | 344 | hfsplus_delete_inode(inode); |
| 358 | } else | 345 | } else |
| 359 | HFSPLUS_SB(sb).file_count--; | 346 | sbi->file_count--; |
| 360 | inode->i_ctime = CURRENT_TIME_SEC; | 347 | inode->i_ctime = CURRENT_TIME_SEC; |
| 361 | mark_inode_dirty(inode); | 348 | mark_inode_dirty(inode); |
| 362 | 349 | out: | |
| 350 | mutex_unlock(&sbi->vh_mutex); | ||
| 363 | return res; | 351 | return res; |
| 364 | } | 352 | } |
| 365 | 353 | ||
| 366 | static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
| 367 | { | ||
| 368 | struct inode *inode; | ||
| 369 | int res; | ||
| 370 | |||
| 371 | inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode); | ||
| 372 | if (!inode) | ||
| 373 | return -ENOSPC; | ||
| 374 | |||
| 375 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
| 376 | if (res) { | ||
| 377 | inode->i_nlink = 0; | ||
| 378 | hfsplus_delete_inode(inode); | ||
| 379 | iput(inode); | ||
| 380 | return res; | ||
| 381 | } | ||
| 382 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
| 383 | mark_inode_dirty(inode); | ||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) | 354 | static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) |
| 388 | { | 355 | { |
| 389 | struct inode *inode; | 356 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
| 357 | struct inode *inode = dentry->d_inode; | ||
| 390 | int res; | 358 | int res; |
| 391 | 359 | ||
| 392 | inode = dentry->d_inode; | ||
| 393 | if (inode->i_size != 2) | 360 | if (inode->i_size != 2) |
| 394 | return -ENOTEMPTY; | 361 | return -ENOTEMPTY; |
| 362 | |||
| 363 | mutex_lock(&sbi->vh_mutex); | ||
| 395 | res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); | 364 | res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); |
| 396 | if (res) | 365 | if (res) |
| 397 | return res; | 366 | goto out; |
| 398 | clear_nlink(inode); | 367 | clear_nlink(inode); |
| 399 | inode->i_ctime = CURRENT_TIME_SEC; | 368 | inode->i_ctime = CURRENT_TIME_SEC; |
| 400 | hfsplus_delete_inode(inode); | 369 | hfsplus_delete_inode(inode); |
| 401 | mark_inode_dirty(inode); | 370 | mark_inode_dirty(inode); |
| 402 | return 0; | 371 | out: |
| 372 | mutex_unlock(&sbi->vh_mutex); | ||
| 373 | return res; | ||
| 403 | } | 374 | } |
| 404 | 375 | ||
| 405 | static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, | 376 | static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, |
| 406 | const char *symname) | 377 | const char *symname) |
| 407 | { | 378 | { |
| 408 | struct super_block *sb; | 379 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
| 409 | struct inode *inode; | 380 | struct inode *inode; |
| 410 | int res; | 381 | int res = -ENOSPC; |
| 411 | 382 | ||
| 412 | sb = dir->i_sb; | 383 | mutex_lock(&sbi->vh_mutex); |
| 413 | inode = hfsplus_new_inode(sb, S_IFLNK | S_IRWXUGO); | 384 | inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); |
| 414 | if (!inode) | 385 | if (!inode) |
| 415 | return -ENOSPC; | 386 | goto out; |
| 416 | 387 | ||
| 417 | res = page_symlink(inode, symname, strlen(symname) + 1); | 388 | res = page_symlink(inode, symname, strlen(symname) + 1); |
| 418 | if (res) { | 389 | if (res) |
| 419 | inode->i_nlink = 0; | 390 | goto out_err; |
| 420 | hfsplus_delete_inode(inode); | ||
| 421 | iput(inode); | ||
| 422 | return res; | ||
| 423 | } | ||
| 424 | 391 | ||
| 425 | mark_inode_dirty(inode); | ||
| 426 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | 392 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); |
| 393 | if (res) | ||
| 394 | goto out_err; | ||
| 427 | 395 | ||
| 428 | if (!res) { | 396 | hfsplus_instantiate(dentry, inode, inode->i_ino); |
| 429 | hfsplus_instantiate(dentry, inode, inode->i_ino); | 397 | mark_inode_dirty(inode); |
| 430 | mark_inode_dirty(inode); | 398 | goto out; |
| 431 | } | ||
| 432 | 399 | ||
| 400 | out_err: | ||
| 401 | inode->i_nlink = 0; | ||
| 402 | hfsplus_delete_inode(inode); | ||
| 403 | iput(inode); | ||
| 404 | out: | ||
| 405 | mutex_unlock(&sbi->vh_mutex); | ||
| 433 | return res; | 406 | return res; |
| 434 | } | 407 | } |
| 435 | 408 | ||
| 436 | static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, | 409 | static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, |
| 437 | int mode, dev_t rdev) | 410 | int mode, dev_t rdev) |
| 438 | { | 411 | { |
| 439 | struct super_block *sb; | 412 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
| 440 | struct inode *inode; | 413 | struct inode *inode; |
| 441 | int res; | 414 | int res = -ENOSPC; |
| 442 | 415 | ||
| 443 | sb = dir->i_sb; | 416 | mutex_lock(&sbi->vh_mutex); |
| 444 | inode = hfsplus_new_inode(sb, mode); | 417 | inode = hfsplus_new_inode(dir->i_sb, mode); |
| 445 | if (!inode) | 418 | if (!inode) |
| 446 | return -ENOSPC; | 419 | goto out; |
| 420 | |||
| 421 | if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) | ||
| 422 | init_special_inode(inode, mode, rdev); | ||
| 447 | 423 | ||
| 448 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | 424 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); |
| 449 | if (res) { | 425 | if (res) { |
| 450 | inode->i_nlink = 0; | 426 | inode->i_nlink = 0; |
| 451 | hfsplus_delete_inode(inode); | 427 | hfsplus_delete_inode(inode); |
| 452 | iput(inode); | 428 | iput(inode); |
| 453 | return res; | 429 | goto out; |
| 454 | } | 430 | } |
| 455 | init_special_inode(inode, mode, rdev); | 431 | |
| 456 | hfsplus_instantiate(dentry, inode, inode->i_ino); | 432 | hfsplus_instantiate(dentry, inode, inode->i_ino); |
| 457 | mark_inode_dirty(inode); | 433 | mark_inode_dirty(inode); |
| 434 | out: | ||
| 435 | mutex_unlock(&sbi->vh_mutex); | ||
| 436 | return res; | ||
| 437 | } | ||
| 458 | 438 | ||
| 459 | return 0; | 439 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, |
| 440 | struct nameidata *nd) | ||
| 441 | { | ||
| 442 | return hfsplus_mknod(dir, dentry, mode, 0); | ||
| 443 | } | ||
| 444 | |||
| 445 | static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
| 446 | { | ||
| 447 | return hfsplus_mknod(dir, dentry, mode | S_IFDIR, 0); | ||
| 460 | } | 448 | } |
| 461 | 449 | ||
| 462 | static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | 450 | static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, |
| @@ -466,7 +454,10 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 466 | 454 | ||
| 467 | /* Unlink destination if it already exists */ | 455 | /* Unlink destination if it already exists */ |
| 468 | if (new_dentry->d_inode) { | 456 | if (new_dentry->d_inode) { |
| 469 | res = hfsplus_unlink(new_dir, new_dentry); | 457 | if (S_ISDIR(new_dentry->d_inode->i_mode)) |
| 458 | res = hfsplus_rmdir(new_dir, new_dentry); | ||
| 459 | else | ||
| 460 | res = hfsplus_unlink(new_dir, new_dentry); | ||
| 470 | if (res) | 461 | if (res) |
| 471 | return res; | 462 | return res; |
| 472 | } | 463 | } |
