static struct inode *ll_alloc_inode(struct super_block *sb) { struct ll_inode_info *lli; ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_ALLOC_INODE, 1); OBD_SLAB_ALLOC_PTR_GFP(lli, ll_inode_cachep, CFS_ALLOC_IO); if (lli == NULL) return NULL; inode_init_once(&lli->lli_vfs_inode); return &lli->lli_vfs_inode; }
int ll_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { struct inode *inode = d_inode(dentry); LASSERT(inode); LASSERT(name); CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n", inode->i_ino, inode->i_generation, inode, name); ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1); if ((strncmp(name, XATTR_TRUSTED_PREFIX, sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 && strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) || (strncmp(name, XATTR_LUSTRE_PREFIX, sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 && strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) { struct lov_user_md *lump = (struct lov_user_md *)value; int rc = 0; if (size != 0 && size < sizeof(struct lov_user_md)) return -EINVAL; /* Attributes that are saved via getxattr will always have * the stripe_offset as 0. Instead, the MDS should be * allowed to pick the starting OST index. b=17846 */ if (lump && lump->lmm_stripe_offset == 0) lump->lmm_stripe_offset = -1; if (lump && S_ISREG(inode->i_mode)) { int flags = FMODE_WRITE; int lum_size = (lump->lmm_magic == LOV_USER_MAGIC_V1) ? sizeof(*lump) : sizeof(struct lov_user_md_v3); rc = ll_lov_setstripe_ea_info(inode, dentry, flags, lump, lum_size); /* b10667: rc always be 0 here for now */ rc = 0; } else if (S_ISDIR(inode->i_mode)) { rc = ll_dir_setstripe(inode, lump, 0); } return rc; } else if (strcmp(name, XATTR_NAME_LMA) == 0 || strcmp(name, XATTR_NAME_LINK) == 0) return 0; return ll_setxattr_common(inode, name, value, size, flags, OBD_MD_FLXATTR); }
static struct inode *ll_alloc_inode(struct super_block *sb) { struct ll_inode_info *lli; ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_ALLOC_INODE, 1); lli = kmem_cache_zalloc(ll_inode_cachep, GFP_NOFS); if (!lli) return NULL; inode_init_once(&lli->lli_vfs_inode); return &lli->lli_vfs_inode; }
int ll_removexattr(struct dentry *dentry, const char *name) { struct inode *inode = dentry->d_inode; LASSERT(inode); LASSERT(name); CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n", inode->i_ino, inode->i_generation, inode, name); ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1); return ll_setxattr_common(inode, name, NULL, 0, 0, OBD_MD_FLXATTRRM); }
static int ll_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) { int count = 0; bool printed = false; bool retry; int result; ll_stats_ops_tally(ll_i2sbi(file_inode(vma->vm_file)), LPROC_LL_MKWRITE, 1); file_update_time(vma->vm_file); do { retry = false; result = ll_page_mkwrite0(vma, vmf->page, &retry); if (!printed && ++count > 16) { const struct dentry *de = file_dentry(vma->vm_file); CWARN("app(%s): the page %lu of file "DFID" is under" " heavy contention\n", current->comm, vmf->pgoff, PFID(ll_inode2fid(de->d_inode))); printed = true; } } while (retry); switch(result) { case 0: LASSERT(PageLocked(vmf->page)); result = VM_FAULT_LOCKED; break; case -ENODATA: case -EFAULT: result = VM_FAULT_NOPAGE; break; case -ENOMEM: result = VM_FAULT_OOM; break; case -EAGAIN: result = VM_FAULT_RETRY; break; default: result = VM_FAULT_SIGBUS; break; } return result; }
int ll_file_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file_inode(file); int rc; if (ll_file_nolock(file)) return -EOPNOTSUPP; ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_MAP, 1); rc = generic_file_mmap(file, vma); if (rc == 0) { vma->vm_ops = &ll_file_vm_ops; vma->vm_ops->open(vma); /* update the inode's size and mtime */ rc = ll_glimpse_size(inode); } return rc; }
static int ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { int count = 0; bool printed = false; int result; sigset_t set; /* Only SIGKILL and SIGTERM is allowed for fault/nopage/mkwrite * so that it can be killed by admin but not cause segfault by * other signals. */ set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM)); ll_stats_ops_tally(ll_i2sbi(file_inode(vma->vm_file)), LPROC_LL_FAULT, 1); restart: result = ll_fault0(vma, vmf); if (!(result & (VM_FAULT_RETRY | VM_FAULT_ERROR | VM_FAULT_LOCKED))) { struct page *vmpage = vmf->page; /* check if this page has been truncated */ lock_page(vmpage); if (unlikely(vmpage->mapping == NULL)) { /* unlucky */ unlock_page(vmpage); put_page(vmpage); vmf->page = NULL; if (!printed && ++count > 16) { CWARN("the page is under heavy contention," "maybe your app(%s) needs revising :-)\n", current->comm); printed = true; } goto restart; } result |= VM_FAULT_LOCKED; } cfs_restore_sigs(set); return result; }
ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) { struct inode *inode = dentry->d_inode; int rc = 0, rc2 = 0; struct lov_mds_md *lmm = NULL; struct ptlrpc_request *request = NULL; int lmmsize; LASSERT(inode); CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1); rc = ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS); if (rc < 0) GOTO(out, rc); if (buffer != NULL) { struct ll_sb_info *sbi = ll_i2sbi(inode); char *xattr_name = buffer; int xlen, rem = rc; while (rem > 0) { xlen = strnlen(xattr_name, rem - 1) + 1; rem -= xlen; if (xattr_type_filter(sbi, get_xattr_type(xattr_name)) == 0) { /* skip OK xattr type * leave it in buffer */ xattr_name += xlen; continue; } /* move up remaining xattrs in buffer * removing the xattr that is not OK */ memmove(xattr_name, xattr_name + xlen, rem); rc -= xlen; } } if (S_ISREG(inode->i_mode)) { if (!ll_i2info(inode)->lli_has_smd) rc2 = -1; } else if (S_ISDIR(inode->i_mode)) { rc2 = ll_dir_getstripe(inode, &lmm, &lmmsize, &request); } if (rc2 < 0) { GOTO(out, rc2 = 0); } else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) { const int prefix_len = sizeof(XATTR_LUSTRE_PREFIX) - 1; const size_t name_len = sizeof("lov") - 1; const size_t total_len = prefix_len + name_len + 1; if (((rc + total_len) > size) && (buffer != NULL)) { ptlrpc_req_finished(request); return -ERANGE; } if (buffer != NULL) { buffer += rc; memcpy(buffer, XATTR_LUSTRE_PREFIX, prefix_len); memcpy(buffer + prefix_len, "lov", name_len); buffer[prefix_len + name_len] = '\0'; } rc2 = total_len; } out: ptlrpc_req_finished(request); rc = rc + rc2; return rc; }
ssize_t ll_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size) { struct inode *inode = dentry->d_inode; LASSERT(inode); LASSERT(name); CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n", inode->i_ino, inode->i_generation, inode, name); ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); if ((strncmp(name, XATTR_TRUSTED_PREFIX, sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 && strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) || (strncmp(name, XATTR_LUSTRE_PREFIX, sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 && strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) { struct lov_stripe_md *lsm; struct lov_user_md *lump; struct lov_mds_md *lmm = NULL; struct ptlrpc_request *request = NULL; int rc = 0, lmmsize = 0; if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) return -ENODATA; if (size == 0 && S_ISDIR(inode->i_mode)) { /* XXX directory EA is fix for now, optimize to save * RPC transfer */ GOTO(out, rc = sizeof(struct lov_user_md)); } lsm = ccc_inode_lsm_get(inode); if (lsm == NULL) { if (S_ISDIR(inode->i_mode)) { rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request); } else { rc = -ENODATA; } } else { /* LSM is present already after lookup/getattr call. * we need to grab layout lock once it is implemented */ rc = obd_packmd(ll_i2dtexp(inode), &lmm, lsm); lmmsize = rc; } ccc_inode_lsm_put(inode, lsm); if (rc < 0) GOTO(out, rc); if (size == 0) { /* used to call ll_get_max_mdsize() forward to get * the maximum buffer size, while some apps (such as * rsync 3.0.x) care much about the exact xattr value * size */ rc = lmmsize; GOTO(out, rc); } if (size < lmmsize) { CERROR("server bug: replied size %d > %d for %s (%s)\n", lmmsize, (int)size, dentry->d_name.name, name); GOTO(out, rc = -ERANGE); } lump = (struct lov_user_md *)buffer; memcpy(lump, lmm, lmmsize); /* do not return layout gen for getxattr otherwise it would * confuse tar --xattr by recognizing layout gen as stripe * offset when the file is restored. See LU-2809. */ lump->lmm_layout_gen = 0; rc = lmmsize; out: if (request) ptlrpc_req_finished(request); else if (lmm) obd_free_diskmd(ll_i2dtexp(inode), &lmm); return(rc); } return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR); }