filter.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,698 行 · 第 1/5 页
C
1,698 行
RETURN(0); /* XXX if fcd_uuid were a real obd_uuid, I could use obd_uuid_equals */ if (strcmp(fed->fed_fcd->fcd_uuid, obd->obd_uuid.uuid ) == 0) GOTO(free, 0); CDEBUG(D_INFO, "freeing client at idx %u, offset %lld with UUID '%s'\n", fed->fed_lr_idx, off, fed->fed_fcd->fcd_uuid); LASSERT(filter->fo_last_rcvd_slots != NULL); off = fed->fed_lr_off; /* Don't clear fed_lr_idx here as it is likely also unset. At worst * we leak a client slot that will be cleaned on the next recovery. */ if (off <= 0) { CERROR("%s: client idx %d has med_off %lld\n", obd->obd_name, fed->fed_lr_idx, off); GOTO(free, rc = -EINVAL); } /* Clear the bit _after_ zeroing out the client so we don't race with filter_client_add and zero out new clients.*/ if (!test_bit(fed->fed_lr_idx, filter->fo_last_rcvd_slots)) { CERROR("FILTER client %u: bit already clear in bitmap!!\n", fed->fed_lr_idx); LBUG(); } if (!(exp->exp_flags & OBD_OPT_FAILOVER)) { memset(&zero_fcd, 0, sizeof zero_fcd); push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); rc = fsfilt_write_record(obd, filter->fo_rcvd_filp, &zero_fcd, sizeof(zero_fcd), &off, (!exp->exp_libclient || exp->exp_need_sync)); if (rc == 0) /* update server's transno */ filter_update_server_data(obd, filter->fo_rcvd_filp, filter->fo_fsd, !exp->exp_libclient); pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); CDEBUG(rc == 0 ? D_INFO : D_ERROR, "zeroing out client %s at idx %u (%llu) in %s rc %d\n", fed->fed_fcd->fcd_uuid, fed->fed_lr_idx, fed->fed_lr_off, LAST_RCVD, rc); } if (!test_and_clear_bit(fed->fed_lr_idx, filter->fo_last_rcvd_slots)) { CERROR("FILTER client %u: bit already clear in bitmap!!\n", fed->fed_lr_idx); LBUG(); } EXIT;free: OBD_FREE(fed->fed_fcd, sizeof(*fed->fed_fcd)); fed->fed_fcd = NULL; return 0;}/* drop fmd reference, free it if last ref. must be called with fed_lock held.*/static inline void filter_fmd_put_nolock(struct filter_export_data *fed, struct filter_mod_data *fmd){ LASSERT_SPIN_LOCKED(&fed->fed_lock); if (--fmd->fmd_refcount == 0) { /* XXX when we have persistent reservations and the handle * is stored herein we need to drop it here. */ fed->fed_mod_count--; list_del(&fmd->fmd_list); OBD_SLAB_FREE(fmd, ll_fmd_cachep, sizeof(*fmd)); }}/* drop fmd reference, free it if last ref */void filter_fmd_put(struct obd_export *exp, struct filter_mod_data *fmd){ struct filter_export_data *fed; if (fmd == NULL) return; fed = &exp->exp_filter_data; spin_lock(&fed->fed_lock); filter_fmd_put_nolock(fed, fmd); /* caller reference */ spin_unlock(&fed->fed_lock);}/* expire entries from the end of the list if there are too many * or they are too old */static void filter_fmd_expire_nolock(struct filter_obd *filter, struct filter_export_data *fed, struct filter_mod_data *keep){ struct filter_mod_data *fmd, *tmp; list_for_each_entry_safe(fmd, tmp, &fed->fed_mod_list, fmd_list) { if (fmd == keep) break; if (time_before(jiffies, fmd->fmd_expire) && fed->fed_mod_count < filter->fo_fmd_max_num) break; list_del_init(&fmd->fmd_list); filter_fmd_put_nolock(fed, fmd); /* list reference */ }}void filter_fmd_expire(struct obd_export *exp){ spin_lock(&exp->exp_filter_data.fed_lock); filter_fmd_expire_nolock(&exp->exp_obd->u.filter, &exp->exp_filter_data, NULL); spin_unlock(&exp->exp_filter_data.fed_lock);}/* find specified objid, group in export fmd list. * caller must hold fed_lock and take fmd reference itself */static struct filter_mod_data *filter_fmd_find_nolock(struct filter_obd *filter, struct filter_export_data *fed, obd_id objid, obd_gr group){ struct filter_mod_data *found = NULL, *fmd; LASSERT_SPIN_LOCKED(&fed->fed_lock); list_for_each_entry_reverse(fmd, &fed->fed_mod_list, fmd_list) { if (fmd->fmd_id == objid && fmd->fmd_gr == group) { found = fmd; list_del(&fmd->fmd_list); list_add_tail(&fmd->fmd_list, &fed->fed_mod_list); fmd->fmd_expire = jiffies + filter->fo_fmd_max_age; break; } } filter_fmd_expire_nolock(filter, fed, found); return found;}/* Find fmd based on objid and group, or return NULL if not found. */struct filter_mod_data *filter_fmd_find(struct obd_export *exp, obd_id objid, obd_gr group){ struct filter_mod_data *fmd; spin_lock(&exp->exp_filter_data.fed_lock); fmd = filter_fmd_find_nolock(&exp->exp_obd->u.filter, &exp->exp_filter_data, objid, group); if (fmd) fmd->fmd_refcount++; /* caller reference */ spin_unlock(&exp->exp_filter_data.fed_lock); return fmd;}/* Find fmd based on objid and group, or create a new one if none is found. * It is possible for this function to return NULL under memory pressure, * or if objid = 0 is passed (which will only cause old entries to expire). * Currently this is not fatal because any fmd state is transient and * may also be freed when it gets sufficiently old. */struct filter_mod_data *filter_fmd_get(struct obd_export *exp, obd_id objid, obd_gr group){ struct filter_export_data *fed = &exp->exp_filter_data; struct filter_mod_data *found = NULL, *fmd_new = NULL; OBD_SLAB_ALLOC(fmd_new, ll_fmd_cachep, CFS_ALLOC_IO, sizeof(*fmd_new)); spin_lock(&fed->fed_lock); found = filter_fmd_find_nolock(&exp->exp_obd->u.filter,fed,objid,group); if (fmd_new) { if (found == NULL) { list_add_tail(&fmd_new->fmd_list, &fed->fed_mod_list); fmd_new->fmd_id = objid; fmd_new->fmd_gr = group; fmd_new->fmd_refcount++; /* list reference */ found = fmd_new; fed->fed_mod_count++; } else { OBD_SLAB_FREE(fmd_new, ll_fmd_cachep, sizeof(*fmd_new)); } } if (found) { found->fmd_refcount++; /* caller reference */ found->fmd_expire = jiffies + exp->exp_obd->u.filter.fo_fmd_max_age; } spin_unlock(&fed->fed_lock); return found;}#ifdef DO_FMD_DROP/* drop fmd list reference so it will disappear when last reference is put. * This isn't so critical because it would in fact only affect the one client * that is doing the unlink and at worst we have an stale entry referencing * an object that should never be used again. */static void filter_fmd_drop(struct obd_export *exp, obd_id objid, obd_gr group){ struct filter_mod_data *found = NULL; spin_lock(&exp->exp_filter_data.fed_lock); found = filter_fmd_find_nolock(&exp->exp_filter_data, objid, group); if (found) { list_del_init(&found->fmd_list); filter_fmd_put_nolock(&exp->exp_filter_data, found); } spin_unlock(&exp->exp_filter_data.fed_lock);}#else#define filter_fmd_drop(exp, objid, group)#endif/* remove all entries from fmd list */static void filter_fmd_cleanup(struct obd_export *exp){ struct filter_export_data *fed = &exp->exp_filter_data; struct filter_mod_data *fmd = NULL, *tmp; spin_lock(&fed->fed_lock); list_for_each_entry_safe(fmd, tmp, &fed->fed_mod_list, fmd_list) { list_del_init(&fmd->fmd_list); filter_fmd_put_nolock(fed, fmd); } spin_unlock(&fed->fed_lock);}static int filter_init_export(struct obd_export *exp){ spin_lock_init(&exp->exp_filter_data.fed_lock); INIT_LIST_HEAD(&exp->exp_filter_data.fed_mod_list); spin_lock(&exp->exp_lock); exp->exp_connecting = 1; spin_unlock(&exp->exp_lock); return 0;}static int filter_free_server_data(struct filter_obd *filter){ OBD_FREE(filter->fo_fsd, sizeof(*filter->fo_fsd)); filter->fo_fsd = NULL; OBD_FREE(filter->fo_last_rcvd_slots, LR_MAX_CLIENTS / 8); filter->fo_last_rcvd_slots = NULL; return 0;}/* assumes caller is already in kernel ctxt */int filter_update_server_data(struct obd_device *obd, struct file *filp, struct lr_server_data *fsd, int force_sync){ loff_t off = 0; int rc; ENTRY; CDEBUG(D_INODE, "server uuid : %s\n", fsd->lsd_uuid); CDEBUG(D_INODE, "server last_rcvd : "LPU64"\n", le64_to_cpu(fsd->lsd_last_transno)); CDEBUG(D_INODE, "server last_mount: "LPU64"\n", le64_to_cpu(fsd->lsd_mount_count)); fsd->lsd_compat14 = fsd->lsd_last_transno; rc = fsfilt_write_record(obd, filp, fsd, sizeof(*fsd), &off,force_sync); if (rc) CERROR("error writing lr_server_data: rc = %d\n", rc); RETURN(rc);}int filter_update_last_objid(struct obd_device *obd, obd_gr group, int force_sync){ struct filter_obd *filter = &obd->u.filter; __u64 tmp; loff_t off = 0; int rc; ENTRY; if (filter->fo_last_objid_files[group] == NULL) { CERROR("Object group "LPU64" not fully setup; not updating " "last_objid\n", group); RETURN(-EINVAL); } CDEBUG(D_INODE, "%s: server last_objid for group "LPU64": "LPU64"\n", obd->obd_name, group, filter->fo_last_objids[group]); tmp = cpu_to_le64(filter->fo_last_objids[group]); rc = fsfilt_write_record(obd, filter->fo_last_objid_files[group], &tmp, sizeof(tmp), &off, force_sync); if (rc) CERROR("error writing group "LPU64" last objid: rc = %d\n", group, rc); RETURN(rc);}/* assumes caller has already in kernel ctxt */static int filter_init_server_data(struct obd_device *obd, struct file * filp){ struct filter_obd *filter = &obd->u.filter; struct lr_server_data *fsd; struct filter_client_data *fcd = NULL; struct inode *inode = filp->f_dentry->d_inode; unsigned long last_rcvd_size = i_size_read(inode); __u64 mount_count; int cl_idx; loff_t off = 0; int rc; /* ensure padding in the struct is the correct size */ CLASSERT (offsetof(struct lr_server_data, lsd_padding) + sizeof(fsd->lsd_padding) == LR_SERVER_SIZE); CLASSERT (offsetof(struct filter_client_data, fcd_padding) + sizeof(fcd->fcd_padding) == LR_CLIENT_SIZE); OBD_ALLOC(fsd, sizeof(*fsd)); if (!fsd) RETURN(-ENOMEM); filter->fo_fsd = fsd; OBD_ALLOC(filter->fo_last_rcvd_slots, LR_MAX_CLIENTS / 8); if (filter->fo_last_rcvd_slots == NULL) { OBD_FREE(fsd, sizeof(*fsd)); RETURN(-ENOMEM); } if (last_rcvd_size == 0) { LCONSOLE_WARN("%s: new disk, initializing\n", obd->obd_name); memcpy(fsd->lsd_uuid, obd->obd_uuid.uuid,sizeof(fsd->lsd_uuid)); fsd->lsd_last_transno = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?