@@ -109,7 +109,7 @@ public int access(Subject subject, Inode inode, int mode) throws IOException {
109
109
throw new InvalException ("invalid access mask" );
110
110
}
111
111
112
- Stat stat = _inner .getattr (inode );
112
+ Stat stat = _inner .getattr (innerInode ( inode ) );
113
113
if ((mode & ACCESS4_READ ) != 0 ) {
114
114
if (canAccess (inode , stat , ACE4_READ_DATA )) {
115
115
accessmask |= ACCESS4_READ ;
@@ -170,7 +170,7 @@ public int access(Subject subject, Inode inode, int mode) throws IOException {
170
170
}
171
171
}
172
172
173
- return accessmask & _inner .access (subject , inode , accessmask );
173
+ return accessmask & _inner .access (subject , innerInode ( inode ) , accessmask );
174
174
}
175
175
176
176
@ Override
@@ -181,12 +181,14 @@ public Inode create(Inode parent, Stat.Type type, String path, Subject subject,
181
181
effectiveSubject = subject ;
182
182
}
183
183
184
+ Inode innerParent = innerInode (parent );
185
+
184
186
if (inheritUidGid (parent )) {
185
- Stat s = _inner .getattr (parent );
187
+ Stat s = _inner .getattr (innerParent );
186
188
effectiveSubject = toSubject (s .getUid (), s .getGid ());
187
189
}
188
190
189
- return pushExportIndex (parent , _inner .create (parent , type , path , effectiveSubject , mode ));
191
+ return pushExportIndex (parent , _inner .create (innerParent , type , path , effectiveSubject , mode ));
190
192
}
191
193
192
194
@ Override
@@ -220,18 +222,20 @@ public Inode lookup(Inode parent, String path) throws IOException {
220
222
throw new NoEntException ("the dcap magic file is blocked" );
221
223
}
222
224
223
- return pushExportIndex (parent , _inner .lookup (parent , path ));
225
+ return pushExportIndex (parent , _inner .lookup (innerInode ( parent ) , path ));
224
226
}
225
227
226
228
@ Override
227
229
public Inode link (Inode parent , Inode link , String path , Subject subject ) throws IOException {
228
230
checkAccess (link , ACE4_WRITE_ATTRIBUTES );
229
231
Subject effectiveSubject = checkAccess (parent , ACE4_ADD_FILE );
232
+
233
+ Inode innerParent = innerInode (parent );
230
234
if (inheritUidGid (parent )) {
231
- Stat s = _inner .getattr (parent );
235
+ Stat s = _inner .getattr (innerParent );
232
236
effectiveSubject = toSubject (s .getUid (), s .getGid ());
233
237
}
234
- return pushExportIndex (parent , _inner .link (parent , link , path , effectiveSubject ));
238
+ return pushExportIndex (parent , _inner .link (innerParent , link , path , effectiveSubject ));
235
239
}
236
240
237
241
@ Override
@@ -240,7 +244,7 @@ public DirectoryStream list(Inode inode, byte[] verifier, long cookie) throws IO
240
244
if (inode .isPseudoInode ()) {
241
245
return new DirectoryStream (listPseudoDirectory (inode )).tail (cookie );
242
246
}
243
- DirectoryStream innerStrem = _inner .list (inode , verifier , cookie );
247
+ DirectoryStream innerStrem = _inner .list (innerInode ( inode ) , verifier , cookie );
244
248
return innerStrem .transform (new PushParentIndex (inode ));
245
249
}
246
250
@@ -251,24 +255,25 @@ public Inode mkdir(Inode parent, String path, Subject subject, int mode) throws
251
255
effectiveSubject = subject ;
252
256
}
253
257
258
+ Inode innerParent = innerInode (parent );
254
259
if (inheritUidGid (parent )) {
255
- Stat s = _inner .getattr (parent );
260
+ Stat s = _inner .getattr (innerParent );
256
261
effectiveSubject = toSubject (s .getUid (), s .getGid ());
257
262
}
258
- return pushExportIndex (parent , _inner .mkdir (parent , path , effectiveSubject , mode ));
263
+ return pushExportIndex (parent , _inner .mkdir (innerParent , path , effectiveSubject , mode ));
259
264
}
260
265
261
266
@ Override
262
267
public boolean move (Inode src , String oldName , Inode dest , String newName ) throws IOException {
263
268
checkAccess (src , ACE4_DELETE_CHILD );
264
269
checkAccess (dest , ACE4_ADD_FILE | ACE4_DELETE_CHILD );
265
- return _inner .move (src , oldName , dest , newName );
270
+ return _inner .move (innerInode ( src ) , oldName , innerInode ( dest ) , newName );
266
271
}
267
272
268
273
@ Override
269
274
public Inode parentOf (Inode inode ) throws IOException {
270
275
271
- Inode parent = _inner .parentOf (inode );
276
+ Inode parent = _inner .parentOf (innerInode ( inode ) );
272
277
Inode asPseudo = realToPseudo (parent );
273
278
if (isPseudoDirectory (asPseudo )) {
274
279
/*
@@ -283,64 +288,67 @@ public Inode parentOf(Inode inode) throws IOException {
283
288
@ Override
284
289
public int read (Inode inode , byte [] data , long offset , int count ) throws IOException {
285
290
checkAccess (inode , ACE4_READ_DATA );
286
- return _inner .read (inode , data , offset , count );
291
+ return _inner .read (innerInode ( inode ) , data , offset , count );
287
292
}
288
293
289
294
@ Override
290
295
public int read (Inode inode , ByteBuffer data , long offset ) throws IOException {
291
296
checkAccess (inode , ACE4_READ_DATA );
292
- return _inner .read (inode , data , offset );
297
+ return _inner .read (innerInode ( inode ) , data , offset );
293
298
}
294
299
295
300
@ Override
296
301
public String readlink (Inode inode ) throws IOException {
297
302
checkAccess (inode , ACE4_READ_DATA );
298
- return _inner .readlink (inode );
303
+ return _inner .readlink (innerInode ( inode ) );
299
304
}
300
305
301
306
@ Override
302
307
public void remove (Inode parent , String path ) throws IOException {
308
+ Inode innerParent = innerInode (parent );
303
309
try {
304
310
checkAccess (parent , ACE4_DELETE_CHILD );
305
311
} catch (ChimeraNFSException e ) {
306
312
if (e .getStatus () == nfsstat .NFSERR_ACCESS ) {
307
- Inode inode = pushExportIndex (parent , _inner .lookup (parent , path ));
313
+ Inode inode = pushExportIndex (parent , _inner .lookup (innerParent , path ));
308
314
checkAccess (inode , ACE4_DELETE );
309
315
} else {
310
316
throw e ;
311
317
}
312
318
}
313
- _inner .remove (parent , path );
319
+ _inner .remove (innerParent , path );
314
320
}
315
321
316
322
@ Override
317
323
public Inode symlink (Inode parent , String path , String link , Subject subject , int mode ) throws IOException {
324
+ Inode innerParent = innerInode (parent );
325
+
318
326
Subject effectiveSubject = checkAccess (parent , ACE4_ADD_FILE );
319
327
if (inheritUidGid (parent )) {
320
- Stat s = _inner .getattr (parent );
328
+ Stat s = _inner .getattr (innerParent );
321
329
effectiveSubject = toSubject (s .getUid (), s .getGid ());
322
330
}
323
- return pushExportIndex (parent , _inner .symlink (parent , path , link , effectiveSubject , mode ));
331
+ return pushExportIndex (parent , _inner .symlink (innerParent , path , link , effectiveSubject , mode ));
324
332
}
325
333
326
334
@ Override
327
335
public WriteResult write (Inode inode , byte [] data , long offset , int count , StabilityLevel stabilityLevel )
328
336
throws IOException {
329
337
checkAccess (inode , ACE4_WRITE_DATA );
330
- return _inner .write (inode , data , offset , count , stabilityLevel );
338
+ return _inner .write (innerInode ( inode ) , data , offset , count , stabilityLevel );
331
339
}
332
340
333
341
@ Override
334
342
public WriteResult write (Inode inode , ByteBuffer data , long offset , StabilityLevel stabilityLevel )
335
343
throws IOException {
336
344
checkAccess (inode , ACE4_WRITE_DATA );
337
- return _inner .write (inode , data , offset , stabilityLevel );
345
+ return _inner .write (innerInode ( inode ) , data , offset , stabilityLevel );
338
346
}
339
347
340
348
@ Override
341
349
public Stat getattr (Inode inode ) throws IOException {
342
350
checkAccess (inode , ACE4_READ_ATTRIBUTES );
343
- return _inner .getattr (inode );
351
+ return _inner .getattr (innerInode ( inode ) );
344
352
}
345
353
346
354
@ Override
@@ -368,51 +376,51 @@ public void setattr(Inode inode, Stat stat) throws IOException {
368
376
}
369
377
370
378
checkAccess (inode , mask );
371
- _inner .setattr (inode , stat );
379
+ _inner .setattr (innerInode ( inode ) , stat );
372
380
}
373
381
374
382
@ Override
375
383
public nfsace4 [] getAcl (Inode inode ) throws IOException {
376
384
checkAccess (inode , ACE4_READ_ACL );
377
- return _inner .getAcl (inode );
385
+ return _inner .getAcl (innerInode ( inode ) );
378
386
}
379
387
380
388
@ Override
381
389
public void setAcl (Inode inode , nfsace4 [] acl ) throws IOException {
382
390
checkAccess (inode , ACE4_WRITE_ACL );
383
- _inner .setAcl (inode , acl );
391
+ _inner .setAcl (innerInode ( inode ) , acl );
384
392
}
385
393
386
394
@ Override
387
395
public byte [] getXattr (Inode inode , String attr ) throws IOException {
388
396
checkAccess (inode , ACE4_READ_DATA );
389
- return _inner .getXattr (inode , attr );
397
+ return _inner .getXattr (innerInode ( inode ) , attr );
390
398
}
391
399
392
400
@ Override
393
401
public void setXattr (Inode inode , String attr , byte [] value , SetXattrMode mode ) throws IOException {
394
402
checkAccess (inode , ACE4_WRITE_DATA );
395
- _inner .setXattr (inode , attr , value , mode );
403
+ _inner .setXattr (innerInode ( inode ) , attr , value , mode );
396
404
}
397
405
398
406
@ Override
399
407
public String [] listXattrs (Inode inode ) throws IOException {
400
408
checkAccess (inode , ACE4_READ_DATA );
401
- return _inner .listXattrs (inode );
409
+ return _inner .listXattrs (innerInode ( inode ) );
402
410
}
403
411
404
412
@ Override
405
413
public void removeXattr (Inode inode , String attr ) throws IOException {
406
414
checkAccess (inode , ACE4_WRITE_DATA );
407
- _inner .removeXattr (inode , attr );
415
+ _inner .removeXattr (innerInode ( inode ) , attr );
408
416
}
409
417
410
418
private Subject checkAccess (Inode inode , int requestedMask ) throws IOException {
411
419
return checkAccess (inode , requestedMask , true );
412
420
}
413
421
414
422
private Subject checkAccess (Inode inode , int requestedMask , boolean shouldLog ) throws IOException {
415
- return checkAccess (inode , _inner .getattr (inode ), requestedMask , shouldLog );
423
+ return checkAccess (inode , _inner .getattr (innerInode ( inode ) ), requestedMask , shouldLog );
416
424
}
417
425
418
426
private Subject checkAccess (Inode inode , Stat stat , int requestedMask , boolean shouldLog ) throws IOException {
@@ -467,7 +475,7 @@ private Subject checkAccess(Inode inode, Stat stat, int requestedMask, boolean s
467
475
}
468
476
469
477
if (export .checkAcls ()) {
470
- aclMatched = _inner .getAclCheckable ().checkAcl (_subject , inode , requestedMask );
478
+ aclMatched = _inner .getAclCheckable ().checkAcl (_subject , innerInode ( inode ) , requestedMask );
471
479
if (aclMatched == Access .DENY ) {
472
480
if (shouldLog ) {
473
481
_log .warn ("Access deny: {} {} {}" , _inetAddress , acemask4 .toString (requestedMask ),
@@ -586,14 +594,15 @@ private Collection<DirectoryEntry> listPseudoDirectory(Inode parent) throws Chim
586
594
for (PseudoFsNode node : nodes ) {
587
595
if (node .id ().equals (parent )) {
588
596
if (node .isMountPoint ()) {
589
- return newArrayList (_inner .list (parent , null , 0L ).transform (new ConvertToRealInode (node )));
597
+ return newArrayList (_inner .list (innerInode (parent ), null , 0L ).transform (new ConvertToRealInode (
598
+ node )));
590
599
} else {
591
600
long cookie = 3 ; // artificial cookie. Values 0, 1 and 2 are reserved.
592
601
List <DirectoryEntry > pseudoLs = new ArrayList <>();
593
602
for (String s : node .getChildren ()) {
594
603
PseudoFsNode subNode = node .getChild (s );
595
604
Inode inode = subNode .id ();
596
- Stat stat = _inner .getattr (inode );
605
+ Stat stat = _inner .getattr (innerInode ( inode ) );
597
606
DirectoryEntry e = new DirectoryEntry (s ,
598
607
subNode .isMountPoint ()
599
608
? pseudoIdToReal (inode , getIndexId (subNode )) : inode , stat , cookie );
@@ -653,7 +662,7 @@ private void pathToPseudoFs(final PseudoFsNode root, Set<PseudoFsNode> all, FsEx
653
662
try {
654
663
PseudoFsNode node = parent .getChild (s );
655
664
if (node == null ) {
656
- node = new PseudoFsNode (realToPseudo (_inner .lookup (parent .id (), s )));
665
+ node = new PseudoFsNode (realToPseudo (_inner .lookup (innerInode ( parent .id () ), s )));
657
666
parent .addChild (s , node );
658
667
pathNodes .add (node );
659
668
}
@@ -724,4 +733,21 @@ private static void checkSecurityFlavor(RpcAuth auth, FsExport.Sec minFlavor) th
724
733
private boolean inheritUidGid (Inode inode ) {
725
734
return _exportTable .getExport (inode .exportIndex (), _inetAddress .getAddress ()).isAllRoot ();
726
735
}
736
+
737
+ /**
738
+ * Convert an {@link Inode} that is used by {@link PseudoFs} to an {@link Inode} that is understood
739
+ * by the underlying file system.
740
+ * <p>
741
+ * We currently store additional information such as "ExportId" and "PseudoInode" as parts of the Inode.
742
+ * {@link VirtualFileSystem}s that store {@link Inode} as a whole (rather than only the "fileId" bit)
743
+ * may not recognize such objects, unless we remove this additional information.
744
+ * <p>
745
+ * Once {@link PseudoFs} handles this configuration internally, we can remove this conversion step.
746
+ *
747
+ * @param inode The {@link Inode} as passed from and to the NFS client.
748
+ * @return The {@link Inode} as passed from {@link PseudoFs} to the underlying {@link VirtualFileSystem}.
749
+ */
750
+ private Inode innerInode (Inode inode ) {
751
+ return Inode .forFile (inode .getFileId ());
752
+ }
727
753
}
0 commit comments