aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Halcrow <mhalcrow@us.ibm.com>2006-10-31 01:07:20 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-31 11:07:01 -0500
commit45ec4ababe999cb95f9c0cad03b2689cb0b77a2b (patch)
tree8d2ff3c5c356539bc87777948822741ca488ea6b
parent316bb95e8ed0ddcd767e8aa54264b6c6190f150c (diff)
[PATCH] eCryptfs: Fix handling of lower d_count
Fix the use of dget/dput calls to balance out on the lower filesystem. Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/ecryptfs/dentry.c8
-rw-r--r--fs/ecryptfs/inode.c62
2 files changed, 27 insertions, 43 deletions
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index f0d2a433242b..0b9992ab990f 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -24,6 +24,7 @@
24 24
25#include <linux/dcache.h> 25#include <linux/dcache.h>
26#include <linux/namei.h> 26#include <linux/namei.h>
27#include <linux/mount.h>
27#include "ecryptfs_kernel.h" 28#include "ecryptfs_kernel.h"
28 29
29/** 30/**
@@ -76,8 +77,13 @@ static void ecryptfs_d_release(struct dentry *dentry)
76 if (ecryptfs_dentry_to_private(dentry)) 77 if (ecryptfs_dentry_to_private(dentry))
77 kmem_cache_free(ecryptfs_dentry_info_cache, 78 kmem_cache_free(ecryptfs_dentry_info_cache,
78 ecryptfs_dentry_to_private(dentry)); 79 ecryptfs_dentry_to_private(dentry));
79 if (lower_dentry) 80 if (lower_dentry) {
81 struct vfsmount *lower_mnt =
82 ecryptfs_dentry_to_lower_mnt(dentry);
83
84 mntput(lower_mnt);
80 dput(lower_dentry); 85 dput(lower_dentry);
86 }
81 return; 87 return;
82} 88}
83 89
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 2f2c6cf972f7..ff4865d24f0f 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -325,7 +325,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
325 struct dentry *lower_dir_dentry; 325 struct dentry *lower_dir_dentry;
326 struct dentry *lower_dentry; 326 struct dentry *lower_dentry;
327 struct vfsmount *lower_mnt; 327 struct vfsmount *lower_mnt;
328 struct dentry *tlower_dentry = NULL;
329 char *encoded_name; 328 char *encoded_name;
330 unsigned int encoded_namelen; 329 unsigned int encoded_namelen;
331 struct ecryptfs_crypt_stat *crypt_stat = NULL; 330 struct ecryptfs_crypt_stat *crypt_stat = NULL;
@@ -336,27 +335,32 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
336 lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent); 335 lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent);
337 dentry->d_op = &ecryptfs_dops; 336 dentry->d_op = &ecryptfs_dops;
338 if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, ".")) 337 if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, "."))
339 || (dentry->d_name.len == 2 && !strcmp(dentry->d_name.name, ".."))) 338 || (dentry->d_name.len == 2
340 goto out_drop; 339 && !strcmp(dentry->d_name.name, ".."))) {
340 d_drop(dentry);
341 goto out;
342 }
341 encoded_namelen = ecryptfs_encode_filename(crypt_stat, 343 encoded_namelen = ecryptfs_encode_filename(crypt_stat,
342 dentry->d_name.name, 344 dentry->d_name.name,
343 dentry->d_name.len, 345 dentry->d_name.len,
344 &encoded_name); 346 &encoded_name);
345 if (encoded_namelen < 0) { 347 if (encoded_namelen < 0) {
346 rc = encoded_namelen; 348 rc = encoded_namelen;
347 goto out_drop; 349 d_drop(dentry);
350 goto out;
348 } 351 }
349 ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " 352 ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen "
350 "= [%d]\n", encoded_name, encoded_namelen); 353 "= [%d]\n", encoded_name, encoded_namelen);
351 lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, 354 lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry,
352 encoded_namelen - 1); 355 encoded_namelen - 1);
353 kfree(encoded_name); 356 kfree(encoded_name);
354 lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
355 if (IS_ERR(lower_dentry)) { 357 if (IS_ERR(lower_dentry)) {
356 ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); 358 ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n");
357 rc = PTR_ERR(lower_dentry); 359 rc = PTR_ERR(lower_dentry);
358 goto out_drop; 360 d_drop(dentry);
361 goto out;
359 } 362 }
363 lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
360 ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" 364 ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->"
361 "d_name.name = [%s]\n", lower_dentry, 365 "d_name.name = [%s]\n", lower_dentry,
362 lower_dentry->d_name.name); 366 lower_dentry->d_name.name);
@@ -397,12 +401,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
397 "as we *think* we are about to unlink\n"); 401 "as we *think* we are about to unlink\n");
398 goto out; 402 goto out;
399 } 403 }
400 tlower_dentry = dget(lower_dentry);
401 if (!tlower_dentry || IS_ERR(tlower_dentry)) {
402 rc = -ENOMEM;
403 ecryptfs_printk(KERN_ERR, "Cannot dget lower_dentry\n");
404 goto out_dput;
405 }
406 /* Released in this function */ 404 /* Released in this function */
407 page_virt = 405 page_virt =
408 (char *)kmem_cache_alloc(ecryptfs_header_cache_2, 406 (char *)kmem_cache_alloc(ecryptfs_header_cache_2,
@@ -414,7 +412,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
414 goto out_dput; 412 goto out_dput;
415 } 413 }
416 memset(page_virt, 0, PAGE_CACHE_SIZE); 414 memset(page_virt, 0, PAGE_CACHE_SIZE);
417 rc = ecryptfs_read_header_region(page_virt, tlower_dentry, nd->mnt); 415 rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt);
418 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; 416 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
419 if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) 417 if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED))
420 ecryptfs_set_default_sizes(crypt_stat); 418 ecryptfs_set_default_sizes(crypt_stat);
@@ -437,9 +435,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
437 435
438out_dput: 436out_dput:
439 dput(lower_dentry); 437 dput(lower_dentry);
440 if (tlower_dentry)
441 dput(tlower_dentry);
442out_drop:
443 d_drop(dentry); 438 d_drop(dentry);
444out: 439out:
445 return ERR_PTR(rc); 440 return ERR_PTR(rc);
@@ -475,8 +470,8 @@ out_lock:
475 unlock_dir(lower_dir_dentry); 470 unlock_dir(lower_dir_dentry);
476 dput(lower_new_dentry); 471 dput(lower_new_dentry);
477 dput(lower_old_dentry); 472 dput(lower_old_dentry);
478 if (!new_dentry->d_inode) 473 d_drop(new_dentry);
479 d_drop(new_dentry); 474 d_drop(old_dentry);
480 return rc; 475 return rc;
481} 476}
482 477
@@ -565,41 +560,24 @@ out:
565 560
566static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) 561static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
567{ 562{
568 int rc = 0;
569 struct dentry *tdentry = NULL;
570 struct dentry *lower_dentry; 563 struct dentry *lower_dentry;
571 struct dentry *tlower_dentry = NULL;
572 struct dentry *lower_dir_dentry; 564 struct dentry *lower_dir_dentry;
565 int rc;
573 566
574 lower_dentry = ecryptfs_dentry_to_lower(dentry); 567 lower_dentry = ecryptfs_dentry_to_lower(dentry);
575 if (!(tdentry = dget(dentry))) { 568 dget(dentry);
576 rc = -EINVAL;
577 ecryptfs_printk(KERN_ERR, "Error dget'ing dentry [%p]\n",
578 dentry);
579 goto out;
580 }
581 lower_dir_dentry = lock_parent(lower_dentry); 569 lower_dir_dentry = lock_parent(lower_dentry);
582 if (!(tlower_dentry = dget(lower_dentry))) { 570 dget(lower_dentry);
583 rc = -EINVAL;
584 ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry "
585 "[%p]\n", lower_dentry);
586 goto out;
587 }
588 rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); 571 rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
589 if (!rc) { 572 dput(lower_dentry);
590 d_delete(tlower_dentry); 573 if (!rc)
591 tlower_dentry = NULL; 574 d_delete(lower_dentry);
592 }
593 ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); 575 ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode);
594 dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; 576 dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
595 unlock_dir(lower_dir_dentry); 577 unlock_dir(lower_dir_dentry);
596 if (!rc) 578 if (!rc)
597 d_drop(dentry); 579 d_drop(dentry);
598out: 580 dput(dentry);
599 if (tdentry)
600 dput(tdentry);
601 if (tlower_dentry)
602 dput(tlower_dentry);
603 return rc; 581 return rc;
604} 582}
605 583