diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 7604ca16b731caf51719ff1f1ecffe02ff275f9c..1ece8a760cd69e4525edb8493bde5b036616ea51 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -164,6 +164,12 @@ Details : Apply the MGS_CONNECT_SUPPORTED mask at reconnect time so * Output of lfs quota has been made less detailed by default, old (verbose) output can be obtained by using -v option. +Severity : minor +Bugzilla : 15899 +Description: Add support for downgrading pools-striped files +Details : This version can understand the new LOV magic from pools + striped files (pools will be available in a future release). + Severity : normal Bugzilla : 15975 Frequency : only patchless client diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index f8ee54599112f4e5a89d80ec8c0caa2954a78725..9b43e7d138537764bc39c8ef0b83de33ae3ee110 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -589,6 +589,41 @@ int mds_get_md(struct obd_device *obd, struct inode *inode, void *md, LOCK_INODE_MUTEX(inode); rc = fsfilt_get_md(obd, inode, md, *size, "lov"); + /* rc == 0 may come from a not large enough buffer if + * we downgrade from a pool version and the file + * is a large stripe like full stripe + */ + if (rc == 0) { + /* get the size of the lov EA */ + rc = fsfilt_get_md(obd, inode, NULL, *size, "lov"); + /* test if the difference is from poolname */ + if (rc == (*size + MAXPOOLNAME)) { + void *buf; + int new_size; + + new_size = *size + MAXPOOLNAME; + OBD_ALLOC(buf, new_size); + if (buf == NULL) { + rc = -ENOMEM; + goto out; + } + rc = fsfilt_get_md(obd, inode, buf, new_size, "lov"); + if (rc <= 0) { + OBD_FREE(buf, new_size); + goto out; + } + + /* convert V3 EA to V1 */ + lmm_size = rc; + rc = mds_convert_lov_ea(obd, inode, buf, lmm_size); + /* copy converted EA to provided buffer */ + memcpy(md, buf, rc); + *size = rc; + OBD_FREE(buf, new_size); + goto out; + } + } + if (rc == 0 && flags == MDS_GETATTR) rc = mds_get_default_md(obd, md, &lmm_size); @@ -608,6 +643,8 @@ int mds_get_md(struct obd_device *obd, struct inode *inode, void *md, } else { *size = 0; } + +out: if (lock) UNLOCK_INODE_MUTEX(inode); @@ -843,9 +880,14 @@ static int mds_getattr_pack_msg(struct ptlrpc_request *req, struct inode *inode, } size[bufcount] = 0; } else if (rc > mds->mds_max_mdsize) { - size[bufcount] = 0; - CERROR("MD size %d larger than maximum possible %u\n", - rc, mds->mds_max_mdsize); + /* pool downgrade case */ + if (rc <= (mds->mds_max_mdsize + MAXPOOLNAME)) { + size[bufcount] = rc; + } else { + size[bufcount] = 0; + CERROR("MD size %d larger than maximum possible %u\n", + rc, mds->mds_max_mdsize); + } } else { size[bufcount] = rc; }