|
@@ -23,6 +23,7 @@ import java.io.IOException;
|
|
|
import java.net.DatagramSocket;
|
|
|
import java.net.InetAddress;
|
|
|
import java.net.InetSocketAddress;
|
|
|
+import java.net.SocketAddress;
|
|
|
import java.nio.ByteBuffer;
|
|
|
import java.util.EnumSet;
|
|
|
|
|
@@ -152,6 +153,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
private final short replication;
|
|
|
private final long blockSize;
|
|
|
private final int bufferSize;
|
|
|
+ private final boolean aixCompatMode;
|
|
|
private Statistics statistics;
|
|
|
private String writeDumpDir; // The dir save dump files
|
|
|
|
|
@@ -169,8 +171,11 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
config.set(FsPermission.UMASK_LABEL, "000");
|
|
|
iug = new IdUserGroup(config);
|
|
|
|
|
|
+ aixCompatMode = config.getBoolean(
|
|
|
+ NfsConfigKeys.AIX_COMPAT_MODE_KEY,
|
|
|
+ NfsConfigKeys.AIX_COMPAT_MODE_DEFAULT);
|
|
|
exports = NfsExports.getInstance(config);
|
|
|
- writeManager = new WriteManager(iug, config);
|
|
|
+ writeManager = new WriteManager(iug, config, aixCompatMode);
|
|
|
clientCache = new DFSClientCache(config);
|
|
|
replication = (short) config.getInt(DFSConfigKeys.DFS_REPLICATION_KEY,
|
|
|
DFSConfigKeys.DFS_REPLICATION_DEFAULT);
|
|
@@ -230,15 +235,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public GETATTR3Response getattr(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public GETATTR3Response getattr(XDR xdr, RpcInfo info) {
|
|
|
GETATTR3Response response = new GETATTR3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -322,9 +327,9 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public SETATTR3Response setattr(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public SETATTR3Response setattr(XDR xdr, RpcInfo info) {
|
|
|
SETATTR3Response response = new SETATTR3Response(Nfs3Status.NFS3_OK);
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -370,7 +375,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
// check the write access privilege
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_WRITE)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_WRITE)) {
|
|
|
return new SETATTR3Response(Nfs3Status.NFS3ERR_ACCES, new WccData(
|
|
|
preOpWcc, preOpAttr));
|
|
|
}
|
|
@@ -398,15 +403,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public LOOKUP3Response lookup(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public LOOKUP3Response lookup(XDR xdr, RpcInfo info) {
|
|
|
LOOKUP3Response response = new LOOKUP3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -460,15 +465,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ACCESS3Response access(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public ACCESS3Response access(XDR xdr, RpcInfo info) {
|
|
|
ACCESS3Response response = new ACCESS3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -519,15 +524,16 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public READLINK3Response readlink(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ @Override
|
|
|
+ public READLINK3Response readlink(XDR xdr, RpcInfo info) {
|
|
|
READLINK3Response response = new READLINK3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -591,12 +597,19 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public READ3Response read(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public READ3Response read(XDR xdr, RpcInfo info) {
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
+ SocketAddress remoteAddress = info.remoteAddress();
|
|
|
+ return read(xdr, securityHandler, remoteAddress);
|
|
|
+ }
|
|
|
+
|
|
|
+ @VisibleForTesting
|
|
|
+ READ3Response read(XDR xdr, SecurityHandler securityHandler,
|
|
|
+ SocketAddress remoteAddress) {
|
|
|
READ3Response response = new READ3Response(Nfs3Status.NFS3_OK);
|
|
|
final String userName = securityHandler.getUser();
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(remoteAddress, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
@@ -715,8 +728,17 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public WRITE3Response write(XDR xdr, Channel channel, int xid,
|
|
|
- SecurityHandler securityHandler, InetAddress client) {
|
|
|
+ public WRITE3Response write(XDR xdr, RpcInfo info) {
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
+ RpcCall rpcCall = (RpcCall) info.header();
|
|
|
+ int xid = rpcCall.getXid();
|
|
|
+ SocketAddress remoteAddress = info.remoteAddress();
|
|
|
+ return write(xdr, info.channel(), xid, securityHandler, remoteAddress);
|
|
|
+ }
|
|
|
+
|
|
|
+ @VisibleForTesting
|
|
|
+ WRITE3Response write(XDR xdr, Channel channel, int xid,
|
|
|
+ SecurityHandler securityHandler, SocketAddress remoteAddress) {
|
|
|
WRITE3Response response = new WRITE3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
@@ -758,7 +780,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
return new WRITE3Response(Nfs3Status.NFS3ERR_STALE);
|
|
|
}
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_WRITE)) {
|
|
|
+ if (!checkAccessPrivilege(remoteAddress, AccessPrivilege.READ_WRITE)) {
|
|
|
return new WRITE3Response(Nfs3Status.NFS3ERR_ACCES, new WccData(
|
|
|
Nfs3Utils.getWccAttr(preOpAttr), preOpAttr), 0, stableHow,
|
|
|
Nfs3Constant.WRITE_COMMIT_VERF);
|
|
@@ -791,8 +813,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public CREATE3Response create(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public CREATE3Response create(XDR xdr, RpcInfo info) {
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
+ SocketAddress remoteAddress = info.remoteAddress();
|
|
|
+ return create(xdr, securityHandler, remoteAddress);
|
|
|
+ }
|
|
|
+
|
|
|
+ @VisibleForTesting
|
|
|
+ CREATE3Response create(XDR xdr, SecurityHandler securityHandler,
|
|
|
+ SocketAddress remoteAddress) {
|
|
|
CREATE3Response response = new CREATE3Response(Nfs3Status.NFS3_OK);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
@@ -838,7 +867,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
return new CREATE3Response(Nfs3Status.NFS3ERR_STALE);
|
|
|
}
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_WRITE)) {
|
|
|
+ if (!checkAccessPrivilege(remoteAddress, AccessPrivilege.READ_WRITE)) {
|
|
|
return new CREATE3Response(Nfs3Status.NFS3ERR_ACCES, null,
|
|
|
preOpDirAttr, new WccData(Nfs3Utils.getWccAttr(preOpDirAttr),
|
|
|
preOpDirAttr));
|
|
@@ -875,7 +904,8 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
|
|
|
// Add open stream
|
|
|
OpenFileCtx openFileCtx = new OpenFileCtx(fos, postOpObjAttr,
|
|
|
- writeDumpDir + "/" + postOpObjAttr.getFileId(), dfsClient, iug);
|
|
|
+ writeDumpDir + "/" + postOpObjAttr.getFileId(), dfsClient, iug,
|
|
|
+ aixCompatMode);
|
|
|
fileHandle = new FileHandle(postOpObjAttr.getFileId());
|
|
|
if (!writeManager.addOpenFileStream(fileHandle, openFileCtx)) {
|
|
|
LOG.warn("Can't add more stream, close it."
|
|
@@ -922,9 +952,9 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public MKDIR3Response mkdir(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public MKDIR3Response mkdir(XDR xdr, RpcInfo info) {
|
|
|
MKDIR3Response response = new MKDIR3Response(Nfs3Status.NFS3_OK);
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -960,7 +990,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
return new MKDIR3Response(Nfs3Status.NFS3ERR_STALE);
|
|
|
}
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_WRITE)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_WRITE)) {
|
|
|
return new MKDIR3Response(Nfs3Status.NFS3ERR_ACCES, null, preOpDirAttr,
|
|
|
new WccData(Nfs3Utils.getWccAttr(preOpDirAttr), preOpDirAttr));
|
|
|
}
|
|
@@ -1012,15 +1042,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public READDIR3Response mknod(XDR xdr,
|
|
|
- SecurityHandler securityHandler, InetAddress client) {
|
|
|
+ @Override
|
|
|
+ public READDIR3Response mknod(XDR xdr, RpcInfo info) {
|
|
|
return new READDIR3Response(Nfs3Status.NFS3ERR_NOTSUPP);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public REMOVE3Response remove(XDR xdr,
|
|
|
- SecurityHandler securityHandler, InetAddress client) {
|
|
|
+ public REMOVE3Response remove(XDR xdr, RpcInfo info) {
|
|
|
REMOVE3Response response = new REMOVE3Response(Nfs3Status.NFS3_OK);
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -1093,9 +1123,9 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public RMDIR3Response rmdir(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public RMDIR3Response rmdir(XDR xdr, RpcInfo info) {
|
|
|
RMDIR3Response response = new RMDIR3Response(Nfs3Status.NFS3_OK);
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -1129,7 +1159,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
|
|
|
WccData errWcc = new WccData(Nfs3Utils.getWccAttr(preOpDirAttr),
|
|
|
preOpDirAttr);
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_WRITE)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_WRITE)) {
|
|
|
return new RMDIR3Response(Nfs3Status.NFS3ERR_ACCES, errWcc);
|
|
|
}
|
|
|
|
|
@@ -1175,9 +1205,9 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public RENAME3Response rename(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public RENAME3Response rename(XDR xdr, RpcInfo info) {
|
|
|
RENAME3Response response = new RENAME3Response(Nfs3Status.NFS3_OK);
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -1221,7 +1251,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
return new RENAME3Response(Nfs3Status.NFS3ERR_STALE);
|
|
|
}
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_WRITE)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_WRITE)) {
|
|
|
WccData fromWcc = new WccData(Nfs3Utils.getWccAttr(fromPreOpAttr),
|
|
|
fromPreOpAttr);
|
|
|
WccData toWcc = new WccData(Nfs3Utils.getWccAttr(toPreOpAttr),
|
|
@@ -1263,15 +1293,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public SYMLINK3Response symlink(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public SYMLINK3Response symlink(XDR xdr, RpcInfo info) {
|
|
|
SYMLINK3Response response = new SYMLINK3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_WRITE)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_WRITE)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -1322,8 +1352,8 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public READDIR3Response link(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ @Override
|
|
|
+ public READDIR3Response link(XDR xdr, RpcInfo info) {
|
|
|
return new READDIR3Response(Nfs3Status.NFS3ERR_NOTSUPP);
|
|
|
}
|
|
|
|
|
@@ -1351,11 +1381,16 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
+ public READDIR3Response readdir(XDR xdr, RpcInfo info) {
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
+ SocketAddress remoteAddress = info.remoteAddress();
|
|
|
+ return readdir(xdr, securityHandler, remoteAddress);
|
|
|
+ }
|
|
|
public READDIR3Response readdir(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ SocketAddress remoteAddress) {
|
|
|
READDIR3Response response = new READDIR3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(remoteAddress, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
@@ -1408,9 +1443,24 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
long cookieVerf = request.getCookieVerf();
|
|
|
if ((cookieVerf != 0) && (cookieVerf != dirStatus.getModificationTime())) {
|
|
|
- LOG.error("CookierVerf mismatch. request cookierVerf:" + cookieVerf
|
|
|
- + " dir cookieVerf:" + dirStatus.getModificationTime());
|
|
|
- return new READDIR3Response(Nfs3Status.NFS3ERR_BAD_COOKIE);
|
|
|
+ if (aixCompatMode) {
|
|
|
+ // The AIX NFS client misinterprets RFC-1813 and will repeatedly send
|
|
|
+ // the same cookieverf value even across VFS-level readdir calls,
|
|
|
+ // instead of getting a new cookieverf for every VFS-level readdir
|
|
|
+ // call, and reusing the cookieverf only in the event that multiple
|
|
|
+ // incremental NFS-level readdir calls must be made to fetch all of
|
|
|
+ // the directory entries. This means that whenever a readdir call is
|
|
|
+ // made by an AIX NFS client for a given directory, and that directory
|
|
|
+ // is subsequently modified, thus changing its mtime, no later readdir
|
|
|
+ // calls will succeed from AIX for that directory until the FS is
|
|
|
+ // unmounted/remounted. See HDFS-6549 for more info.
|
|
|
+ LOG.warn("AIX compatibility mode enabled, ignoring cookieverf " +
|
|
|
+ "mismatches.");
|
|
|
+ } else {
|
|
|
+ LOG.error("CookieVerf mismatch. request cookieVerf: " + cookieVerf
|
|
|
+ + " dir cookieVerf: " + dirStatus.getModificationTime());
|
|
|
+ return new READDIR3Response(Nfs3Status.NFS3ERR_BAD_COOKIE);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (cookie == 0) {
|
|
@@ -1491,9 +1541,17 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
dirStatus.getModificationTime(), dirList);
|
|
|
}
|
|
|
|
|
|
- public READDIRPLUS3Response readdirplus(XDR xdr,
|
|
|
- SecurityHandler securityHandler, InetAddress client) {
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ @Override
|
|
|
+ public READDIRPLUS3Response readdirplus(XDR xdr, RpcInfo info) {
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
+ SocketAddress remoteAddress = info.remoteAddress();
|
|
|
+ return readdirplus(xdr, securityHandler, remoteAddress);
|
|
|
+ }
|
|
|
+
|
|
|
+ @VisibleForTesting
|
|
|
+ READDIRPLUS3Response readdirplus(XDR xdr, SecurityHandler securityHandler,
|
|
|
+ SocketAddress remoteAddress) {
|
|
|
+ if (!checkAccessPrivilege(remoteAddress, AccessPrivilege.READ_ONLY)) {
|
|
|
return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_ACCES);
|
|
|
}
|
|
|
|
|
@@ -1550,9 +1608,22 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
long cookieVerf = request.getCookieVerf();
|
|
|
if ((cookieVerf != 0) && (cookieVerf != dirStatus.getModificationTime())) {
|
|
|
- LOG.error("CookierVerf mismatch. request cookierVerf:" + cookieVerf
|
|
|
- + " dir cookieVerf:" + dirStatus.getModificationTime());
|
|
|
- return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_BAD_COOKIE);
|
|
|
+ if (aixCompatMode) {
|
|
|
+ // The AIX NFS client misinterprets RFC-1813 and will repeatedly send
|
|
|
+ // the same cookieverf value even across VFS-level readdir calls,
|
|
|
+ // instead of getting a new cookieverf for every VFS-level readdir
|
|
|
+ // call. This means that whenever a readdir call is made by an AIX NFS
|
|
|
+ // client for a given directory, and that directory is subsequently
|
|
|
+ // modified, thus changing its mtime, no later readdir calls will
|
|
|
+ // succeed for that directory from AIX until the FS is
|
|
|
+ // unmounted/remounted. See HDFS-6549 for more info.
|
|
|
+ LOG.warn("AIX compatibility mode enabled, ignoring cookieverf " +
|
|
|
+ "mismatches.");
|
|
|
+ } else {
|
|
|
+ LOG.error("cookieverf mismatch. request cookieverf: " + cookieVerf
|
|
|
+ + " dir cookieverf: " + dirStatus.getModificationTime());
|
|
|
+ return new READDIRPLUS3Response(Nfs3Status.NFS3ERR_BAD_COOKIE);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (cookie == 0) {
|
|
@@ -1643,15 +1714,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public FSSTAT3Response fsstat(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public FSSTAT3Response fsstat(XDR xdr, RpcInfo info) {
|
|
|
FSSTAT3Response response = new FSSTAT3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -1711,15 +1782,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public FSINFO3Response fsinfo(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public FSINFO3Response fsinfo(XDR xdr, RpcInfo info) {
|
|
|
FSINFO3Response response = new FSINFO3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -1769,15 +1840,15 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public PATHCONF3Response pathconf(XDR xdr, SecurityHandler securityHandler,
|
|
|
- InetAddress client) {
|
|
|
+ public PATHCONF3Response pathconf(XDR xdr, RpcInfo info) {
|
|
|
PATHCONF3Response response = new PATHCONF3Response(Nfs3Status.NFS3_OK);
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_ONLY)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_ONLY)) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_ACCES);
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -1816,9 +1887,11 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public COMMIT3Response commit(XDR xdr, Channel channel, int xid,
|
|
|
- SecurityHandler securityHandler, InetAddress client) {
|
|
|
+ public COMMIT3Response commit(XDR xdr, RpcInfo info) {
|
|
|
+ //Channel channel, int xid,
|
|
|
+ // SecurityHandler securityHandler, InetAddress client) {
|
|
|
COMMIT3Response response = new COMMIT3Response(Nfs3Status.NFS3_OK);
|
|
|
+ SecurityHandler securityHandler = getSecurityHandler(info);
|
|
|
DFSClient dfsClient = clientCache.getDfsClient(securityHandler.getUser());
|
|
|
if (dfsClient == null) {
|
|
|
response.setStatus(Nfs3Status.NFS3ERR_SERVERFAULT);
|
|
@@ -1849,7 +1922,7 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
return new COMMIT3Response(Nfs3Status.NFS3ERR_STALE);
|
|
|
}
|
|
|
|
|
|
- if (!checkAccessPrivilege(client, AccessPrivilege.READ_WRITE)) {
|
|
|
+ if (!checkAccessPrivilege(info, AccessPrivilege.READ_WRITE)) {
|
|
|
return new COMMIT3Response(Nfs3Status.NFS3ERR_ACCES, new WccData(
|
|
|
Nfs3Utils.getWccAttr(preOpAttr), preOpAttr),
|
|
|
Nfs3Constant.WRITE_COMMIT_VERF);
|
|
@@ -1859,8 +1932,10 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
: (request.getOffset() + request.getCount());
|
|
|
|
|
|
// Insert commit as an async request
|
|
|
- writeManager.handleCommit(dfsClient, handle, commitOffset, channel, xid,
|
|
|
- preOpAttr);
|
|
|
+ RpcCall rpcCall = (RpcCall) info.header();
|
|
|
+ int xid = rpcCall.getXid();
|
|
|
+ writeManager.handleCommit(dfsClient, handle, commitOffset,
|
|
|
+ info.channel(), xid, preOpAttr);
|
|
|
return null;
|
|
|
} catch (IOException e) {
|
|
|
LOG.warn("Exception ", e);
|
|
@@ -1885,11 +1960,16 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private SecurityHandler getSecurityHandler(RpcInfo info) {
|
|
|
+ RpcCall rpcCall = (RpcCall) info.header();
|
|
|
+ return getSecurityHandler(rpcCall.getCredential(), rpcCall.getVerifier());
|
|
|
+ }
|
|
|
|
|
|
@Override
|
|
|
public void handleInternal(ChannelHandlerContext ctx, RpcInfo info) {
|
|
|
RpcCall rpcCall = (RpcCall) info.header();
|
|
|
- final NFSPROC3 nfsproc3 = NFSPROC3.fromValue(rpcCall.getProcedure());
|
|
|
+ final NFSPROC3 nfsproc3 = NFSPROC3.fromValue(rpcCall.getProcedure());
|
|
|
int xid = rpcCall.getXid();
|
|
|
byte[] data = new byte[info.data().readableBytes()];
|
|
|
info.data().readBytes(data);
|
|
@@ -1897,9 +1977,8 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
XDR out = new XDR();
|
|
|
InetAddress client = ((InetSocketAddress) info.remoteAddress())
|
|
|
.getAddress();
|
|
|
- Channel channel = info.channel();
|
|
|
-
|
|
|
Credentials credentials = rpcCall.getCredential();
|
|
|
+
|
|
|
// Ignore auth only for NFSPROC3_NULL, especially for Linux clients.
|
|
|
if (nfsproc3 != NFSPROC3.NULL) {
|
|
|
if (credentials.getFlavor() != AuthFlavor.AUTH_SYS
|
|
@@ -1937,27 +2016,24 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- SecurityHandler securityHandler = getSecurityHandler(credentials,
|
|
|
- rpcCall.getVerifier());
|
|
|
-
|
|
|
NFS3Response response = null;
|
|
|
if (nfsproc3 == NFSPROC3.NULL) {
|
|
|
response = nullProcedure();
|
|
|
} else if (nfsproc3 == NFSPROC3.GETATTR) {
|
|
|
- response = getattr(xdr, securityHandler, client);
|
|
|
+ response = getattr(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.SETATTR) {
|
|
|
- response = setattr(xdr, securityHandler, client);
|
|
|
+ response = setattr(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.LOOKUP) {
|
|
|
- response = lookup(xdr, securityHandler, client);
|
|
|
+ response = lookup(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.ACCESS) {
|
|
|
- response = access(xdr, securityHandler, client);
|
|
|
+ response = access(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.READLINK) {
|
|
|
- response = readlink(xdr, securityHandler, client);
|
|
|
+ response = readlink(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.READ) {
|
|
|
if (LOG.isDebugEnabled()) {
|
|
|
LOG.debug(Nfs3Utils.READ_RPC_START + xid);
|
|
|
}
|
|
|
- response = read(xdr, securityHandler, client);
|
|
|
+ response = read(xdr, info);
|
|
|
if (LOG.isDebugEnabled() && (nfsproc3 == NFSPROC3.READ)) {
|
|
|
LOG.debug(Nfs3Utils.READ_RPC_END + xid);
|
|
|
}
|
|
@@ -1965,36 +2041,36 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
if (LOG.isDebugEnabled()) {
|
|
|
LOG.debug(Nfs3Utils.WRITE_RPC_START + xid);
|
|
|
}
|
|
|
- response = write(xdr, channel, xid, securityHandler, client);
|
|
|
+ response = write(xdr, info);
|
|
|
// Write end debug trace is in Nfs3Utils.writeChannel
|
|
|
} else if (nfsproc3 == NFSPROC3.CREATE) {
|
|
|
- response = create(xdr, securityHandler, client);
|
|
|
+ response = create(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.MKDIR) {
|
|
|
- response = mkdir(xdr, securityHandler, client);
|
|
|
+ response = mkdir(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.SYMLINK) {
|
|
|
- response = symlink(xdr, securityHandler, client);
|
|
|
+ response = symlink(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.MKNOD) {
|
|
|
- response = mknod(xdr, securityHandler, client);
|
|
|
+ response = mknod(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.REMOVE) {
|
|
|
- response = remove(xdr, securityHandler, client);
|
|
|
+ response = remove(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.RMDIR) {
|
|
|
- response = rmdir(xdr, securityHandler, client);
|
|
|
+ response = rmdir(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.RENAME) {
|
|
|
- response = rename(xdr, securityHandler, client);
|
|
|
+ response = rename(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.LINK) {
|
|
|
- response = link(xdr, securityHandler, client);
|
|
|
+ response = link(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.READDIR) {
|
|
|
- response = readdir(xdr, securityHandler, client);
|
|
|
+ response = readdir(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.READDIRPLUS) {
|
|
|
- response = readdirplus(xdr, securityHandler, client);
|
|
|
+ response = readdirplus(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.FSSTAT) {
|
|
|
- response = fsstat(xdr, securityHandler, client);
|
|
|
+ response = fsstat(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.FSINFO) {
|
|
|
- response = fsinfo(xdr, securityHandler, client);
|
|
|
+ response = fsinfo(xdr, info);
|
|
|
} else if (nfsproc3 == NFSPROC3.PATHCONF) {
|
|
|
- response = pathconf(xdr, securityHandler, client);
|
|
|
+ response = pathconf(xdr,info);
|
|
|
} else if (nfsproc3 == NFSPROC3.COMMIT) {
|
|
|
- response = commit(xdr, channel, xid, securityHandler, client);
|
|
|
+ response = commit(xdr, info);
|
|
|
} else {
|
|
|
// Invalid procedure
|
|
|
RpcAcceptedReply.getInstance(xid,
|
|
@@ -2027,8 +2103,21 @@ public class RpcProgramNfs3 extends RpcProgram implements Nfs3Interface {
|
|
|
return nfsproc3 == null || nfsproc3.isIdempotent();
|
|
|
}
|
|
|
|
|
|
- private boolean checkAccessPrivilege(final InetAddress client,
|
|
|
+ private boolean checkAccessPrivilege(RpcInfo info,
|
|
|
+ final AccessPrivilege expected) {
|
|
|
+ SocketAddress remoteAddress = info.remoteAddress();
|
|
|
+ return checkAccessPrivilege(remoteAddress, expected);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean checkAccessPrivilege(SocketAddress remoteAddress,
|
|
|
final AccessPrivilege expected) {
|
|
|
+ // Port monitoring
|
|
|
+ if (!doPortMonitoring(remoteAddress)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check export table
|
|
|
+ InetAddress client = ((InetSocketAddress) remoteAddress).getAddress();
|
|
|
AccessPrivilege access = exports.getAccessPrivilege(client);
|
|
|
if (access == AccessPrivilege.NONE) {
|
|
|
return false;
|