X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fosd-ldiskfs%2Fosd_handler.c;h=c561425f3f5d98b540976d504ca8283b4100e497;hp=273b3c10717b730b657bf5d3944ef107c0d47946;hb=7805b45f1182ed21198c0cd2000ffe93b7de5340;hpb=2789978e1192dbf6d90399c96b5594e0dc049cd9 diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 273b3c1..c561425 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -39,6 +39,7 @@ #define DEBUG_SUBSYSTEM S_OSD +#include #include #include #include @@ -209,14 +210,14 @@ osd_idc_add(const struct lu_env *env, struct osd_device *osd, i = oti->oti_ins_cache_size * 2; if (i == 0) i = OSD_INS_CACHE_SIZE; - OBD_ALLOC(idc, sizeof(*idc) * i); + OBD_ALLOC_PTR_ARRAY(idc, i); if (idc == NULL) return ERR_PTR(-ENOMEM); if (oti->oti_ins_cache != NULL) { memcpy(idc, oti->oti_ins_cache, oti->oti_ins_cache_used * sizeof(*idc)); - OBD_FREE(oti->oti_ins_cache, - oti->oti_ins_cache_used * sizeof(*idc)); + OBD_FREE_PTR_ARRAY(oti->oti_ins_cache, + oti->oti_ins_cache_used); } oti->oti_ins_cache = idc; oti->oti_ins_cache_size = i; @@ -477,6 +478,7 @@ int osd_ldiskfs_add_entry(struct osd_thread_info *info, struct osd_device *osd, struct lustre_ost_attrs *loa = &info->oti_ost_attrs; struct inode *parent = child->d_parent->d_inode; struct lu_fid *fid = NULL; + char fidstr[FID_LEN + 1] = "unknown"; rc2 = osd_get_lma(info, parent, child->d_parent, loa); if (!rc2) { @@ -493,19 +495,18 @@ int osd_ldiskfs_add_entry(struct osd_thread_info *info, struct osd_device *osd, } if (fid != NULL) - /* below message is checked in sanity.sh test_129 */ - CWARN("%s: directory (inode: %lu, FID: "DFID") %s maximum entry limit\n", - osd_name(osd), parent->i_ino, PFID(fid), - rc == -ENOSPC ? "has reached" : "is approaching"); - else - /* below message is checked in sanity.sh test_129 */ - CWARN("%s: directory (inode: %lu, FID: unknown) %s maximum entry limit\n", - osd_name(osd), parent->i_ino, - rc == -ENOSPC ? "has reached" : "is approaching"); + snprintf(fidstr, sizeof(fidstr), DFID, PFID(fid)); + + /* below message is checked in sanity.sh test_129 */ + if (rc == -ENOSPC) { + CWARN("%s: directory (inode: %lu, FID: %s) has reached max size limit\n", + osd_name(osd), parent->i_ino, fidstr); + } else { + rc = 0; /* ignore such error now */ + CWARN("%s: directory (inode: %lu, FID: %s) is approaching max size limit\n", + osd_name(osd), parent->i_ino, fidstr); + } - /* ignore such error now */ - if (rc == -ENOBUFS) - rc = 0; } return rc; @@ -956,8 +957,7 @@ static int osd_check_lmv(struct osd_thread_info *oti, struct osd_device *dev, { struct lu_buf *buf = &oti->oti_big_buf; struct dentry *dentry = &oti->oti_obj_dentry; - struct file *filp = &oti->oti_file; - const struct file_operations *fops; + struct file *filp; struct lmv_mds_md_v1 *lmv1; struct osd_check_lmv_buf oclb = { .ctx.actor = osd_stripe_dir_filldir, @@ -1002,18 +1002,7 @@ again: if (le32_to_cpu(lmv1->lmv_magic) != LMV_MAGIC_V1) GOTO(out, rc = 0); - fops = inode->i_fop; - dentry->d_inode = inode; - dentry->d_sb = inode->i_sb; - filp->f_pos = 0; - filp->f_path.dentry = dentry; - filp->f_flags |= O_NOATIME; - filp->f_mode = FMODE_64BITHASH | FMODE_NONOTIFY; - filp->f_mapping = inode->i_mapping; - filp->f_op = fops; - filp->private_data = NULL; - filp->f_cred = current_cred(); - filp->f_inode = inode; + filp = osd_quasi_file(oti->oti_env, inode); rc = osd_security_file_alloc(filp); if (rc) goto out; @@ -1023,7 +1012,7 @@ again: rc = iterate_dir(filp, &oclb.ctx); } while (rc >= 0 && oclb.oclb_items > 0 && !oclb.oclb_found && filp->f_pos != LDISKFS_HTREE_EOF_64BIT); - fops->release(inode, filp); + inode->i_fop->release(inode, filp); out: if (rc < 0) @@ -1178,17 +1167,19 @@ trigger: } } - if (thread_is_running(&scrub->os_thread)) { + if (scrub->os_running) { if (scrub->os_partial_scan && !scrub->os_in_join) goto join; - if (IS_ERR_OR_NULL(inode) || result) + osd_add_oi_cache(info, dev, id, fid); + if (IS_ERR_OR_NULL(inode) || result) { + osd_oii_insert(dev, oic, result == -ENOENT); GOTO(out, result = -EINPROGRESS); + } LASSERT(remote); LASSERT(obj->oo_inode == inode); - osd_add_oi_cache(info, dev, id, fid); osd_oii_insert(dev, oic, true); goto found; } @@ -1211,13 +1202,15 @@ join: if (rc1 && rc1 != -EALREADY) GOTO(out, result = -EREMCHG); - if (IS_ERR_OR_NULL(inode) || result) + osd_add_oi_cache(info, dev, id, fid); + if (IS_ERR_OR_NULL(inode) || result) { + osd_oii_insert(dev, oic, result == -ENOENT); GOTO(out, result = -EINPROGRESS); + } LASSERT(remote); LASSERT(obj->oo_inode == inode); - osd_add_oi_cache(info, dev, id, fid); osd_oii_insert(dev, oic, true); goto found; @@ -1400,6 +1393,13 @@ static int osd_object_init(const struct lu_env *env, struct lu_object *l, LINVRNT(osd_invariant(obj)); + if (OBD_FAIL_PRECHECK(OBD_FAIL_MDS_LLOG_UMOUNT_RACE) && + cfs_fail_val == 2) { + struct osd_thread_info *info = osd_oti_get(env); + struct osd_idmap_cache *oic = &info->oti_cache; + /* invalidate thread cache */ + memset(&oic->oic_fid, 0, sizeof(oic->oic_fid)); + } if (fid_is_otable_it(&l->lo_header->loh_fid)) { obj->oo_dt.do_ops = &osd_obj_otable_it_ops; l->lo_header->loh_attr |= LOHA_EXISTS; @@ -1429,6 +1429,7 @@ static int osd_object_init(const struct lu_env *env, struct lu_object *l, result = 0; } } + obj->oo_dirent_count = LU_DIRENT_COUNT_UNSET; LINVRNT(osd_invariant(obj)); return result; @@ -1582,11 +1583,8 @@ static void osd_object_free(const struct lu_env *env, struct lu_object *l) ldiskfs_htree_lock_head_free(obj->oo_hl_head); /* obj doesn't contain an lu_object_header, so we don't need call_rcu */ OBD_FREE_PTR(obj); - if (unlikely(h)) { - lu_object_header_fini(h); - OBD_FREE_PRE(h, sizeof(*h), "kfreed"); - kfree_rcu(h, loh_rcu); - } + if (unlikely(h)) + lu_object_header_free(h); } /* @@ -1608,16 +1606,6 @@ static void osd_index_fini(struct osd_object *o) } } -/* - * Concurrency: no concurrent access is possible that late in object - * life-cycle (for all existing callers, that is. New callers have to provide - * their own locking.) - */ -static int osd_inode_unlinked(const struct inode *inode) -{ - return inode->i_nlink == 0; -} - enum { OSD_TXN_OI_DELETE_CREDITS = 20, OSD_TXN_INODE_DELETE_CREDITS = 20 @@ -1704,7 +1692,7 @@ static int osd_param_is_not_sane(const struct osd_device *dev, static void osd_trans_commit_cb(struct super_block *sb, struct ldiskfs_journal_cb_entry *jcb, int error) { - struct osd_thandle *oh = container_of0(jcb, struct osd_thandle, ot_jcb); + struct osd_thandle *oh = container_of(jcb, struct osd_thandle, ot_jcb); struct thandle *th = &oh->ot_super; struct lu_device *lud = &th->th_dev->dd_lu_dev; struct dt_txn_commit_cb *dcb, *tmp; @@ -1789,7 +1777,7 @@ void osd_trans_dump_creds(const struct lu_env *env, struct thandle *th) struct osd_thread_info *oti = osd_oti_get(env); struct osd_thandle *oh; - oh = container_of0(th, struct osd_thandle, ot_super); + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh != NULL); CWARN(" create: %u/%u/%u, destroy: %u/%u/%u\n", @@ -1848,7 +1836,7 @@ static int osd_trans_start(const struct lu_env *env, struct dt_device *d, LASSERT(current->journal_info == NULL); - oh = container_of0(th, struct osd_thandle, ot_super); + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh != NULL); LASSERT(oh->ot_handle == NULL); @@ -1977,7 +1965,7 @@ static int osd_trans_stop(const struct lu_env *env, struct dt_device *dt, ENTRY; - oh = container_of0(th, struct osd_thandle, ot_super); + oh = container_of(th, struct osd_thandle, ot_super); remove_agents = oh->ot_remove_agents; @@ -2026,7 +2014,7 @@ static int osd_trans_stop(const struct lu_env *env, struct dt_device *dt, OBD_FREE_PTR(oh); } - osd_trunc_unlock_all(&truncates); + osd_trunc_unlock_all(env, &truncates); /* inform the quota slave device that the transaction is stopping */ qsd_op_end(env, qsd, qtrans); @@ -2062,8 +2050,8 @@ static int osd_trans_stop(const struct lu_env *env, struct dt_device *dt, static int osd_trans_cb_add(struct thandle *th, struct dt_txn_commit_cb *dcb) { - struct osd_thandle *oh = container_of0(th, struct osd_thandle, - ot_super); + struct osd_thandle *oh = container_of(th, struct osd_thandle, + ot_super); LASSERT(dcb->dcb_magic == TRANS_COMMIT_CB_MAGIC); LASSERT(&dcb->dcb_func != NULL); @@ -2102,6 +2090,9 @@ static void osd_object_delete(const struct lu_env *env, struct lu_object *l) if (!inode) return; + if (osd_has_index(obj) && obj->oo_dt.do_index_ops == &osd_index_iam_ops) + ldiskfs_set_inode_flag(inode, LDISKFS_INODE_JOURNAL_DATA); + uid = i_uid_read(inode); gid = i_gid_read(inode); projid = i_projid_read(inode); @@ -2199,9 +2190,9 @@ int osd_statfs(const struct lu_env *env, struct dt_device *d, statfs_pack(sfs, ksfs); if (unlikely(sb->s_flags & SB_RDONLY)) - sfs->os_state |= OS_STATE_READONLY; + sfs->os_state |= OS_STATFS_READONLY; - sfs->os_state |= osd->od_nonrotational ? OS_STATE_NONROT : 0; + sfs->os_state |= osd->od_nonrotational ? OS_STATFS_NONROT : 0; if (ldiskfs_has_feature_extents(sb)) sfs->os_maxbytes = sb->s_maxbytes; @@ -2417,10 +2408,6 @@ static int osd_commit_async(const struct lu_env *env, RETURN(rc); } -/* Our own copy of the set readonly functions if present, or NU if not. */ -static int (*priv_dev_set_rdonly)(struct block_device *bdev); -static int (*priv_dev_check_rdonly)(struct block_device *bdev); -/* static int (*priv_dev_clear_rdonly)(struct block_device *bdev); */ static int (*priv_security_file_alloc)(struct file *file); int osd_security_file_alloc(struct file *file) @@ -2441,35 +2428,8 @@ static int osd_ro(const struct lu_env *env, struct dt_device *d) ENTRY; - if (priv_dev_set_rdonly) { - struct block_device *jdev = LDISKFS_SB(sb)->journal_bdev; - - rc = 0; - CERROR("*** setting %s read-only ***\n", - osd_dt_dev(d)->od_svname); - - if (sb->s_op->freeze_fs) { - rc = sb->s_op->freeze_fs(sb); - if (rc) - goto out; - } - - if (jdev && (jdev != dev)) { - CDEBUG(D_IOCTL | D_HA, "set journal dev %lx rdonly\n", - (long)jdev); - priv_dev_set_rdonly(jdev); - } - CDEBUG(D_IOCTL | D_HA, "set dev %lx rdonly\n", (long)dev); - priv_dev_set_rdonly(dev); - - if (sb->s_op->unfreeze_fs) - sb->s_op->unfreeze_fs(sb); - } - -out: - if (rc) - CERROR("%s: %lx CANNOT BE SET READONLY: rc = %d\n", - osd_dt_dev(d)->od_svname, (long)dev, rc); + CERROR("%s: %lx CANNOT BE SET READONLY: rc = %d\n", + osd_dt_dev(d)->od_svname, (long)dev, rc); RETURN(rc); } @@ -2618,11 +2578,12 @@ static void osd_inode_getattr(const struct lu_env *env, attr->la_valid |= LA_ATIME | LA_MTIME | LA_CTIME | LA_MODE | LA_SIZE | LA_BLOCKS | LA_UID | LA_GID | LA_PROJID | LA_FLAGS | LA_NLINK | LA_RDEV | - LA_BLKSIZE | LA_TYPE; + LA_BLKSIZE | LA_TYPE | LA_BTIME; attr->la_atime = inode->i_atime.tv_sec; attr->la_mtime = inode->i_mtime.tv_sec; attr->la_ctime = inode->i_ctime.tv_sec; + attr->la_btime = LDISKFS_I(inode)->i_crtime.tv_sec; attr->la_mode = inode->i_mode; attr->la_size = i_size_read(inode); attr->la_blocks = inode->i_blocks; @@ -2643,10 +2604,71 @@ static void osd_inode_getattr(const struct lu_env *env, attr->la_flags |= LUSTRE_PROJINHERIT_FL; } +static int osd_dirent_count(const struct lu_env *env, struct dt_object *dt, + u64 *count) +{ + struct osd_object *obj = osd_dt_obj(dt); + const struct dt_it_ops *iops; + struct dt_it *it; + int rc; + + ENTRY; + + LASSERT(S_ISDIR(obj->oo_inode->i_mode)); + LASSERT(fid_is_namespace_visible(lu_object_fid(&obj->oo_dt.do_lu))); + + if (obj->oo_dirent_count != LU_DIRENT_COUNT_UNSET) { + *count = obj->oo_dirent_count; + RETURN(0); + } + + /* directory not initialized yet */ + if (!dt->do_index_ops) { + *count = 0; + RETURN(0); + } + + iops = &dt->do_index_ops->dio_it; + it = iops->init(env, dt, LUDA_64BITHASH); + if (IS_ERR(it)) + RETURN(PTR_ERR(it)); + + rc = iops->load(env, it, 0); + if (rc < 0) { + if (rc == -ENODATA) { + rc = 0; + *count = 0; + } + GOTO(out, rc); + } + if (rc > 0) + rc = iops->next(env, it); + + for (*count = 0; rc == 0 || rc == -ESTALE; rc = iops->next(env, it)) { + if (rc == -ESTALE) + continue; + + if (iops->key_size(env, it) == 0) + continue; + + (*count)++; + } + if (rc == 1) { + obj->oo_dirent_count = *count; + rc = 0; + } +out: + iops->put(env, it); + iops->fini(env, it); + + RETURN(rc); +} + static int osd_attr_get(const struct lu_env *env, struct dt_object *dt, struct lu_attr *attr) { struct osd_object *obj = osd_dt_obj(dt); + int rc = 0; if (unlikely(!dt_object_exists(dt))) return -ENOENT; @@ -2662,9 +2684,17 @@ static int osd_attr_get(const struct lu_env *env, struct dt_object *dt, attr->la_valid |= LA_FLAGS; attr->la_flags |= LUSTRE_ORPHAN_FL; } + if (obj->oo_lma_flags & LUSTRE_ENCRYPT_FL) { + attr->la_valid |= LA_FLAGS; + attr->la_flags |= LUSTRE_ENCRYPT_FL; + } spin_unlock(&obj->oo_guard); - return 0; + if (S_ISDIR(obj->oo_inode->i_mode) && + fid_is_namespace_visible(lu_object_fid(&dt->do_lu))) + rc = osd_dirent_count(env, dt, &attr->la_dirent_count); + + return rc; } static int osd_declare_attr_qid(const struct lu_env *env, @@ -2747,7 +2777,7 @@ static int osd_declare_attr_set(const struct lu_env *env, obj = osd_dt_obj(dt); LASSERT(osd_invariant(obj)); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); osd_trans_declare_op(env, oh, OSD_OT_ATTR_SET, @@ -2862,6 +2892,13 @@ static int osd_inode_setattr(const struct lu_env *env, /* always keep S_NOCMTIME */ inode->i_flags = ll_ext_to_inode_flags(attr->la_flags) | S_NOCMTIME; +#if defined(S_ENCRYPTED) + /* Always remove S_ENCRYPTED, because ldiskfs must not be + * aware of encryption status. It is just stored into LMA + * so that it can be forwared to client side. + */ + inode->i_flags &= ~S_ENCRYPTED; +#endif /* * Ext4 did not transfer inherit flags from * @inode->i_flags to raw inode i_flags when writing @@ -2876,7 +2913,8 @@ static int osd_inode_setattr(const struct lu_env *env, } #ifdef HAVE_PROJECT_QUOTA -static int osd_transfer_project(struct inode *inode, __u32 projid) +static int osd_transfer_project(struct inode *inode, __u32 projid, + struct thandle *handle) { struct super_block *sb = inode->i_sb; struct ldiskfs_inode_info *ei = LDISKFS_I(inode); @@ -2908,9 +2946,18 @@ static int osd_transfer_project(struct inode *inode, __u32 projid) raw_inode = ldiskfs_raw_inode(&iloc); if (!LDISKFS_FITS_IN_INODE(raw_inode, ei, i_projid)) { - err = -EOVERFLOW; - brelse(iloc.bh); - return err; + struct osd_thandle *oh = container_of(handle, + struct osd_thandle, + ot_super); + /** + * try to expand inode size automatically. + */ + ldiskfs_mark_inode_dirty(oh->ot_handle, inode); + if (!LDISKFS_FITS_IN_INODE(raw_inode, ei, i_projid)) { + err = -EOVERFLOW; + brelse(iloc.bh); + return err; + } } brelse(iloc.bh); @@ -2927,7 +2974,8 @@ static int osd_transfer_project(struct inode *inode, __u32 projid) } #endif -static int osd_quota_transfer(struct inode *inode, const struct lu_attr *attr) +static int osd_quota_transfer(struct inode *inode, const struct lu_attr *attr, + struct thandle *handle) { int rc; @@ -2962,7 +3010,7 @@ static int osd_quota_transfer(struct inode *inode, const struct lu_attr *attr) if (attr->la_valid & LA_PROJID && attr->la_projid != i_projid_read(inode)) { #ifdef HAVE_PROJECT_QUOTA - rc = osd_transfer_project(inode, attr->la_projid); + rc = osd_transfer_project(inode, attr->la_projid, handle); #else rc = -ENOTSUPP; #endif @@ -3013,7 +3061,7 @@ static int osd_attr_set(const struct lu_env *env, if (unlikely(ipd == NULL)) RETURN(-ENOMEM); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); rc = iam_update(oh->ot_handle, bag, (const struct iam_key *)fid1, (const struct iam_rec *)id, ipd); @@ -3023,7 +3071,7 @@ static int osd_attr_set(const struct lu_env *env, inode = obj->oo_inode; - rc = osd_quota_transfer(inode, attr); + rc = osd_quota_transfer(inode, attr, handle); if (rc) return rc; @@ -3163,6 +3211,8 @@ static int osd_mkdir(struct osd_thread_info *info, struct osd_object *obj, oth = container_of(th, struct osd_thandle, ot_super); LASSERT(oth->ot_handle->h_transaction != NULL); + if (fid_is_namespace_visible(lu_object_fid(&obj->oo_dt.do_lu))) + obj->oo_dirent_count = 0; result = osd_mkfile(info, obj, mode, hint, th, attr); return result; @@ -3309,7 +3359,8 @@ static void osd_ah_init(const struct lu_env *env, struct dt_allocation_hint *ah, } static void osd_attr_init(struct osd_thread_info *info, struct osd_object *obj, - struct lu_attr *attr, struct dt_object_format *dof) + struct lu_attr *attr, struct dt_object_format *dof, + struct thandle *handle) { struct inode *inode = obj->oo_inode; __u64 valid = attr->la_valid; @@ -3326,7 +3377,7 @@ static void osd_attr_init(struct osd_thread_info *info, struct osd_object *obj, if ((valid & LA_MTIME) && (attr->la_mtime == inode->i_mtime.tv_sec)) attr->la_valid &= ~LA_MTIME; - result = osd_quota_transfer(inode, attr); + result = osd_quota_transfer(inode, attr, handle); if (result) return; @@ -3377,7 +3428,7 @@ static int __osd_create(struct osd_thread_info *info, struct osd_object *obj, } if (likely(result == 0)) { - osd_attr_init(info, obj, attr, dof); + osd_attr_init(info, obj, attr, dof, th); osd_object_init0(obj); } @@ -3405,7 +3456,7 @@ static int __osd_oi_insert(const struct lu_env *env, struct osd_object *obj, LASSERT(obj->oo_inode != NULL); - oh = container_of0(th, struct osd_thandle, ot_super); + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh->ot_handle); osd_trans_exec_op(env, th, OSD_OT_INSERT); @@ -3471,7 +3522,7 @@ static int osd_declare_create(const struct lu_env *env, struct dt_object *dt, LASSERT(handle != NULL); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); /* @@ -3529,7 +3580,7 @@ static int osd_declare_destroy(const struct lu_env *env, struct dt_object *dt, if (inode == NULL) RETURN(-ENOENT); - oh = container_of0(th, struct osd_thandle, ot_super); + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); osd_trans_declare_op(env, oh, OSD_OT_DESTROY, @@ -3580,7 +3631,7 @@ static int osd_destroy(const struct lu_env *env, struct dt_object *dt, ENTRY; - oh = container_of0(th, struct osd_thandle, ot_super); + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh->ot_handle); LASSERT(inode); LASSERT(!lu_object_is_dying(dt->do_lu.lo_header)); @@ -3596,8 +3647,10 @@ static int osd_destroy(const struct lu_env *env, struct dt_object *dt, } if (S_ISDIR(inode->i_mode)) { - LASSERT(osd_inode_unlinked(inode) || inode->i_nlink == 1 || - inode->i_nlink == 2); + if (inode->i_nlink > 2) + CERROR("%s: directory "DFID" ino %lu link count is %u at unlink. run e2fsck to repair\n", + osd_name(osd), PFID(fid), inode->i_ino, + inode->i_nlink); spin_lock(&obj->oo_guard); clear_nlink(inode); @@ -3801,6 +3854,7 @@ static struct inode *osd_create_local_agent_inode(const struct lu_env *env, struct osd_thread_info *info = osd_oti_get(env); struct inode *local; struct osd_thandle *oh; + uid_t own[2] = {0, 0}; int rc; ENTRY; @@ -3809,8 +3863,7 @@ static struct inode *osd_create_local_agent_inode(const struct lu_env *env, oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh->ot_handle->h_transaction != NULL); - local = ldiskfs_create_inode(oh->ot_handle, pobj->oo_inode, type, - NULL); + local = ldiskfs_create_inode(oh->ot_handle, pobj->oo_inode, type, own); if (IS_ERR(local)) { CERROR("%s: create local error %d\n", osd_name(osd), (int)PTR_ERR(local)); @@ -3842,7 +3895,7 @@ static struct inode *osd_create_local_agent_inode(const struct lu_env *env, #ifdef HAVE_PROJECT_QUOTA if (LDISKFS_I(pobj->oo_inode)->i_flags & LUSTRE_PROJINHERIT_FL && i_projid_read(pobj->oo_inode) != 0) { - rc = osd_transfer_project(local, 0); + rc = osd_transfer_project(local, 0, th); if (rc) { CERROR("%s: quota transfer failed: rc = %d. Is project " "quota enforcement enabled on the ldiskfs " @@ -4039,7 +4092,7 @@ static int osd_declare_ref_add(const struct lu_env *env, struct dt_object *dt, /* it's possible that object doesn't exist yet */ LASSERT(handle != NULL); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); osd_trans_declare_op(env, oh, OSD_OT_REF_ADD, @@ -4069,7 +4122,7 @@ static int osd_ref_add(const struct lu_env *env, struct dt_object *dt, LASSERT(osd_is_write_locked(env, obj)); LASSERT(th != NULL); - oh = container_of0(th, struct osd_thandle, ot_super); + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh->ot_handle != NULL); osd_trans_exec_op(env, th, OSD_OT_REF_ADD); @@ -4117,7 +4170,7 @@ static int osd_declare_ref_del(const struct lu_env *env, struct dt_object *dt, LASSERT(!dt_object_remote(dt)); LASSERT(handle != NULL); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); osd_trans_declare_op(env, oh, OSD_OT_REF_DEL, @@ -4145,7 +4198,10 @@ static int osd_ref_del(const struct lu_env *env, struct dt_object *dt, LASSERT(osd_is_write_locked(env, obj)); LASSERT(th != NULL); - oh = container_of0(th, struct osd_thandle, ot_super); + if (OBD_FAIL_CHECK(OBD_FAIL_OSD_REF_DEL)) + return -EIO; + + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh->ot_handle != NULL); osd_trans_exec_op(env, th, OSD_OT_REF_DEL); @@ -4296,7 +4352,7 @@ static int osd_declare_xattr_set(const struct lu_env *env, LASSERT(handle != NULL); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); if (strcmp(name, XATTR_NAME_LMA) == 0) { @@ -4435,7 +4491,7 @@ static int osd_xattr_set_pfid(const struct lu_env *env, struct osd_object *obj, /* Remove old PFID EA entry firstly. */ dquot_initialize(inode); - rc = osd_removexattr(dentry, inode, XATTR_NAME_FID); + rc = ll_vfs_removexattr(dentry, inode, XATTR_NAME_FID); if (rc == -ENODATA) { if ((fl & LU_XATTR_REPLACE) && !(fl & LU_XATTR_CREATE)) RETURN(rc); @@ -4515,7 +4571,7 @@ static int osd_xattr_handle_linkea(const struct lu_env *env, ENTRY; - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle != NULL); rc = linkea_init_with_rec(&ldata); @@ -4684,7 +4740,7 @@ static int osd_declare_xattr_del(const struct lu_env *env, LASSERT(!dt_object_remote(dt)); LASSERT(handle != NULL); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); osd_trans_declare_op(env, oh, OSD_OT_XATTR_SET, @@ -4741,7 +4797,7 @@ static int osd_xattr_del(const struct lu_env *env, struct dt_object *dt, dquot_initialize(inode); dentry->d_inode = inode; dentry->d_sb = inode->i_sb; - rc = osd_removexattr(dentry, inode, name); + rc = ll_vfs_removexattr(dentry, inode, name); } osd_trans_exec_check(env, handle, OSD_OT_XATTR_SET); @@ -4759,20 +4815,11 @@ static int osd_object_sync(const struct lu_env *env, struct dt_object *dt, { struct osd_object *obj = osd_dt_obj(dt); struct inode *inode = obj->oo_inode; - struct osd_thread_info *info = osd_oti_get(env); - struct dentry *dentry = &info->oti_obj_dentry; - struct file *file = &info->oti_file; + struct file *file = osd_quasi_file(env, inode); int rc; ENTRY; - dentry->d_inode = inode; - dentry->d_sb = inode->i_sb; - file->f_path.dentry = dentry; - file->f_mapping = inode->i_mapping; - file->f_op = inode->i_fop; - file->f_inode = inode; - rc = vfs_fsync_range(file, start, end, 0); RETURN(rc); @@ -4985,7 +5032,7 @@ static int osd_index_declare_iam_delete(const struct lu_env *env, { struct osd_thandle *oh; - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); /* Recycle may cause additional three blocks to be changed. */ @@ -5033,7 +5080,7 @@ static int osd_index_iam_delete(const struct lu_env *env, struct dt_object *dt, if (unlikely(ipd == NULL)) RETURN(-ENOMEM); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle != NULL); LASSERT(oh->ot_handle->h_transaction != NULL); @@ -5064,7 +5111,7 @@ static int osd_index_declare_ea_delete(const struct lu_env *env, LASSERT(!dt_object_remote(dt)); LASSERT(handle != NULL); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); credits = osd_dto_credits_noquota[DTO_INDEX_DELETE]; @@ -5226,11 +5273,21 @@ static int osd_index_ea_delete(const struct lu_env *env, struct dt_object *dt, } else { rc = PTR_ERR(bh); } + + if (!rc && fid_is_namespace_visible(lu_object_fid(&dt->do_lu)) && + obj->oo_dirent_count != LU_DIRENT_COUNT_UNSET) { + /* NB, dirent count may not be accurate, because it's counted + * without lock. + */ + if (obj->oo_dirent_count) + obj->oo_dirent_count--; + else + obj->oo_dirent_count = LU_DIRENT_COUNT_UNSET; + } if (hlock != NULL) ldiskfs_htree_unlock(hlock); else up_write(&obj->oo_ext_idx_sem); - GOTO(out, rc); out: LASSERT(osd_invariant(obj)); @@ -5317,7 +5374,7 @@ static int osd_index_declare_iam_insert(const struct lu_env *env, LASSERT(handle != NULL); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); osd_trans_declare_op(env, oh, OSD_OT_INSERT, @@ -5367,7 +5424,7 @@ static int osd_index_iam_insert(const struct lu_env *env, struct dt_object *dt, if (unlikely(ipd == NULL)) RETURN(-ENOMEM); - oh = container_of0(th, struct osd_thandle, ot_super); + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh->ot_handle != NULL); LASSERT(oh->ot_handle->h_transaction != NULL); if (S_ISDIR(obj->oo_inode->i_mode)) { @@ -5565,6 +5622,10 @@ static int osd_ea_add_rec(const struct lu_env *env, struct osd_object *pobj, hlock, th); } } + if (!rc && fid_is_namespace_visible(lu_object_fid(&pobj->oo_dt.do_lu)) + && pobj->oo_dirent_count != LU_DIRENT_COUNT_UNSET) + pobj->oo_dirent_count++; + if (hlock != NULL) ldiskfs_htree_unlock(hlock); else @@ -5590,8 +5651,7 @@ osd_consistency_check(struct osd_thread_info *oti, struct osd_device *dev, if (!fid_is_norm(fid) && !fid_is_igif(fid)) RETURN(0); - if (thread_is_running(&scrub->os_thread) && - scrub->os_pos_current > id->oii_ino) + if (scrub->os_running && scrub->os_pos_current > id->oii_ino) RETURN(0); if (dev->od_auto_scrub_interval == AS_NEVER || @@ -5632,7 +5692,7 @@ again: insert = false; trigger: - if (thread_is_running(&scrub->os_thread)) { + if (scrub->os_running) { if (inode == NULL) { inode = osd_iget(oti, dev, id); /* The inode has been removed (by race maybe). */ @@ -5958,7 +6018,7 @@ static int osd_index_declare_ea_insert(const struct lu_env *env, LASSERT(fid != NULL); LASSERT(rec1->rec_type != 0); - oh = container_of0(handle, struct osd_thandle, ot_super); + oh = container_of(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_handle == NULL); credits = osd_dto_credits_noquota[DTO_INDEX_INSERT]; @@ -6118,6 +6178,7 @@ static int osd_index_ea_insert(const struct lu_env *env, struct dt_object *dt, iput(child_inode); LASSERT(osd_invariant(obj)); osd_trans_exec_check(env, th, OSD_OT_INSERT); + RETURN(rc); } @@ -7213,8 +7274,6 @@ static inline int osd_it_ea_rec(const struct lu_env *env, rc = osd_ea_fid_get(env, obj, ino, fid, id); } - } else { - osd_id_gen(id, ino, OSD_OII_NOGEN); } } @@ -7224,15 +7283,6 @@ static inline int osd_it_ea_rec(const struct lu_env *env, it->oie_dirent->oied_namelen, it->oie_dirent->oied_type, attr); - if (rc < 0) - RETURN(rc); - - if (osd_remote_fid(env, dev, fid)) - RETURN(0); - - if (likely(!(attr & (LUDA_IGNORE | LUDA_UNKNOWN)) && rc == 0)) - osd_add_oi_cache(oti, dev, id, fid); - RETURN(rc > 0 ? 0 : rc); } @@ -7389,11 +7439,17 @@ static void osd_key_fini(const struct lu_context *ctx, if (info->oti_dio_pages) { int i; for (i = 0; i < PTLRPC_MAX_BRW_PAGES; i++) { - if (info->oti_dio_pages[i]) - __free_page(info->oti_dio_pages[i]); + struct page *page = info->oti_dio_pages[i]; + if (page) { + LASSERT(PagePrivate2(page)); + LASSERT(PageLocked(page)); + ClearPagePrivate2(page); + unlock_page(page); + __free_page(page); + } } - OBD_FREE(info->oti_dio_pages, - sizeof(struct page *) * PTLRPC_MAX_BRW_PAGES); + OBD_FREE_PTR_ARRAY_LARGE(info->oti_dio_pages, + PTLRPC_MAX_BRW_PAGES); } if (info->oti_inode != NULL) @@ -7407,7 +7463,7 @@ static void osd_key_fini(const struct lu_context *ctx, lu_buf_free(&info->oti_big_buf); if (idc != NULL) { LASSERT(info->oti_ins_cache_size > 0); - OBD_FREE(idc, sizeof(*idc) * info->oti_ins_cache_size); + OBD_FREE_PTR_ARRAY(idc, info->oti_ins_cache_size); info->oti_ins_cache = NULL; info->oti_ins_cache_size = 0; } @@ -7449,7 +7505,7 @@ static int osd_device_init(const struct lu_env *env, struct lu_device *d, static int osd_fid_init(const struct lu_env *env, struct osd_device *osd) { struct seq_server_site *ss = osd_seq_site(osd); - int rc; + int rc = 0; ENTRY; @@ -7463,13 +7519,8 @@ static int osd_fid_init(const struct lu_env *env, struct osd_device *osd) if (osd->od_cl_seq == NULL) RETURN(-ENOMEM); - rc = seq_client_init(osd->od_cl_seq, NULL, LUSTRE_SEQ_METADATA, - osd->od_svname, ss->ss_server_seq); - if (rc != 0) { - OBD_FREE_PTR(osd->od_cl_seq); - osd->od_cl_seq = NULL; - RETURN(rc); - } + seq_client_init(osd->od_cl_seq, NULL, LUSTRE_SEQ_METADATA, + osd->od_svname, ss->ss_server_seq); if (ss->ss_node_id == 0) { /* @@ -7600,7 +7651,7 @@ static int osd_mount(const struct lu_env *env, *options = '\0'; if (opts != NULL) { /* strip out the options for back compatiblity */ - static char *sout[] = { + static const char * const sout[] = { "mballoc", "iopen", "noiopen", @@ -7668,23 +7719,10 @@ static int osd_mount(const struct lu_env *env, } if (lmd_flags & LMD_FLG_DEV_RDONLY) { - if (priv_dev_set_rdonly) { - priv_dev_set_rdonly(osd_sb(o)->s_bdev); - o->od_dt_dev.dd_rdonly = 1; - LCONSOLE_WARN("%s: set dev_rdonly on this device\n", - name); - } else { - LCONSOLE_WARN("%s: not support dev_rdonly on this device", - name); + LCONSOLE_WARN("%s: not support dev_rdonly on this device", + name); - GOTO(out_mnt, rc = -EOPNOTSUPP); - } - } else if (priv_dev_check_rdonly && - priv_dev_check_rdonly(osd_sb(o)->s_bdev)) { - CERROR("%s: underlying device %s is marked as " - "read-only. Setup failed\n", name, dev); - - GOTO(out_mnt, rc = -EROFS); + GOTO(out_mnt, rc = -EOPNOTSUPP); } if (!ldiskfs_has_feature_journal(o->od_mnt->mnt_sb)) { @@ -7920,10 +7958,8 @@ static struct lu_device *osd_device_free(const struct lu_env *env, /* XXX: make osd top device in order to release reference */ d->ld_site->ls_top_dev = d; lu_site_purge(env, d->ld_site, -1); - if (!cfs_hash_is_empty(d->ld_site->ls_obj_hash)) { - LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_ERROR, NULL); - lu_site_print(env, d->ld_site, &msgdata, lu_cdebug_printer); - } + lu_site_print(env, d->ld_site, &d->ld_site->ls_obj_hash.nelems, + D_ERROR, lu_cdebug_printer); lu_site_fini(&o->od_site); dt_device_fini(&o->od_dt_dev); OBD_FREE_PTR(o); @@ -8095,10 +8131,18 @@ static int osd_prepare(const struct lu_env *env, struct lu_device *pdev, RETURN(result); } -static int osd_fid_alloc(const struct lu_env *env, struct obd_export *exp, - struct lu_fid *fid, struct md_op_data *op_data) +/** + * Implementation of lu_device_operations::ldo_fid_alloc() for OSD + * + * Allocate FID. + * + * see include/lu_object.h for the details. + */ +static int osd_fid_alloc(const struct lu_env *env, struct lu_device *d, + struct lu_fid *fid, struct lu_object *parent, + const struct lu_name *name) { - struct osd_device *osd = osd_dev(exp->exp_obd->obd_lu_dev); + struct osd_device *osd = osd_dev(d); return seq_client_alloc_fid(env, osd->od_cl_seq, fid); } @@ -8117,6 +8161,7 @@ const struct lu_device_operations osd_lu_ops = { .ldo_process_config = osd_process_config, .ldo_recovery_complete = osd_recovery_complete, .ldo_prepare = osd_prepare, + .ldo_fid_alloc = osd_fid_alloc, }; static const struct lu_device_type_operations osd_device_type_ops = { @@ -8155,7 +8200,6 @@ static const struct obd_ops osd_obd_device_ops = { .o_owner = THIS_MODULE, .o_connect = osd_obd_connect, .o_disconnect = osd_obd_disconnect, - .o_fid_alloc = osd_fid_alloc, .o_health_check = osd_health_check, }; @@ -8204,9 +8248,6 @@ static int __init osd_init(void) #ifdef CONFIG_KALLSYMS priv_security_file_alloc = (void *)kallsyms_lookup_name("security_file_alloc"); - priv_dev_set_rdonly = (void *)kallsyms_lookup_name("dev_set_rdonly"); - priv_dev_check_rdonly = - (void *)kallsyms_lookup_name("dev_check_rdonly"); #endif rc = class_register_type(&osd_obd_device_ops, NULL, true, NULL,