diff options
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/inode.c | 89 |
1 files changed, 77 insertions, 12 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 8cd617b66baa..a8acfc5d3476 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -348,6 +348,76 @@ out: | |||
348 | } | 348 | } |
349 | 349 | ||
350 | /** | 350 | /** |
351 | * ecryptfs_new_lower_dentry | ||
352 | * @ename: The name of the new dentry. | ||
353 | * @lower_dir_dentry: Parent directory of the new dentry. | ||
354 | * @nd: nameidata from last lookup. | ||
355 | * | ||
356 | * Create a new dentry or get it from lower parent dir. | ||
357 | */ | ||
358 | static struct dentry * | ||
359 | ecryptfs_new_lower_dentry(struct qstr *name, struct dentry *lower_dir_dentry, | ||
360 | struct nameidata *nd) | ||
361 | { | ||
362 | struct dentry *new_dentry; | ||
363 | struct dentry *tmp; | ||
364 | struct inode *lower_dir_inode; | ||
365 | |||
366 | lower_dir_inode = lower_dir_dentry->d_inode; | ||
367 | |||
368 | tmp = d_alloc(lower_dir_dentry, name); | ||
369 | if (!tmp) | ||
370 | return ERR_PTR(-ENOMEM); | ||
371 | |||
372 | mutex_lock(&lower_dir_inode->i_mutex); | ||
373 | new_dentry = lower_dir_inode->i_op->lookup(lower_dir_inode, tmp, nd); | ||
374 | mutex_unlock(&lower_dir_inode->i_mutex); | ||
375 | |||
376 | if (!new_dentry) | ||
377 | new_dentry = tmp; | ||
378 | else | ||
379 | dput(tmp); | ||
380 | |||
381 | return new_dentry; | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * ecryptfs_lookup_one_lower | ||
387 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | ||
388 | * @lower_dir_dentry: lower parent directory | ||
389 | * | ||
390 | * Get the lower dentry from vfs. If lower dentry does not exist yet, | ||
391 | * create it. | ||
392 | */ | ||
393 | static struct dentry * | ||
394 | ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry, | ||
395 | struct dentry *lower_dir_dentry) | ||
396 | { | ||
397 | struct nameidata nd; | ||
398 | struct vfsmount *lower_mnt; | ||
399 | struct qstr *name; | ||
400 | int err; | ||
401 | |||
402 | name = &ecryptfs_dentry->d_name; | ||
403 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( | ||
404 | ecryptfs_dentry->d_parent)); | ||
405 | err = vfs_path_lookup(lower_dir_dentry, lower_mnt, name->name , 0, &nd); | ||
406 | mntput(lower_mnt); | ||
407 | |||
408 | if (!err) { | ||
409 | /* we dont need the mount */ | ||
410 | mntput(nd.path.mnt); | ||
411 | return nd.path.dentry; | ||
412 | } | ||
413 | if (err != -ENOENT) | ||
414 | return ERR_PTR(err); | ||
415 | |||
416 | /* create a new lower dentry */ | ||
417 | return ecryptfs_new_lower_dentry(name, lower_dir_dentry, &nd); | ||
418 | } | ||
419 | |||
420 | /** | ||
351 | * ecryptfs_lookup | 421 | * ecryptfs_lookup |
352 | * @ecryptfs_dir_inode: The eCryptfs directory inode | 422 | * @ecryptfs_dir_inode: The eCryptfs directory inode |
353 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | 423 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up |
@@ -374,14 +444,12 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
374 | goto out_d_drop; | 444 | goto out_d_drop; |
375 | } | 445 | } |
376 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); | 446 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); |
377 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); | 447 | |
378 | lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, | 448 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, |
379 | lower_dir_dentry, | 449 | lower_dir_dentry); |
380 | ecryptfs_dentry->d_name.len); | ||
381 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); | ||
382 | if (IS_ERR(lower_dentry)) { | 450 | if (IS_ERR(lower_dentry)) { |
383 | rc = PTR_ERR(lower_dentry); | 451 | rc = PTR_ERR(lower_dentry); |
384 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 452 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " |
385 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 453 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
386 | encrypted_and_encoded_name); | 454 | encrypted_and_encoded_name); |
387 | goto out_d_drop; | 455 | goto out_d_drop; |
@@ -403,14 +471,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
403 | "filename; rc = [%d]\n", __func__, rc); | 471 | "filename; rc = [%d]\n", __func__, rc); |
404 | goto out_d_drop; | 472 | goto out_d_drop; |
405 | } | 473 | } |
406 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); | 474 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, |
407 | lower_dentry = lookup_one_len(encrypted_and_encoded_name, | 475 | lower_dir_dentry); |
408 | lower_dir_dentry, | ||
409 | encrypted_and_encoded_name_size - 1); | ||
410 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); | ||
411 | if (IS_ERR(lower_dentry)) { | 476 | if (IS_ERR(lower_dentry)) { |
412 | rc = PTR_ERR(lower_dentry); | 477 | rc = PTR_ERR(lower_dentry); |
413 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 478 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " |
414 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 479 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
415 | encrypted_and_encoded_name); | 480 | encrypted_and_encoded_name); |
416 | goto out_d_drop; | 481 | goto out_d_drop; |