|
@@ -1840,6 +1840,33 @@ struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid,
|
|
return inode;
|
|
return inode;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Get an inode object given its location and corresponding root.
|
|
|
|
+ * Returns in *is_new if the inode was read from disk
|
|
|
|
+ */
|
|
|
|
+struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
|
|
|
+ struct btrfs_root *root, int *is_new)
|
|
|
|
+{
|
|
|
|
+ struct inode *inode;
|
|
|
|
+
|
|
|
|
+ inode = btrfs_iget_locked(s, location->objectid, root);
|
|
|
|
+ if (!inode)
|
|
|
|
+ return ERR_PTR(-EACCES);
|
|
|
|
+
|
|
|
|
+ if (inode->i_state & I_NEW) {
|
|
|
|
+ BTRFS_I(inode)->root = root;
|
|
|
|
+ memcpy(&BTRFS_I(inode)->location, location, sizeof(*location));
|
|
|
|
+ btrfs_read_locked_inode(inode);
|
|
|
|
+ unlock_new_inode(inode);
|
|
|
|
+ if (is_new)
|
|
|
|
+ *is_new = 1;
|
|
|
|
+ } else {
|
|
|
|
+ if (is_new)
|
|
|
|
+ *is_new = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return inode;
|
|
|
|
+}
|
|
|
|
+
|
|
static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
|
|
static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
|
|
struct nameidata *nd)
|
|
struct nameidata *nd)
|
|
{
|
|
{
|
|
@@ -1848,7 +1875,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
|
|
struct btrfs_root *root = bi->root;
|
|
struct btrfs_root *root = bi->root;
|
|
struct btrfs_root *sub_root = root;
|
|
struct btrfs_root *sub_root = root;
|
|
struct btrfs_key location;
|
|
struct btrfs_key location;
|
|
- int ret, do_orphan = 0;
|
|
|
|
|
|
+ int ret, new, do_orphan = 0;
|
|
|
|
|
|
if (dentry->d_name.len > BTRFS_NAME_LEN)
|
|
if (dentry->d_name.len > BTRFS_NAME_LEN)
|
|
return ERR_PTR(-ENAMETOOLONG);
|
|
return ERR_PTR(-ENAMETOOLONG);
|
|
@@ -1866,23 +1893,15 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
|
|
return ERR_PTR(ret);
|
|
return ERR_PTR(ret);
|
|
if (ret > 0)
|
|
if (ret > 0)
|
|
return ERR_PTR(-ENOENT);
|
|
return ERR_PTR(-ENOENT);
|
|
-
|
|
|
|
- inode = btrfs_iget_locked(dir->i_sb, location.objectid,
|
|
|
|
- sub_root);
|
|
|
|
- if (!inode)
|
|
|
|
- return ERR_PTR(-EACCES);
|
|
|
|
- if (inode->i_state & I_NEW) {
|
|
|
|
- /* the inode and parent dir are two different roots */
|
|
|
|
- if (sub_root != root) {
|
|
|
|
- igrab(inode);
|
|
|
|
- sub_root->inode = inode;
|
|
|
|
- do_orphan = 1;
|
|
|
|
- }
|
|
|
|
- BTRFS_I(inode)->root = sub_root;
|
|
|
|
- memcpy(&BTRFS_I(inode)->location, &location,
|
|
|
|
- sizeof(location));
|
|
|
|
- btrfs_read_locked_inode(inode);
|
|
|
|
- unlock_new_inode(inode);
|
|
|
|
|
|
+ inode = btrfs_iget(dir->i_sb, &location, sub_root, &new);
|
|
|
|
+ if (IS_ERR(inode))
|
|
|
|
+ return ERR_CAST(inode);
|
|
|
|
+
|
|
|
|
+ /* the inode and parent dir are two different roots */
|
|
|
|
+ if (new && root != sub_root) {
|
|
|
|
+ igrab(inode);
|
|
|
|
+ sub_root->inode = inode;
|
|
|
|
+ do_orphan = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|