diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-18 12:03:15 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-18 12:03:15 -0400 |
| commit | d36c30181c4cf6ead34ae30fa2c777b871225c87 (patch) | |
| tree | 8a2476c0eb6bb83ed5a8b493d79458d0e114a146 | |
| parent | a406721dff91a9a5297d140dbb90327966cf9bc0 (diff) | |
| parent | 0916a5e45fbd2604a303c8cc18e6b2b7c815e4c9 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
hppfs_lookup(): don't open-code lookup_one_len()
hppfs: fix dentry leak
cramfs: get_cramfs_inode() returns ERR_PTR() on failure
ufs should use d_splice_alias()
fix exofs ->get_parent()
ceph analog of cifs build_path_from_dentry() race fix
cifs: build_path_from_dentry() race fix
| -rw-r--r-- | fs/ceph/mds_client.c | 19 | ||||
| -rw-r--r-- | fs/cifs/dir.c | 13 | ||||
| -rw-r--r-- | fs/cramfs/inode.c | 22 | ||||
| -rw-r--r-- | fs/exofs/super.c | 2 | ||||
| -rw-r--r-- | fs/hppfs/hppfs.c | 31 | ||||
| -rw-r--r-- | fs/ufs/namei.c | 12 |
6 files changed, 54 insertions, 45 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 79743d146be6..0c1d91756528 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
| @@ -1438,12 +1438,15 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, | |||
| 1438 | struct dentry *temp; | 1438 | struct dentry *temp; |
| 1439 | char *path; | 1439 | char *path; |
| 1440 | int len, pos; | 1440 | int len, pos; |
| 1441 | unsigned seq; | ||
| 1441 | 1442 | ||
| 1442 | if (dentry == NULL) | 1443 | if (dentry == NULL) |
| 1443 | return ERR_PTR(-EINVAL); | 1444 | return ERR_PTR(-EINVAL); |
| 1444 | 1445 | ||
| 1445 | retry: | 1446 | retry: |
| 1446 | len = 0; | 1447 | len = 0; |
| 1448 | seq = read_seqbegin(&rename_lock); | ||
| 1449 | rcu_read_lock(); | ||
| 1447 | for (temp = dentry; !IS_ROOT(temp);) { | 1450 | for (temp = dentry; !IS_ROOT(temp);) { |
| 1448 | struct inode *inode = temp->d_inode; | 1451 | struct inode *inode = temp->d_inode; |
| 1449 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) | 1452 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) |
| @@ -1455,10 +1458,12 @@ retry: | |||
| 1455 | len += 1 + temp->d_name.len; | 1458 | len += 1 + temp->d_name.len; |
| 1456 | temp = temp->d_parent; | 1459 | temp = temp->d_parent; |
| 1457 | if (temp == NULL) { | 1460 | if (temp == NULL) { |
| 1461 | rcu_read_unlock(); | ||
| 1458 | pr_err("build_path corrupt dentry %p\n", dentry); | 1462 | pr_err("build_path corrupt dentry %p\n", dentry); |
| 1459 | return ERR_PTR(-EINVAL); | 1463 | return ERR_PTR(-EINVAL); |
| 1460 | } | 1464 | } |
| 1461 | } | 1465 | } |
| 1466 | rcu_read_unlock(); | ||
| 1462 | if (len) | 1467 | if (len) |
| 1463 | len--; /* no leading '/' */ | 1468 | len--; /* no leading '/' */ |
| 1464 | 1469 | ||
| @@ -1467,9 +1472,12 @@ retry: | |||
| 1467 | return ERR_PTR(-ENOMEM); | 1472 | return ERR_PTR(-ENOMEM); |
| 1468 | pos = len; | 1473 | pos = len; |
| 1469 | path[pos] = 0; /* trailing null */ | 1474 | path[pos] = 0; /* trailing null */ |
| 1475 | rcu_read_lock(); | ||
| 1470 | for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) { | 1476 | for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) { |
| 1471 | struct inode *inode = temp->d_inode; | 1477 | struct inode *inode; |
| 1472 | 1478 | ||
| 1479 | spin_lock(&temp->d_lock); | ||
| 1480 | inode = temp->d_inode; | ||
| 1473 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) { | 1481 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) { |
| 1474 | dout("build_path path+%d: %p SNAPDIR\n", | 1482 | dout("build_path path+%d: %p SNAPDIR\n", |
| 1475 | pos, temp); | 1483 | pos, temp); |
| @@ -1478,21 +1486,26 @@ retry: | |||
| 1478 | break; | 1486 | break; |
| 1479 | } else { | 1487 | } else { |
| 1480 | pos -= temp->d_name.len; | 1488 | pos -= temp->d_name.len; |
| 1481 | if (pos < 0) | 1489 | if (pos < 0) { |
| 1490 | spin_unlock(&temp->d_lock); | ||
| 1482 | break; | 1491 | break; |
| 1492 | } | ||
| 1483 | strncpy(path + pos, temp->d_name.name, | 1493 | strncpy(path + pos, temp->d_name.name, |
| 1484 | temp->d_name.len); | 1494 | temp->d_name.len); |
| 1485 | } | 1495 | } |
| 1496 | spin_unlock(&temp->d_lock); | ||
| 1486 | if (pos) | 1497 | if (pos) |
| 1487 | path[--pos] = '/'; | 1498 | path[--pos] = '/'; |
| 1488 | temp = temp->d_parent; | 1499 | temp = temp->d_parent; |
| 1489 | if (temp == NULL) { | 1500 | if (temp == NULL) { |
| 1501 | rcu_read_unlock(); | ||
| 1490 | pr_err("build_path corrupt dentry\n"); | 1502 | pr_err("build_path corrupt dentry\n"); |
| 1491 | kfree(path); | 1503 | kfree(path); |
| 1492 | return ERR_PTR(-EINVAL); | 1504 | return ERR_PTR(-EINVAL); |
| 1493 | } | 1505 | } |
| 1494 | } | 1506 | } |
| 1495 | if (pos != 0) { | 1507 | rcu_read_unlock(); |
| 1508 | if (pos != 0 || read_seqretry(&rename_lock, seq)) { | ||
| 1496 | pr_err("build_path did not end path lookup where " | 1509 | pr_err("build_path did not end path lookup where " |
| 1497 | "expected, namelen is %d, pos is %d\n", len, pos); | 1510 | "expected, namelen is %d, pos is %d\n", len, pos); |
| 1498 | /* presumably this is only possible if racing with a | 1511 | /* presumably this is only possible if racing with a |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 81914df47ef1..fa8c21d913bc 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -55,6 +55,7 @@ build_path_from_dentry(struct dentry *direntry) | |||
| 55 | char dirsep; | 55 | char dirsep; |
| 56 | struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); | 56 | struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); |
| 57 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | 57 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
| 58 | unsigned seq; | ||
| 58 | 59 | ||
| 59 | if (direntry == NULL) | 60 | if (direntry == NULL) |
| 60 | return NULL; /* not much we can do if dentry is freed and | 61 | return NULL; /* not much we can do if dentry is freed and |
| @@ -68,22 +69,29 @@ build_path_from_dentry(struct dentry *direntry) | |||
| 68 | dfsplen = 0; | 69 | dfsplen = 0; |
| 69 | cifs_bp_rename_retry: | 70 | cifs_bp_rename_retry: |
| 70 | namelen = dfsplen; | 71 | namelen = dfsplen; |
| 72 | seq = read_seqbegin(&rename_lock); | ||
| 73 | rcu_read_lock(); | ||
| 71 | for (temp = direntry; !IS_ROOT(temp);) { | 74 | for (temp = direntry; !IS_ROOT(temp);) { |
| 72 | namelen += (1 + temp->d_name.len); | 75 | namelen += (1 + temp->d_name.len); |
| 73 | temp = temp->d_parent; | 76 | temp = temp->d_parent; |
| 74 | if (temp == NULL) { | 77 | if (temp == NULL) { |
| 75 | cERROR(1, "corrupt dentry"); | 78 | cERROR(1, "corrupt dentry"); |
| 79 | rcu_read_unlock(); | ||
| 76 | return NULL; | 80 | return NULL; |
| 77 | } | 81 | } |
| 78 | } | 82 | } |
| 83 | rcu_read_unlock(); | ||
| 79 | 84 | ||
| 80 | full_path = kmalloc(namelen+1, GFP_KERNEL); | 85 | full_path = kmalloc(namelen+1, GFP_KERNEL); |
| 81 | if (full_path == NULL) | 86 | if (full_path == NULL) |
| 82 | return full_path; | 87 | return full_path; |
| 83 | full_path[namelen] = 0; /* trailing null */ | 88 | full_path[namelen] = 0; /* trailing null */ |
| 89 | rcu_read_lock(); | ||
| 84 | for (temp = direntry; !IS_ROOT(temp);) { | 90 | for (temp = direntry; !IS_ROOT(temp);) { |
| 91 | spin_lock(&temp->d_lock); | ||
| 85 | namelen -= 1 + temp->d_name.len; | 92 | namelen -= 1 + temp->d_name.len; |
| 86 | if (namelen < 0) { | 93 | if (namelen < 0) { |
| 94 | spin_unlock(&temp->d_lock); | ||
| 87 | break; | 95 | break; |
| 88 | } else { | 96 | } else { |
| 89 | full_path[namelen] = dirsep; | 97 | full_path[namelen] = dirsep; |
| @@ -91,14 +99,17 @@ cifs_bp_rename_retry: | |||
| 91 | temp->d_name.len); | 99 | temp->d_name.len); |
| 92 | cFYI(0, "name: %s", full_path + namelen); | 100 | cFYI(0, "name: %s", full_path + namelen); |
| 93 | } | 101 | } |
| 102 | spin_unlock(&temp->d_lock); | ||
| 94 | temp = temp->d_parent; | 103 | temp = temp->d_parent; |
| 95 | if (temp == NULL) { | 104 | if (temp == NULL) { |
| 96 | cERROR(1, "corrupt dentry"); | 105 | cERROR(1, "corrupt dentry"); |
| 106 | rcu_read_unlock(); | ||
| 97 | kfree(full_path); | 107 | kfree(full_path); |
| 98 | return NULL; | 108 | return NULL; |
| 99 | } | 109 | } |
| 100 | } | 110 | } |
| 101 | if (namelen != dfsplen) { | 111 | rcu_read_unlock(); |
| 112 | if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) { | ||
| 102 | cERROR(1, "did not end path lookup where expected namelen is %d", | 113 | cERROR(1, "did not end path lookup where expected namelen is %d", |
| 103 | namelen); | 114 | namelen); |
| 104 | /* presumably this is only possible if racing with a rename | 115 | /* presumably this is only possible if racing with a rename |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index e141939080f0..739fb59bcdc2 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
| @@ -37,7 +37,7 @@ static DEFINE_MUTEX(read_mutex); | |||
| 37 | /* These macros may change in future, to provide better st_ino semantics. */ | 37 | /* These macros may change in future, to provide better st_ino semantics. */ |
| 38 | #define OFFSET(x) ((x)->i_ino) | 38 | #define OFFSET(x) ((x)->i_ino) |
| 39 | 39 | ||
| 40 | static unsigned long cramino(struct cramfs_inode *cino, unsigned int offset) | 40 | static unsigned long cramino(const struct cramfs_inode *cino, unsigned int offset) |
| 41 | { | 41 | { |
| 42 | if (!cino->offset) | 42 | if (!cino->offset) |
| 43 | return offset + 1; | 43 | return offset + 1; |
| @@ -61,7 +61,7 @@ static unsigned long cramino(struct cramfs_inode *cino, unsigned int offset) | |||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static struct inode *get_cramfs_inode(struct super_block *sb, | 63 | static struct inode *get_cramfs_inode(struct super_block *sb, |
| 64 | struct cramfs_inode *cramfs_inode, unsigned int offset) | 64 | const struct cramfs_inode *cramfs_inode, unsigned int offset) |
| 65 | { | 65 | { |
| 66 | struct inode *inode; | 66 | struct inode *inode; |
| 67 | static struct timespec zerotime; | 67 | static struct timespec zerotime; |
| @@ -317,7 +317,7 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 317 | /* Set it all up.. */ | 317 | /* Set it all up.. */ |
| 318 | sb->s_op = &cramfs_ops; | 318 | sb->s_op = &cramfs_ops; |
| 319 | root = get_cramfs_inode(sb, &super.root, 0); | 319 | root = get_cramfs_inode(sb, &super.root, 0); |
| 320 | if (!root) | 320 | if (IS_ERR(root)) |
| 321 | goto out; | 321 | goto out; |
| 322 | sb->s_root = d_alloc_root(root); | 322 | sb->s_root = d_alloc_root(root); |
| 323 | if (!sb->s_root) { | 323 | if (!sb->s_root) { |
| @@ -423,6 +423,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 423 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 423 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
| 424 | { | 424 | { |
| 425 | unsigned int offset = 0; | 425 | unsigned int offset = 0; |
| 426 | struct inode *inode = NULL; | ||
| 426 | int sorted; | 427 | int sorted; |
| 427 | 428 | ||
| 428 | mutex_lock(&read_mutex); | 429 | mutex_lock(&read_mutex); |
| @@ -449,8 +450,8 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s | |||
| 449 | 450 | ||
| 450 | for (;;) { | 451 | for (;;) { |
| 451 | if (!namelen) { | 452 | if (!namelen) { |
| 452 | mutex_unlock(&read_mutex); | 453 | inode = ERR_PTR(-EIO); |
| 453 | return ERR_PTR(-EIO); | 454 | goto out; |
| 454 | } | 455 | } |
| 455 | if (name[namelen-1]) | 456 | if (name[namelen-1]) |
| 456 | break; | 457 | break; |
| @@ -462,17 +463,18 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s | |||
| 462 | if (retval > 0) | 463 | if (retval > 0) |
| 463 | continue; | 464 | continue; |
| 464 | if (!retval) { | 465 | if (!retval) { |
| 465 | struct cramfs_inode entry = *de; | 466 | inode = get_cramfs_inode(dir->i_sb, de, dir_off); |
| 466 | mutex_unlock(&read_mutex); | 467 | break; |
| 467 | d_add(dentry, get_cramfs_inode(dir->i_sb, &entry, dir_off)); | ||
| 468 | return NULL; | ||
| 469 | } | 468 | } |
| 470 | /* else (retval < 0) */ | 469 | /* else (retval < 0) */ |
| 471 | if (sorted) | 470 | if (sorted) |
| 472 | break; | 471 | break; |
| 473 | } | 472 | } |
| 473 | out: | ||
| 474 | mutex_unlock(&read_mutex); | 474 | mutex_unlock(&read_mutex); |
| 475 | d_add(dentry, NULL); | 475 | if (IS_ERR(inode)) |
| 476 | return ERR_CAST(inode); | ||
| 477 | d_add(dentry, inode); | ||
| 476 | return NULL; | 478 | return NULL; |
| 477 | } | 479 | } |
| 478 | 480 | ||
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 06065bd37fc3..c57beddcc217 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
| @@ -913,7 +913,7 @@ struct dentry *exofs_get_parent(struct dentry *child) | |||
| 913 | unsigned long ino = exofs_parent_ino(child); | 913 | unsigned long ino = exofs_parent_ino(child); |
| 914 | 914 | ||
| 915 | if (!ino) | 915 | if (!ino) |
| 916 | return NULL; | 916 | return ERR_PTR(-ESTALE); |
| 917 | 917 | ||
| 918 | return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino)); | 918 | return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino)); |
| 919 | } | 919 | } |
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index 87ed48e0343d..85c098a499f3 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c | |||
| @@ -139,7 +139,8 @@ static int file_removed(struct dentry *dentry, const char *file) | |||
| 139 | static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | 139 | static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, |
| 140 | struct nameidata *nd) | 140 | struct nameidata *nd) |
| 141 | { | 141 | { |
| 142 | struct dentry *proc_dentry, *new, *parent; | 142 | struct dentry *proc_dentry, *parent; |
| 143 | struct qstr *name = &dentry->d_name; | ||
| 143 | struct inode *inode; | 144 | struct inode *inode; |
| 144 | int err, deleted; | 145 | int err, deleted; |
| 145 | 146 | ||
| @@ -149,23 +150,9 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | |||
| 149 | else if (deleted) | 150 | else if (deleted) |
| 150 | return ERR_PTR(-ENOENT); | 151 | return ERR_PTR(-ENOENT); |
| 151 | 152 | ||
| 152 | err = -ENOMEM; | ||
| 153 | parent = HPPFS_I(ino)->proc_dentry; | 153 | parent = HPPFS_I(ino)->proc_dentry; |
| 154 | mutex_lock(&parent->d_inode->i_mutex); | 154 | mutex_lock(&parent->d_inode->i_mutex); |
| 155 | proc_dentry = d_lookup(parent, &dentry->d_name); | 155 | proc_dentry = lookup_one_len(name->name, parent, name->len); |
| 156 | if (proc_dentry == NULL) { | ||
| 157 | proc_dentry = d_alloc(parent, &dentry->d_name); | ||
| 158 | if (proc_dentry == NULL) { | ||
| 159 | mutex_unlock(&parent->d_inode->i_mutex); | ||
| 160 | goto out; | ||
| 161 | } | ||
| 162 | new = (*parent->d_inode->i_op->lookup)(parent->d_inode, | ||
| 163 | proc_dentry, NULL); | ||
| 164 | if (new) { | ||
| 165 | dput(proc_dentry); | ||
| 166 | proc_dentry = new; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | mutex_unlock(&parent->d_inode->i_mutex); | 156 | mutex_unlock(&parent->d_inode->i_mutex); |
| 170 | 157 | ||
| 171 | if (IS_ERR(proc_dentry)) | 158 | if (IS_ERR(proc_dentry)) |
| @@ -174,13 +161,11 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | |||
| 174 | err = -ENOMEM; | 161 | err = -ENOMEM; |
| 175 | inode = get_inode(ino->i_sb, proc_dentry); | 162 | inode = get_inode(ino->i_sb, proc_dentry); |
| 176 | if (!inode) | 163 | if (!inode) |
| 177 | goto out_dput; | 164 | goto out; |
| 178 | 165 | ||
| 179 | d_add(dentry, inode); | 166 | d_add(dentry, inode); |
| 180 | return NULL; | 167 | return NULL; |
| 181 | 168 | ||
| 182 | out_dput: | ||
| 183 | dput(proc_dentry); | ||
| 184 | out: | 169 | out: |
| 185 | return ERR_PTR(err); | 170 | return ERR_PTR(err); |
| 186 | } | 171 | } |
| @@ -690,8 +675,10 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) | |||
| 690 | struct inode *proc_ino = dentry->d_inode; | 675 | struct inode *proc_ino = dentry->d_inode; |
| 691 | struct inode *inode = new_inode(sb); | 676 | struct inode *inode = new_inode(sb); |
| 692 | 677 | ||
| 693 | if (!inode) | 678 | if (!inode) { |
| 679 | dput(dentry); | ||
| 694 | return ERR_PTR(-ENOMEM); | 680 | return ERR_PTR(-ENOMEM); |
| 681 | } | ||
| 695 | 682 | ||
| 696 | if (S_ISDIR(dentry->d_inode->i_mode)) { | 683 | if (S_ISDIR(dentry->d_inode->i_mode)) { |
| 697 | inode->i_op = &hppfs_dir_iops; | 684 | inode->i_op = &hppfs_dir_iops; |
| @@ -704,7 +691,7 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) | |||
| 704 | inode->i_fop = &hppfs_file_fops; | 691 | inode->i_fop = &hppfs_file_fops; |
| 705 | } | 692 | } |
| 706 | 693 | ||
| 707 | HPPFS_I(inode)->proc_dentry = dget(dentry); | 694 | HPPFS_I(inode)->proc_dentry = dentry; |
| 708 | 695 | ||
| 709 | inode->i_uid = proc_ino->i_uid; | 696 | inode->i_uid = proc_ino->i_uid; |
| 710 | inode->i_gid = proc_ino->i_gid; | 697 | inode->i_gid = proc_ino->i_gid; |
| @@ -737,7 +724,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) | |||
| 737 | sb->s_fs_info = proc_mnt; | 724 | sb->s_fs_info = proc_mnt; |
| 738 | 725 | ||
| 739 | err = -ENOMEM; | 726 | err = -ENOMEM; |
| 740 | root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root); | 727 | root_inode = get_inode(sb, dget(proc_mnt->mnt_sb->s_root)); |
| 741 | if (!root_inode) | 728 | if (!root_inode) |
| 742 | goto out_mntput; | 729 | goto out_mntput; |
| 743 | 730 | ||
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 29309e25417f..b57aab9a1184 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c | |||
| @@ -56,16 +56,12 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru | |||
| 56 | 56 | ||
| 57 | lock_ufs(dir->i_sb); | 57 | lock_ufs(dir->i_sb); |
| 58 | ino = ufs_inode_by_name(dir, &dentry->d_name); | 58 | ino = ufs_inode_by_name(dir, &dentry->d_name); |
| 59 | if (ino) { | 59 | if (ino) |
| 60 | inode = ufs_iget(dir->i_sb, ino); | 60 | inode = ufs_iget(dir->i_sb, ino); |
| 61 | if (IS_ERR(inode)) { | ||
| 62 | unlock_ufs(dir->i_sb); | ||
| 63 | return ERR_CAST(inode); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | unlock_ufs(dir->i_sb); | 61 | unlock_ufs(dir->i_sb); |
| 67 | d_add(dentry, inode); | 62 | if (IS_ERR(inode)) |
| 68 | return NULL; | 63 | return ERR_CAST(inode); |
| 64 | return d_splice_alias(inode, dentry); | ||
| 69 | } | 65 | } |
| 70 | 66 | ||
| 71 | /* | 67 | /* |
