aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/dir.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@tuxera.com>2010-09-30 23:45:08 -0400
committerChristoph Hellwig <hch@lst.de>2010-09-30 23:45:08 -0400
commit7ac9fb9c2a50963b699b3548e6f00698c1554dc6 (patch)
tree3660bfb2985c65838b5969694e54043ae6639b3a /fs/hfsplus/dir.c
parent58a818f532e83f337689358c102ba2048d1b37f5 (diff)
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>
Diffstat (limited to 'fs/hfsplus/dir.c')
-rw-r--r--fs/hfsplus/dir.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index f8ae468f4ab6..1c81eedcab01 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -251,6 +251,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
251 if (HFSPLUS_IS_RSRC(inode)) 251 if (HFSPLUS_IS_RSRC(inode))
252 return -EPERM; 252 return -EPERM;
253 253
254 mutex_lock(&sbi->vh_mutex);
254 if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { 255 if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) {
255 for (;;) { 256 for (;;) {
256 get_random_bytes(&id, sizeof(cnid)); 257 get_random_bytes(&id, sizeof(cnid));
@@ -263,7 +264,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
263 if (!res) 264 if (!res)
264 break; 265 break;
265 if (res != -EEXIST) 266 if (res != -EEXIST)
266 return res; 267 goto out;
267 } 268 }
268 HFSPLUS_I(inode)->dev = id; 269 HFSPLUS_I(inode)->dev = id;
269 cnid = sbi->next_cnid++; 270 cnid = sbi->next_cnid++;
@@ -271,13 +272,13 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
271 res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); 272 res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode);
272 if (res) 273 if (res)
273 /* panic? */ 274 /* panic? */
274 return res; 275 goto out;
275 sbi->file_count++; 276 sbi->file_count++;
276 } 277 }
277 cnid = sbi->next_cnid++; 278 cnid = sbi->next_cnid++;
278 res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); 279 res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode);
279 if (res) 280 if (res)
280 return res; 281 goto out;
281 282
282 inc_nlink(inode); 283 inc_nlink(inode);
283 hfsplus_instantiate(dst_dentry, inode, cnid); 284 hfsplus_instantiate(dst_dentry, inode, cnid);
@@ -286,8 +287,9 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
286 mark_inode_dirty(inode); 287 mark_inode_dirty(inode);
287 sbi->file_count++; 288 sbi->file_count++;
288 dst_dir->i_sb->s_dirt = 1; 289 dst_dir->i_sb->s_dirt = 1;
289 290out:
290 return 0; 291 mutex_unlock(&sbi->vh_mutex);
292 return res;
291} 293}
292 294
293static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) 295static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
@@ -302,6 +304,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
302 if (HFSPLUS_IS_RSRC(inode)) 304 if (HFSPLUS_IS_RSRC(inode))
303 return -EPERM; 305 return -EPERM;
304 306
307 mutex_lock(&sbi->vh_mutex);
305 cnid = (u32)(unsigned long)dentry->d_fsdata; 308 cnid = (u32)(unsigned long)dentry->d_fsdata;
306 if (inode->i_ino == cnid && 309 if (inode->i_ino == cnid &&
307 atomic_read(&HFSPLUS_I(inode)->opencnt)) { 310 atomic_read(&HFSPLUS_I(inode)->opencnt)) {
@@ -312,11 +315,11 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
312 sbi->hidden_dir, &str); 315 sbi->hidden_dir, &str);
313 if (!res) 316 if (!res)
314 inode->i_flags |= S_DEAD; 317 inode->i_flags |= S_DEAD;
315 return res; 318 goto out;
316 } 319 }
317 res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); 320 res = hfsplus_delete_cat(cnid, dir, &dentry->d_name);
318 if (res) 321 if (res)
319 return res; 322 goto out;
320 323
321 if (inode->i_nlink > 0) 324 if (inode->i_nlink > 0)
322 drop_nlink(inode); 325 drop_nlink(inode);
@@ -339,37 +342,44 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
339 sbi->file_count--; 342 sbi->file_count--;
340 inode->i_ctime = CURRENT_TIME_SEC; 343 inode->i_ctime = CURRENT_TIME_SEC;
341 mark_inode_dirty(inode); 344 mark_inode_dirty(inode);
342 345out:
346 mutex_unlock(&sbi->vh_mutex);
343 return res; 347 return res;
344} 348}
345 349
346static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) 350static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
347{ 351{
348 struct inode *inode; 352 struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
353 struct inode *inode = dentry->d_inode;
349 int res; 354 int res;
350 355
351 inode = dentry->d_inode;
352 if (inode->i_size != 2) 356 if (inode->i_size != 2)
353 return -ENOTEMPTY; 357 return -ENOTEMPTY;
358
359 mutex_lock(&sbi->vh_mutex);
354 res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); 360 res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
355 if (res) 361 if (res)
356 return res; 362 goto out;
357 clear_nlink(inode); 363 clear_nlink(inode);
358 inode->i_ctime = CURRENT_TIME_SEC; 364 inode->i_ctime = CURRENT_TIME_SEC;
359 hfsplus_delete_inode(inode); 365 hfsplus_delete_inode(inode);
360 mark_inode_dirty(inode); 366 mark_inode_dirty(inode);
361 return 0; 367out:
368 mutex_unlock(&sbi->vh_mutex);
369 return res;
362} 370}
363 371
364static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, 372static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
365 const char *symname) 373 const char *symname)
366{ 374{
375 struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
367 struct inode *inode; 376 struct inode *inode;
368 int res; 377 int res = -ENOSPC;
369 378
379 mutex_lock(&sbi->vh_mutex);
370 inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); 380 inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO);
371 if (!inode) 381 if (!inode)
372 return -ENOSPC; 382 goto out;
373 383
374 res = page_symlink(inode, symname, strlen(symname) + 1); 384 res = page_symlink(inode, symname, strlen(symname) + 1);
375 if (res) 385 if (res)
@@ -381,31 +391,35 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
381 391
382 hfsplus_instantiate(dentry, inode, inode->i_ino); 392 hfsplus_instantiate(dentry, inode, inode->i_ino);
383 mark_inode_dirty(inode); 393 mark_inode_dirty(inode);
384 return 0; 394 goto out;
385 395
386out_err: 396out_err:
387 inode->i_nlink = 0; 397 inode->i_nlink = 0;
388 hfsplus_delete_inode(inode); 398 hfsplus_delete_inode(inode);
389 iput(inode); 399 iput(inode);
400out:
401 mutex_unlock(&sbi->vh_mutex);
390 return res; 402 return res;
391} 403}
392 404
393static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, 405static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
394 int mode, dev_t rdev) 406 int mode, dev_t rdev)
395{ 407{
408 struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
396 struct inode *inode; 409 struct inode *inode;
397 int res; 410 int res = -ENOSPC;
398 411
412 mutex_lock(&sbi->vh_mutex);
399 inode = hfsplus_new_inode(dir->i_sb, mode); 413 inode = hfsplus_new_inode(dir->i_sb, mode);
400 if (!inode) 414 if (!inode)
401 return -ENOSPC; 415 goto out;
402 416
403 res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); 417 res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
404 if (res) { 418 if (res) {
405 inode->i_nlink = 0; 419 inode->i_nlink = 0;
406 hfsplus_delete_inode(inode); 420 hfsplus_delete_inode(inode);
407 iput(inode); 421 iput(inode);
408 return res; 422 goto out;
409 } 423 }
410 424
411 if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) 425 if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode))
@@ -413,7 +427,9 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
413 427
414 hfsplus_instantiate(dentry, inode, inode->i_ino); 428 hfsplus_instantiate(dentry, inode, inode->i_ino);
415 mark_inode_dirty(inode); 429 mark_inode_dirty(inode);
416 return 0; 430out:
431 mutex_unlock(&sbi->vh_mutex);
432 return res;
417} 433}
418 434
419static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, 435static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,