Skip to content

Commit ecdd82e

Browse files
committed
nfs: remove transfer from the door list if pool selection failed
Motivation: As pNFS layouts are independent of file open, they are invalidated only when layout return is issued. The door logic creates a transfer, adds transfer into transfers list and then performs namespace lookup, pool selection and starting a mover. In cases, when pool selection fails due to stage protection or an attempt to overwrite, the layout get will return "permission deny", thus layout return will never be issued and transfer will stay in the door forever. Modification: Update layoutGet error handling such that on permission deny error pool less transfers will be removed. An unexpected conditions are logged. Result: orphan transfers like "WriteTransfer null@N/A," are removed when it's safe. Acked-by: Marina Sahakyan Target: master, 12.0, 11.2 Require-book: no Require-notes: yes
1 parent f46a968 commit ecdd82e

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

  • modules/dcache-nfs/src/main/java/org/dcache/chimera/nfsv41/door

‎modules/dcache-nfs/src/main/java/org/dcache/chimera/nfsv41/door/NFSv41Door.java‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ public Layout layoutGet(CompoundContext context, LAYOUTGET4args args)
802802
final stateid4 stateid = Stateids.getCurrentStateidIfNeeded(context, args.loga_stateid);
803803

804804
LayoutDriver layoutDriver = getLayoutDriver(layoutType);
805+
NfsTransfer transfer = null;
805806

806807
final NFS4Client client;
807808
if (context.getMinorversion() == 0) {
@@ -835,7 +836,7 @@ public Layout layoutGet(CompoundContext context, LAYOUTGET4args args)
835836
throw new LayoutUnavailableException("special DOT file");
836837
}
837838

838-
NfsTransfer transfer = layoutStateid != null ? _transfers.get(layoutStateid) : null;
839+
transfer = layoutStateid != null ? _transfers.get(layoutStateid) : null;
839840
if (transfer == null) {
840841
Transfer.initSession(false, false);
841842
NDC.push(pnfsId.toString());
@@ -911,6 +912,20 @@ public Layout layoutGet(CompoundContext context, LAYOUTGET4args args)
911912
*/
912913
client.releaseState(stateid);
913914
throw new StaleException("File is removed", e);
915+
} catch (PermissionDeniedCacheException e) {
916+
// pool selection due to stage protection or an overwrite attempt of an existing file.
917+
if (transfer.getPool() == null) {
918+
// safe to forget
919+
_log.error("Removing pool-less transfer for client {} for file {}: {}",
920+
toAddrString(context.getRemoteSocketAddress().getAddress()),
921+
transfer.getPnfsId(), e.getMessage());
922+
_transfers.remove(transfer.getStateid().stateid());
923+
} else {
924+
// should never happen
925+
_log.error("Report to support@dcache.org: Unexpected permission denied for transfer {} with assigned pool: {}", transfer, e.toString());
926+
}
927+
928+
throw new PermException(e.getMessage(), e);
914929
} catch (CacheException | ChimeraFsException | TimeoutException | ExecutionException e) {
915930
throw asNfsException(e, LayoutTryLaterException.class);
916931
} catch (InterruptedException e) {
@@ -1526,7 +1541,7 @@ deviceid4[] selectDataServers(long timeout) throws
15261541
* allow writes only into new files
15271542
*/
15281543
if (!attr.getStorageInfo().isCreatedOnly()) {
1529-
throw new PermException("Can't modify existing file");
1544+
throw new PermissionDeniedCacheException("Can't modify existing file");
15301545
}
15311546

15321547
// REVISIT: this have to go into Transfer class.

0 commit comments

Comments
 (0)