static int panic_notifier(struct notifier_block *self, unsigned long unused1, void *unused2) { if (libcfs_panic_in_progress) return 0; libcfs_panic_in_progress = 1; mb(); #ifdef LNET_DUMP_ON_PANIC /* This is currently disabled because it spews far too much to the * console on the rare cases it is ever triggered. */ if (in_interrupt()) { cfs_trace_debug_print(); } else { # ifdef HAVE_KERNEL_LOCKED while (kernel_locked()) unlock_kernel(); # endif libcfs_debug_dumplog_internal((void *)(long)cfs_curproc_pid()); } #endif return 0; }
void libcfs_debug_dumplog(void) { cfs_waitlink_t wait; cfs_task_t *dumper; ENTRY; /* we're being careful to ensure that the kernel thread is * able to set our state to running as it exits before we * get to schedule() */ cfs_waitlink_init(&wait); cfs_set_current_state(CFS_TASK_INTERRUPTIBLE); cfs_waitq_add(&debug_ctlwq, &wait); dumper = cfs_kthread_run(libcfs_debug_dumplog_thread, (void*)(long)cfs_curproc_pid(), "libcfs_debug_dumper"); if (IS_ERR(dumper)) printk(CFS_KERN_ERR "LustreError: cannot start log dump thread:" " %ld\n", PTR_ERR(dumper)); else cfs_waitq_wait(&wait, CFS_TASK_INTERRUPTIBLE); /* be sure to teardown if cfs_create_thread() failed */ cfs_waitq_del(&debug_ctlwq, &wait); cfs_set_current_state(CFS_TASK_RUNNING); }
void set_ptldebug_header(struct ptldebug_header *header, int subsys, int mask, const int line, unsigned long stack) { struct timeval tv; /* * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT) * from here: this will lead to infinite recursion. */ do_gettimeofday(&tv); header->ph_subsys = subsys; header->ph_mask = mask; header->ph_cpu_id = cfs_smp_processor_id(); header->ph_type = 0; header->ph_sec = (__u32)tv.tv_sec; header->ph_usec = tv.tv_usec; header->ph_stack = stack; header->ph_pid = cfs_curproc_pid(); header->ph_line_num = line; header->ph_extern_pid = (__u32)current_thread(); }
struct lc_watchdog *lc_watchdog_add(int timeout, void (*callback)(pid_t, void *), void *data) { struct lc_watchdog *lcw = NULL; ENTRY; LIBCFS_ALLOC(lcw, sizeof(*lcw)); if (lcw == NULL) { CDEBUG(D_INFO, "Could not allocate new lc_watchdog\n"); RETURN(ERR_PTR(-ENOMEM)); } cfs_spin_lock_init(&lcw->lcw_lock); lcw->lcw_refcount = 1; /* refcount for owner */ lcw->lcw_task = cfs_current(); lcw->lcw_pid = cfs_curproc_pid(); lcw->lcw_callback = (callback != NULL) ? callback : lc_watchdog_dumplog; lcw->lcw_data = data; lcw->lcw_state = LC_WATCHDOG_DISABLED; CFS_INIT_LIST_HEAD(&lcw->lcw_list); cfs_timer_init(&lcw->lcw_timer, lcw_cb, lcw); cfs_down(&lcw_refcount_sem); if (++lcw_refcount == 1) lcw_dispatch_start(); cfs_up(&lcw_refcount_sem); /* Keep this working in case we enable them by default */ if (lcw->lcw_state == LC_WATCHDOG_ENABLED) { lcw->lcw_last_touched = cfs_time_current(); cfs_timer_arm(&lcw->lcw_timer, cfs_time_seconds(timeout) + cfs_time_current()); } RETURN(lcw); }
/* Must be called under the lov_stripe_lock() */ int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm, obd_off size, int shrink) { struct lov_oinfo *loi; int stripe = 0; __u64 kms; ENTRY; LASSERT_SPIN_LOCKED(&lsm->lsm_lock); #ifdef __KERNEL__ LASSERT(lsm->lsm_lock_owner == cfs_curproc_pid()); #endif if (shrink) { for (; stripe < lsm->lsm_stripe_count; stripe++) { struct lov_oinfo *loi = lsm->lsm_oinfo[stripe]; kms = lov_size_to_stripe(lsm, size, stripe); CDEBUG(D_INODE, "stripe %d KMS %sing "LPU64"->"LPU64"\n", stripe, kms > loi->loi_kms ? "increas":"shrink", loi->loi_kms, kms); loi_kms_set(loi, loi->loi_lvb.lvb_size = kms); } RETURN(0); } if (size > 0) stripe = lov_stripe_number(lsm, size - 1); kms = lov_size_to_stripe(lsm, size, stripe); loi = lsm->lsm_oinfo[stripe]; CDEBUG(D_INODE, "stripe %d KMS %sincreasing "LPU64"->"LPU64"\n", stripe, kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms); if (kms > loi->loi_kms) loi_kms_set(loi, kms); RETURN(0); }
static int ll_getxattr_common(struct inode *inode, const char *name, void *buffer, size_t size, __u64 valid) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req = NULL; struct mdt_body *body; int xattr_type, rc; void *xdata; struct obd_capa *oc; struct rmtacl_ctl_entry *rce = NULL; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); /* listxattr have slightly different behavior from of ext3: * without 'user_xattr' ext3 will list all xattr names but * filtered out "^user..*"; we list them all for simplicity. */ if (!name) { xattr_type = XATTR_OTHER_T; goto do_getxattr; } xattr_type = get_xattr_type(name); rc = xattr_type_filter(sbi, xattr_type); if (rc) RETURN(rc); /* b15587: ignore security.capability xattr for now */ if ((xattr_type == XATTR_SECURITY_T && strcmp(name, "security.capability") == 0)) RETURN(-ENODATA); /* LU-549: Disable security.selinux when selinux is disabled */ if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && strcmp(name, "security.selinux") == 0) RETURN(-EOPNOTSUPP); #ifdef CONFIG_FS_POSIX_ACL if (sbi->ll_flags & LL_SBI_RMT_CLIENT && (xattr_type == XATTR_ACL_ACCESS_T || xattr_type == XATTR_ACL_DEFAULT_T)) { rce = rct_search(&sbi->ll_rct, cfs_curproc_pid()); if (rce == NULL || (rce->rce_ops != RMT_LSETFACL && rce->rce_ops != RMT_LGETFACL && rce->rce_ops != RMT_RSETFACL && rce->rce_ops != RMT_RGETFACL)) RETURN(-EOPNOTSUPP); } /* posix acl is under protection of LOOKUP lock. when calling to this, * we just have path resolution to the target inode, so we have great * chance that cached ACL is uptodate. */ if (xattr_type == XATTR_ACL_ACCESS_T && !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) { struct ll_inode_info *lli = ll_i2info(inode); struct posix_acl *acl; spin_lock(&lli->lli_lock); acl = posix_acl_dup(lli->lli_posix_acl); spin_unlock(&lli->lli_lock); if (!acl) RETURN(-ENODATA); rc = posix_acl_to_xattr(acl, buffer, size); posix_acl_release(acl); RETURN(rc); } if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode)) RETURN(-ENODATA); #endif do_getxattr: oc = ll_mdscapa_get(inode); rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid | (rce ? rce_ops2valid(rce->rce_ops) : 0), name, NULL, 0, size, 0, &req); capa_put(oc); if (rc) { if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { LCONSOLE_INFO("Disabling user_xattr feature because " "it is not supported on the server\n"); sbi->ll_flags &= ~LL_SBI_USER_XATTR; } RETURN(rc); } body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); LASSERT(body); /* only detect the xattr size */ if (size == 0) GOTO(out, rc = body->eadatasize); if (size < body->eadatasize) { CERROR("server bug: replied size %u > %u\n", body->eadatasize, (int)size); GOTO(out, rc = -ERANGE); } if (body->eadatasize == 0) GOTO(out, rc = -ENODATA); /* do not need swab xattr data */ xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, body->eadatasize); if (!xdata) GOTO(out, rc = -EFAULT); #ifdef CONFIG_FS_POSIX_ACL if (body->eadatasize >= 0 && rce && rce->rce_ops == RMT_LSETFACL) { ext_acl_xattr_header *acl; acl = lustre_posix_acl_xattr_2ext((posix_acl_xattr_header *)xdata, body->eadatasize); if (IS_ERR(acl)) GOTO(out, rc = PTR_ERR(acl)); rc = ee_add(&sbi->ll_et, cfs_curproc_pid(), ll_inode2fid(inode), xattr_type, acl); if (unlikely(rc < 0)) { lustre_ext_acl_xattr_free(acl); GOTO(out, rc); } } #endif if (body->eadatasize == 0) { rc = -ENODATA; } else { LASSERT(buffer); memcpy(buffer, xdata, body->eadatasize); rc = body->eadatasize; } EXIT; out: ptlrpc_req_finished(req); return rc; }
static int ll_setxattr_common(struct inode *inode, const char *name, const void *value, size_t size, int flags, __u64 valid) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req; int xattr_type, rc; struct obd_capa *oc; posix_acl_xattr_header *new_value = NULL; struct rmtacl_ctl_entry *rce = NULL; ext_acl_xattr_header *acl = NULL; const char *pv = value; ENTRY; xattr_type = get_xattr_type(name); rc = xattr_type_filter(sbi, xattr_type); if (rc) RETURN(rc); /* b10667: ignore lustre special xattr for now */ if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) || (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0)) RETURN(0); /* b15587: ignore security.capability xattr for now */ if ((xattr_type == XATTR_SECURITY_T && strcmp(name, "security.capability") == 0)) RETURN(0); /* LU-549: Disable security.selinux when selinux is disabled */ if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && strcmp(name, "security.selinux") == 0) RETURN(-EOPNOTSUPP); #ifdef CONFIG_FS_POSIX_ACL if (sbi->ll_flags & LL_SBI_RMT_CLIENT && (xattr_type == XATTR_ACL_ACCESS_T || xattr_type == XATTR_ACL_DEFAULT_T)) { rce = rct_search(&sbi->ll_rct, cfs_curproc_pid()); if (rce == NULL || (rce->rce_ops != RMT_LSETFACL && rce->rce_ops != RMT_RSETFACL)) RETURN(-EOPNOTSUPP); if (rce->rce_ops == RMT_LSETFACL) { struct eacl_entry *ee; ee = et_search_del(&sbi->ll_et, cfs_curproc_pid(), ll_inode2fid(inode), xattr_type); LASSERT(ee != NULL); if (valid & OBD_MD_FLXATTR) { acl = lustre_acl_xattr_merge2ext( (posix_acl_xattr_header *)value, size, ee->ee_acl); if (IS_ERR(acl)) { ee_free(ee); RETURN(PTR_ERR(acl)); } size = CFS_ACL_XATTR_SIZE(\ le32_to_cpu(acl->a_count), \ ext_acl_xattr); pv = (const char *)acl; } ee_free(ee); } else if (rce->rce_ops == RMT_RSETFACL) { size = lustre_posix_acl_xattr_filter( (posix_acl_xattr_header *)value, size, &new_value); if (unlikely(size < 0)) RETURN(size); pv = (const char *)new_value; } else RETURN(-EOPNOTSUPP); valid |= rce_ops2valid(rce->rce_ops); } #endif oc = ll_mdscapa_get(inode); rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name, pv, size, 0, flags, ll_i2suppgid(inode), &req); capa_put(oc); #ifdef CONFIG_FS_POSIX_ACL if (new_value != NULL) lustre_posix_acl_xattr_free(new_value, size); if (acl != NULL) lustre_ext_acl_xattr_free(acl); #endif if (rc) { if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { LCONSOLE_INFO("Disabling user_xattr feature because " "it is not supported on the server\n"); sbi->ll_flags &= ~LL_SBI_USER_XATTR; } RETURN(rc); } ptlrpc_req_finished(req); RETURN(0); }
/** Merge the lock value block(&lvb) attributes and KMS from each of the * stripes in a file into a single lvb. It is expected that the caller * initializes the current atime, mtime, ctime to avoid regressing a more * uptodate time on the local client. */ int lov_merge_lvb_kms(struct lov_stripe_md *lsm, struct ost_lvb *lvb, __u64 *kms_place) { __u64 size = 0; __u64 kms = 0; __u64 blocks = 0; obd_time current_mtime = lvb->lvb_mtime; obd_time current_atime = lvb->lvb_atime; obd_time current_ctime = lvb->lvb_ctime; int i; int rc = 0; LASSERT_SPIN_LOCKED(&lsm->lsm_lock); #ifdef __KERNEL__ LASSERT(lsm->lsm_lock_owner == cfs_curproc_pid()); #endif CDEBUG(D_INODE, "MDT FID "DFID" initial value: s="LPU64" m="LPU64 " a="LPU64" c="LPU64" b="LPU64"\n", lsm->lsm_object_seq, (__u32)lsm->lsm_object_id, (__u32)(lsm->lsm_object_id >> 32), lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks); for (i = 0; i < lsm->lsm_stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; obd_size lov_size, tmpsize; if (OST_LVB_IS_ERR(loi->loi_lvb.lvb_blocks)) { rc = OST_LVB_GET_ERR(loi->loi_lvb.lvb_blocks); continue; } tmpsize = loi->loi_kms; lov_size = lov_stripe_size(lsm, tmpsize, i); if (lov_size > kms) kms = lov_size; if (loi->loi_lvb.lvb_size > tmpsize) tmpsize = loi->loi_lvb.lvb_size; lov_size = lov_stripe_size(lsm, tmpsize, i); if (lov_size > size) size = lov_size; /* merge blocks, mtime, atime */ blocks += loi->loi_lvb.lvb_blocks; if (loi->loi_lvb.lvb_mtime > current_mtime) current_mtime = loi->loi_lvb.lvb_mtime; if (loi->loi_lvb.lvb_atime > current_atime) current_atime = loi->loi_lvb.lvb_atime; if (loi->loi_lvb.lvb_ctime > current_ctime) current_ctime = loi->loi_lvb.lvb_ctime; CDEBUG(D_INODE, "MDT FID "DFID" on OST[%u]: s="LPU64" m="LPU64 " a="LPU64" c="LPU64" b="LPU64"\n", lsm->lsm_object_seq, (__u32)lsm->lsm_object_id, (__u32)(lsm->lsm_object_id >> 32), loi->loi_ost_idx, loi->loi_lvb.lvb_size, loi->loi_lvb.lvb_mtime, loi->loi_lvb.lvb_atime, loi->loi_lvb.lvb_ctime, loi->loi_lvb.lvb_blocks); } *kms_place = kms; lvb->lvb_size = size; lvb->lvb_blocks = blocks; lvb->lvb_mtime = current_mtime; lvb->lvb_atime = current_atime; lvb->lvb_ctime = current_ctime; RETURN(rc); }