There are some cases possible during upgrade to the Lustre 2.5
from older versions which need workaround instead assertion.
The osd_object_ref_del() shouldn't assert on nlink == 0 if
object is local file but produce error message.
The underlying ext4_unlink() code doesn't treat decref on an
inode with nlink == 0 as a fatal error either, so only print
an error in the non-upgrade case for regular objects.
Signed-off-by: Mikhail Pershin <mike.pershin@intel.com>
Change-Id: I5aa1cc3d9a6d6210e8ce9f55193a4f25507b0986
Reviewed-on: http://review.whamcloud.com/7673
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
static int osd_object_ref_del(const struct lu_env *env, struct dt_object *dt,
struct thandle *th)
{
static int osd_object_ref_del(const struct lu_env *env, struct dt_object *dt,
struct thandle *th)
{
- struct osd_object *obj = osd_dt_obj(dt);
- struct inode *inode = obj->oo_inode;
+ struct osd_object *obj = osd_dt_obj(dt);
+ struct inode *inode = obj->oo_inode;
+ struct osd_device *osd = osd_dev(dt->do_lu.lo_dev);
- LINVRNT(osd_invariant(obj));
+ LINVRNT(osd_invariant(obj));
LASSERT(dt_object_exists(dt) && !dt_object_remote(dt));
LASSERT(dt_object_exists(dt) && !dt_object_remote(dt));
- LASSERT(osd_write_locked(env, obj));
- LASSERT(th != NULL);
+ LASSERT(osd_write_locked(env, obj));
+ LASSERT(th != NULL);
osd_trans_exec_op(env, th, OSD_OT_REF_DEL);
spin_lock(&obj->oo_guard);
osd_trans_exec_op(env, th, OSD_OT_REF_DEL);
spin_lock(&obj->oo_guard);
- LASSERT(inode->i_nlink > 0);
+ /* That can be result of upgrade from old Lustre version and
+ * applied only to local files. Just skip this ref_del call.
+ * ext4_unlink() only treats this as a warning, don't LASSERT here.*/
+ if (inode->i_nlink == 0) {
+ CDEBUG_LIMIT(fid_is_norm(lu_object_fid(&dt->do_lu)) ?
+ D_ERROR : D_INODE, "%s: nlink == 0 on "DFID
+ ", maybe an upgraded file? (LU-3915)\n",
+ osd_name(osd), PFID(lu_object_fid(&dt->do_lu)));
+ spin_unlock(&obj->oo_guard);
+ return 0;
+ }
/* This based on ldiskfs_dec_count(), which is not exported.
*
/* This based on ldiskfs_dec_count(), which is not exported.
*
* threads not holding oo_guard seeing i_nlink == 0 in rare cases.
*
* nlink == 1 means the directory has/had > EXT4_LINK_MAX subdirs.
* threads not holding oo_guard seeing i_nlink == 0 in rare cases.
*
* nlink == 1 means the directory has/had > EXT4_LINK_MAX subdirs.
if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 1) {
drop_nlink(inode);
if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 1) {
drop_nlink(inode);