@@ -256,12 +256,9 @@ void v9fs_set_netfs_context(struct inode *inode)
256
256
}
257
257
258
258
int 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 )
260
260
{
261
261
int err = 0 ;
262
- struct v9fs_inode * v9inode = V9FS_I (inode );
263
-
264
- memcpy (& v9inode -> qid , qid , sizeof (struct p9_qid ));
265
262
266
263
inode_init_owner (& nop_mnt_idmap , inode , NULL , mode );
267
264
inode -> i_blocks = 0 ;
@@ -365,59 +362,105 @@ void v9fs_evict_inode(struct inode *inode)
365
362
clear_inode (inode );
366
363
}
367
364
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 )
370
409
{
371
410
dev_t rdev ;
372
411
int retval ;
373
412
umode_t umode ;
374
413
struct inode * inode ;
375
- struct p9_wstat * st ;
376
414
struct v9fs_session_info * v9ses = sb -> s_fs_info ;
415
+ int (* test )(struct inode * inode , void * data );
377
416
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 ;
393
421
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 ;
394
427
/*
395
428
* initialize the inode with the stat info
396
429
* FIXME!! we may need support for stale inodes
397
430
* later.
398
431
*/
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 );
405
433
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 );
410
435
if (retval )
411
436
goto error ;
412
437
438
+ v9fs_stat2inode (st , inode , sb , 0 );
413
439
v9fs_set_netfs_context (inode );
414
440
v9fs_cache_inode_get_cookie (inode );
415
441
unlock_new_inode (inode );
416
- done :
417
442
return inode ;
418
443
error :
419
444
iget_failed (inode );
420
445
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 ;
421
464
}
422
465
423
466
/**
@@ -449,15 +492,8 @@ static int v9fs_at_to_dotl_flags(int flags)
449
492
*/
450
493
static void v9fs_dec_count (struct inode * inode )
451
494
{
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 );
461
497
}
462
498
463
499
/**
@@ -508,9 +544,6 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
508
544
} else
509
545
v9fs_dec_count (inode );
510
546
511
- if (inode -> i_nlink <= 0 ) /* no more refs unhash it */
512
- remove_inode_hash (inode );
513
-
514
547
v9fs_invalidate_inode_attr (inode );
515
548
v9fs_invalidate_inode_attr (dir );
516
549
@@ -576,7 +609,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
576
609
/*
577
610
* instantiate inode and assign the unopened fid to the dentry
578
611
*/
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 );
580
613
if (IS_ERR (inode )) {
581
614
err = PTR_ERR (inode );
582
615
p9_debug (P9_DEBUG_VFS ,
@@ -704,8 +737,10 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
704
737
inode = NULL ;
705
738
else if (IS_ERR (fid ))
706
739
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 );
707
742
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 );
709
744
/*
710
745
* If we had a rename on the server and a parallel lookup
711
746
* for the new name, then make sure we instantiate with
0 commit comments