@@ -256,12 +256,9 @@ void v9fs_set_netfs_context(struct inode *inode)
256256}
257257
258258int v9fs_init_inode (struct v9fs_session_info * v9ses ,
259- struct inode * inode , struct p9_qid * qid , umode_t mode , dev_t rdev )
259+ struct inode * inode , umode_t mode , dev_t rdev )
260260{
261261 int err = 0 ;
262- struct v9fs_inode * v9inode = V9FS_I (inode );
263-
264- memcpy (& v9inode -> qid , qid , sizeof (struct p9_qid ));
265262
266263 inode_init_owner (& nop_mnt_idmap , inode , NULL , mode );
267264 inode -> i_blocks = 0 ;
@@ -365,59 +362,105 @@ void v9fs_evict_inode(struct inode *inode)
365362 clear_inode (inode );
366363}
367364
368- struct inode *
369- v9fs_fid_iget (struct super_block * sb , struct p9_fid * fid , bool new )
365+ static int v9fs_test_inode (struct inode * inode , void * data )
366+ {
367+ int umode ;
368+ dev_t rdev ;
369+ struct v9fs_inode * v9inode = V9FS_I (inode );
370+ struct p9_wstat * st = (struct p9_wstat * )data ;
371+ struct v9fs_session_info * v9ses = v9fs_inode2v9ses (inode );
372+
373+ umode = p9mode2unixmode (v9ses , st , & rdev );
374+ /* don't match inode of different type */
375+ if (inode_wrong_type (inode , umode ))
376+ return 0 ;
377+
378+ /* compare qid details */
379+ if (memcmp (& v9inode -> qid .version ,
380+ & st -> qid .version , sizeof (v9inode -> qid .version )))
381+ return 0 ;
382+
383+ if (v9inode -> qid .type != st -> qid .type )
384+ return 0 ;
385+
386+ if (v9inode -> qid .path != st -> qid .path )
387+ return 0 ;
388+ return 1 ;
389+ }
390+
391+ static int v9fs_test_new_inode (struct inode * inode , void * data )
392+ {
393+ return 0 ;
394+ }
395+
396+ static int v9fs_set_inode (struct inode * inode , void * data )
397+ {
398+ struct v9fs_inode * v9inode = V9FS_I (inode );
399+ struct p9_wstat * st = (struct p9_wstat * )data ;
400+
401+ memcpy (& v9inode -> qid , & st -> qid , sizeof (st -> qid ));
402+ return 0 ;
403+ }
404+
405+ static struct inode * v9fs_qid_iget (struct super_block * sb ,
406+ struct p9_qid * qid ,
407+ struct p9_wstat * st ,
408+ int new )
370409{
371410 dev_t rdev ;
372411 int retval ;
373412 umode_t umode ;
374413 struct inode * inode ;
375- struct p9_wstat * st ;
376414 struct v9fs_session_info * v9ses = sb -> s_fs_info ;
415+ int (* test )(struct inode * inode , void * data );
377416
378- inode = iget_locked (sb , QID2INO (& fid -> qid ));
379- if (unlikely (!inode ))
380- return ERR_PTR (- ENOMEM );
381- if (!(inode -> i_state & I_NEW )) {
382- if (!new ) {
383- goto done ;
384- } else {
385- p9_debug (P9_DEBUG_VFS , "WARNING: Inode collision %ld\n" ,
386- inode -> i_ino );
387- iput (inode );
388- remove_inode_hash (inode );
389- inode = iget_locked (sb , QID2INO (& fid -> qid ));
390- WARN_ON (!(inode -> i_state & I_NEW ));
391- }
392- }
417+ if (new )
418+ test = v9fs_test_new_inode ;
419+ else
420+ test = v9fs_test_inode ;
393421
422+ inode = iget5_locked (sb , QID2INO (qid ), test , v9fs_set_inode , st );
423+ if (!inode )
424+ return ERR_PTR (- ENOMEM );
425+ if (!(inode -> i_state & I_NEW ))
426+ return inode ;
394427 /*
395428 * initialize the inode with the stat info
396429 * FIXME!! we may need support for stale inodes
397430 * later.
398431 */
399- st = p9_client_stat (fid );
400- if (IS_ERR (st )) {
401- retval = PTR_ERR (st );
402- goto error ;
403- }
404-
432+ inode -> i_ino = QID2INO (qid );
405433 umode = p9mode2unixmode (v9ses , st , & rdev );
406- retval = v9fs_init_inode (v9ses , inode , & fid -> qid , umode , rdev );
407- v9fs_stat2inode (st , inode , sb , 0 );
408- p9stat_free (st );
409- kfree (st );
434+ retval = v9fs_init_inode (v9ses , inode , umode , rdev );
410435 if (retval )
411436 goto error ;
412437
438+ v9fs_stat2inode (st , inode , sb , 0 );
413439 v9fs_set_netfs_context (inode );
414440 v9fs_cache_inode_get_cookie (inode );
415441 unlock_new_inode (inode );
416- done :
417442 return inode ;
418443error :
419444 iget_failed (inode );
420445 return ERR_PTR (retval );
446+
447+ }
448+
449+ struct inode *
450+ v9fs_inode_from_fid (struct v9fs_session_info * v9ses , struct p9_fid * fid ,
451+ struct super_block * sb , int new )
452+ {
453+ struct p9_wstat * st ;
454+ struct inode * inode = NULL ;
455+
456+ st = p9_client_stat (fid );
457+ if (IS_ERR (st ))
458+ return ERR_CAST (st );
459+
460+ inode = v9fs_qid_iget (sb , & st -> qid , st , new );
461+ p9stat_free (st );
462+ kfree (st );
463+ return inode ;
421464}
422465
423466/**
@@ -449,15 +492,8 @@ static int v9fs_at_to_dotl_flags(int flags)
449492 */
450493static void v9fs_dec_count (struct inode * inode )
451494{
452- if (!S_ISDIR (inode -> i_mode ) || inode -> i_nlink > 2 ) {
453- if (inode -> i_nlink ) {
454- drop_nlink (inode );
455- } else {
456- p9_debug (P9_DEBUG_VFS ,
457- "WARNING: unexpected i_nlink zero %d inode %ld\n" ,
458- inode -> i_nlink , inode -> i_ino );
459- }
460- }
495+ if (!S_ISDIR (inode -> i_mode ) || inode -> i_nlink > 2 )
496+ drop_nlink (inode );
461497}
462498
463499/**
@@ -508,9 +544,6 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
508544 } else
509545 v9fs_dec_count (inode );
510546
511- if (inode -> i_nlink <= 0 ) /* no more refs unhash it */
512- remove_inode_hash (inode );
513-
514547 v9fs_invalidate_inode_attr (inode );
515548 v9fs_invalidate_inode_attr (dir );
516549
@@ -576,7 +609,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
576609 /*
577610 * instantiate inode and assign the unopened fid to the dentry
578611 */
579- inode = v9fs_get_inode_from_fid (v9ses , fid , dir -> i_sb , true );
612+ inode = v9fs_get_new_inode_from_fid (v9ses , fid , dir -> i_sb );
580613 if (IS_ERR (inode )) {
581614 err = PTR_ERR (inode );
582615 p9_debug (P9_DEBUG_VFS ,
@@ -704,8 +737,10 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
704737 inode = NULL ;
705738 else if (IS_ERR (fid ))
706739 inode = ERR_CAST (fid );
740+ else if (v9ses -> cache & (CACHE_META |CACHE_LOOSE ))
741+ inode = v9fs_get_inode_from_fid (v9ses , fid , dir -> i_sb );
707742 else
708- inode = v9fs_get_inode_from_fid (v9ses , fid , dir -> i_sb , false );
743+ inode = v9fs_get_new_inode_from_fid (v9ses , fid , dir -> i_sb );
709744 /*
710745 * If we had a rename on the server and a parallel lookup
711746 * for the new name, then make sure we instantiate with
0 commit comments