return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
}
+/**
+ * GFS2 lookup code fills in vfs inode contents based on info obtained
+ * from directory entry inside gfs2_inode_lookup(). This has caused issues
+ * with NFS code path since its get_dentry routine doesn't have the relevant
+ * directory entry when gfs2_inode_lookup() is invoked. Part of the code
+ * segment inside gfs2_inode_lookup code needs to get moved around.
+ *
+ * Clean up I_LOCK and I_NEW as well.
+ **/
+
+void gfs2_set_iop(struct inode *inode)
+{
+ umode_t mode = inode->i_mode;
+
+ if (S_ISREG(mode)) {
+ inode->i_op = &gfs2_file_iops;
+ inode->i_fop = &gfs2_file_fops;
+ inode->i_mapping->a_ops = &gfs2_file_aops;
+ } else if (S_ISDIR(mode)) {
+ inode->i_op = &gfs2_dir_iops;
+ inode->i_fop = &gfs2_dir_fops;
+ } else if (S_ISLNK(mode)) {
+ inode->i_op = &gfs2_symlink_iops;
+ } else {
+ inode->i_op = &gfs2_dev_iops;
+ }
+
+ unlock_new_inode(inode);
+}
+
/**
* gfs2_inode_lookup - Lookup an inode
* @sb: The super block
* Returns: A VFS inode, or an error
*/
-struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned int type)
+struct inode *gfs2_inode_lookup(struct super_block *sb,
+ unsigned int type,
+ u64 no_addr,
+ u64 no_formal_ino)
{
struct inode *inode = gfs2_iget(sb, no_addr);
struct gfs2_inode *ip = GFS2_I(inode);
if (inode->i_state & I_NEW) {
struct gfs2_sbd *sdp = GFS2_SB(inode);
- umode_t mode = DT2IF(type);
inode->i_private = ip;
- inode->i_mode = mode;
-
- if (S_ISREG(mode)) {
- inode->i_op = &gfs2_file_iops;
- inode->i_fop = &gfs2_file_fops;
- inode->i_mapping->a_ops = &gfs2_file_aops;
- } else if (S_ISDIR(mode)) {
- inode->i_op = &gfs2_dir_iops;
- inode->i_fop = &gfs2_dir_fops;
- } else if (S_ISLNK(mode)) {
- inode->i_op = &gfs2_symlink_iops;
- } else {
- inode->i_op = &gfs2_dev_iops;
- }
+ ip->i_no_formal_ino = no_formal_ino;
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
if (unlikely(error))
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
if (unlikely(error))
goto fail_iopen;
+ ip->i_iopen_gh.gh_gl->gl_object = ip;
gfs2_glock_put(io_gl);
- unlock_new_inode(inode);
+
+ if ((type == DT_UNKNOWN) && (no_formal_ino == 0))
+ goto gfs2_nfsbypass;
+
+ inode->i_mode = DT2IF(type);
+
+ /*
+ * We must read the inode in order to work out its type in
+ * this case. Note that this doesn't happen often as we normally
+ * know the type beforehand. This code path only occurs during
+ * unlinked inode recovery (where it is safe to do this glock,
+ * which is not true in the general case).
+ */
+ if (type == DT_UNKNOWN) {
+ struct gfs2_holder gh;
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+ if (unlikely(error))
+ goto fail_glock;
+ /* Inode is now uptodate */
+ gfs2_glock_dq_uninit(&gh);
+ }
+
+ gfs2_set_iop(inode);
}
+gfs2_nfsbypass:
return inode;
+fail_glock:
+ gfs2_glock_dq(&ip->i_iopen_gh);
fail_iopen:
gfs2_glock_put(io_gl);
fail_put:
struct super_block *sb = dir->i_sb;
struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_holder d_gh;
- int error;
+ int error = 0;
struct inode *inode = NULL;
int unlock = 0;
if (error)
goto fail_gunlock2;
- inode = gfs2_inode_lookup(dir->i_sb, inum.no_addr, IF2DT(mode));
+ inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode),
+ inum.no_addr,
+ inum.no_formal_ino);
if (IS_ERR(inode))
goto fail_gunlock2;