aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2012-01-27 13:43:23 -0800
committerBrian Behlendorf <[email protected]>2012-02-02 11:22:08 -0800
commit0c5dde492ff4fadcc9c43477c81b3d3824ac41db (patch)
tree052ee6a0f94ec5083249b81b6a3fd25605e9fe34 /module
parente29be02e46ba2470795c9ab12e6da12d58ff2e5a (diff)
Allow multiple values per directory entry
When using zfs to back a Lustre filesystem it's advantageous to to store a fid with the object id in the directory zap. The only technical impediment to doing this is that the zpl code expects a single value in the zap per directory entry. This change relaxes that requirement such that multiple entries are allowed provided the first one is the object id. The zpl code will just ignore additional entries. This allows the ZoL count to mount datasets which are being used as Lustre server backends. Once the upstream feature flags support is merged in this change should be updated to a read-only feature. Until this occurs other zfs implementations will not be able to read the zfs filesystems created by Lustre. Signed-off-by: Brian Behlendorf <[email protected]>
Diffstat (limited to 'module')
-rw-r--r--module/zfs/zfs_dir.c18
-rw-r--r--module/zfs/zfs_vnops.c16
2 files changed, 28 insertions, 6 deletions
diff --git a/module/zfs/zfs_dir.c b/module/zfs/zfs_dir.c
index 47550ec63..8f1a0c2cc 100644
--- a/module/zfs/zfs_dir.c
+++ b/module/zfs/zfs_dir.c
@@ -64,11 +64,11 @@ static int
zfs_match_find(zfs_sb_t *zsb, znode_t *dzp, char *name, boolean_t exact,
boolean_t update, int *deflags, pathname_t *rpnp, uint64_t *zoid)
{
+ boolean_t conflict = B_FALSE;
int error;
if (zsb->z_norm) {
matchtype_t mt = MT_FIRST;
- boolean_t conflict = B_FALSE;
size_t bufsz = 0;
char *buf = NULL;
@@ -84,11 +84,23 @@ zfs_match_find(zfs_sb_t *zsb, znode_t *dzp, char *name, boolean_t exact,
*/
error = zap_lookup_norm(zsb->z_os, dzp->z_id, name, 8, 1,
zoid, mt, buf, bufsz, &conflict);
- if (!error && deflags)
- *deflags = conflict ? ED_CASE_CONFLICT : 0;
} else {
error = zap_lookup(zsb->z_os, dzp->z_id, name, 8, 1, zoid);
}
+
+ /*
+ * Allow multiple entries provided the first entry is
+ * the object id. Non-zpl consumers may safely make
+ * use of the additional space.
+ *
+ * XXX: This should be a feature flag for compatibility
+ */
+ if (error == EOVERFLOW)
+ error = 0;
+
+ if (zsb->z_norm && !error && deflags)
+ *deflags = conflict ? ED_CASE_CONFLICT : 0;
+
*zoid = ZFS_DIRENT_OBJ(*zoid);
#ifdef HAVE_DNLC
diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c
index b7f5daaaf..c1391984a 100644
--- a/module/zfs/zfs_vnops.c
+++ b/module/zfs/zfs_vnops.c
@@ -2012,12 +2012,22 @@ zfs_readdir(struct inode *ip, void *dirent, filldir_t filldir,
goto update;
}
+ /*
+ * Allow multiple entries provided the first entry is
+ * the object id. Non-zpl consumers may safely make
+ * use of the additional space.
+ *
+ * XXX: This should be a feature flag for compatibility
+ */
if (zap.za_integer_length != 8 ||
- zap.za_num_integers != 1) {
+ zap.za_num_integers == 0) {
cmn_err(CE_WARN, "zap_readdir: bad directory "
- "entry, obj = %lld, offset = %lld\n",
+ "entry, obj = %lld, offset = %lld, "
+ "length = %d, num = %lld\n",
(u_longlong_t)zp->z_id,
- (u_longlong_t)*pos);
+ (u_longlong_t)*pos,
+ zap.za_integer_length,
+ (u_longlong_t)zap.za_num_integers);
error = ENXIO;
goto update;
}