hash = fd->fd_dir.lfd_next;
} else {
- struct ll_inode_info *lli = ll_i2info(inode);
-
- cfs_spin_lock(&lli->lli_sa_lock);
- if (lli->lli_sai)
- LASSERT(lli->lli_sai->sai_pid == cfs_curproc_pid());
- else
- LASSERT(lli->lli_opendir_pid == cfs_curproc_pid());
- hash = lli->lli_sa_pos;
- cfs_spin_unlock(&lli->lli_sa_lock);
+ hash = ll_i2info(inode)->lli_sa_pos;
}
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) hash "LPU64"\n",
inode->i_ino, inode->i_generation, inode, hash);
SetPageChecked(page);
}
-static void ll_release_page(struct page *page, __u64 hash,
- __u64 start, __u64 end)
+void ll_release_page(struct page *page, int remove)
{
kunmap(page);
- lock_page(page);
- if (likely(page->mapping != NULL)) {
- ll_truncate_complete_page(page);
- unlock_page(page);
- } else {
+ if (remove) {
+ lock_page(page);
+ if (likely(page->mapping != NULL))
+ truncate_complete_page(page->mapping, page);
unlock_page(page);
- CWARN("NULL mapping page %p, truncated by others: "
- "hash("LPX64") | start("LPX64") | end("LPX64")\n",
- page, hash, start, end);
}
page_cache_release(page);
}
LPX64",hash = "LPX64"\n", *start, *end, *hash);
CDEBUG(D_VFSTRACE, "page %lu [%llu %llu], hash "LPU64"\n",
offset, *start, *end, *hash);
- if (*hash > *end || (*end != *start && *hash == *end)) {
+ if (*hash > *end) {
+ ll_release_page(page, 0);
+ page = NULL;
+ } else if (*end != *start && *hash == *end) {
/*
* upon hash collision, remove this page,
* otherwise put page reference, and
* ll_get_dir_page() will issue RPC to fetch
* the page we want.
*/
- if (dp->ldp_flags & cpu_to_le32(LDF_COLLIDE)) {
- ll_release_page(page, *hash, *start, *end);
- } else {
- cfs_kunmap(page);
- page_cache_release(page);
- }
+ ll_release_page(page,
+ le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE);
page = NULL;
}
} else {
}
struct page *ll_get_dir_page(struct file *filp, struct inode *dir, __u64 hash,
- int exact, struct ll_dir_chain *chain)
+ struct ll_dir_chain *chain)
{
ldlm_policy_data_t policy = {.l_inodebits = {MDS_INODELOCK_UPDATE} };
struct address_space *mapping = dir->i_mapping;
CERROR("dir page locate: "DFID" at "LPU64": rc %ld\n",
PFID(ll_inode2fid(dir)), lhash, PTR_ERR(page));
GOTO(out_unlock, page);
- }
-
- if (page != NULL) {
+ } else if (page != NULL) {
/*
* XXX nikita: not entirely correct handling of a corner case:
* suppose hash chain of entries with hash value HASH crosses
* it as an "overflow" page. 1. invalidate all pages at
* once. 2. use HASH|1 as an index for P1.
*/
- if (exact && lhash != start) {
- /*
- * readdir asked for a page starting _exactly_ from
- * given hash, but cache contains stale page, with
- * entries with smaller hash values. Stale page should
- * be invalidated, and new one fetched.
- */
- CDEBUG(D_OTHER, "Stale readpage page %p: "
- "start = "LPX64",end = "LPX64"hash ="LPX64"\n",
- page, start, end, lhash);
- ll_release_page(page, lhash, start, end);
- } else {
- GOTO(hash_collision, page);
- }
+ GOTO(hash_collision, page);
}
page = read_cache_page(mapping, hash_x_index(hash, hash64),
return page;
fail:
- ll_put_page(page);
+ ll_release_page(page, 1);
page = ERR_PTR(-EIO);
goto out_unlock;
}
struct page *page;
struct ll_dir_chain chain;
int done;
- int shift;
int rc;
ENTRY;
rc = 0;
done = 0;
- shift = 0;
ll_dir_chain_init(&chain);
fd->fd_dir.lfd_next = pos;
- page = ll_get_dir_page(filp, inode, pos, 0, &chain);
+ page = ll_get_dir_page(filp, inode, pos, &chain);
while (rc == 0 && !done) {
struct lu_dirpage *dp;
lhash, ino, type);
}
next = le64_to_cpu(dp->ldp_hash_end);
- ll_put_page(page);
if (!done) {
pos = next;
if (pos == MDS_DIR_END_OFF) {
* End of directory reached.
*/
done = 1;
+ ll_release_page(page, 0);
} else if (1 /* chain is exhausted*/) {
/*
* Normal case: continue to the next
* page.
*/
+ ll_release_page(page,
+ le32_to_cpu(dp->ldp_flags) &
+ LDF_COLLIDE);
fd->fd_dir.lfd_next = pos;
page = ll_get_dir_page(filp, inode, pos,
- 1, &chain);
+ &chain);
} else {
/*
* go into overflow page.
*/
+ LASSERT(le32_to_cpu(dp->ldp_flags) &
+ LDF_COLLIDE);
+ ll_release_page(page, 1);
}
} else {
pos = hash;
+ ll_release_page(page, 0);
}
} else {
rc = PTR_ERR(page);
op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL,
0, lmmsize, LUSTRE_OPC_ANY,
NULL);
- if (op_data == NULL)
- RETURN(-ENOMEM);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
op_data->op_valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
rc = md_getattr(sbi->ll_md_exp, op_data, &req);
op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0,
0, LUSTRE_OPC_ANY, NULL);
- if (op_data == NULL)
- RETURN(-ENOMEM);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
op_data->op_valid |= OBD_MD_MDTIDX;
rc = md_getattr(sbi->ll_md_exp, op_data, NULL);
OBD_FREE_PTR(oqctl);
RETURN(rc);
}
+ /* If QIF_SPACE is not set, client should collect the
+ * space usage from OSSs by itself */
+ if (cmd == Q_GETQUOTA &&
+ !(oqctl->qc_dqblk.dqb_valid & QIF_SPACE) &&
+ !oqctl->qc_dqblk.dqb_curspace) {
+ struct obd_quotactl *oqctl_tmp;
+
+ OBD_ALLOC_PTR(oqctl_tmp);
+ if (oqctl_tmp == NULL)
+ GOTO(out, rc = -ENOMEM);
+
+ oqctl_tmp->qc_cmd = Q_GETOQUOTA;
+ oqctl_tmp->qc_id = oqctl->qc_id;
+ oqctl_tmp->qc_type = oqctl->qc_type;
+
+ /* collect space usage from OSTs */
+ oqctl_tmp->qc_dqblk.dqb_curspace = 0;
+ rc = obd_quotactl(sbi->ll_dt_exp, oqctl_tmp);
+ if (!rc || rc == -EREMOTEIO) {
+ oqctl->qc_dqblk.dqb_curspace =
+ oqctl_tmp->qc_dqblk.dqb_curspace;
+ oqctl->qc_dqblk.dqb_valid |= QIF_SPACE;
+ }
+
+ /* collect space & inode usage from MDTs */
+ oqctl_tmp->qc_dqblk.dqb_curspace = 0;
+ oqctl_tmp->qc_dqblk.dqb_curinodes = 0;
+ rc = obd_quotactl(sbi->ll_md_exp, oqctl_tmp);
+ if (!rc || rc == -EREMOTEIO) {
+ oqctl->qc_dqblk.dqb_curspace +=
+ oqctl_tmp->qc_dqblk.dqb_curspace;
+ oqctl->qc_dqblk.dqb_curinodes =
+ oqctl_tmp->qc_dqblk.dqb_curinodes;
+ oqctl->qc_dqblk.dqb_valid |= QIF_INODES;
+ } else {
+ oqctl->qc_dqblk.dqb_valid &= ~QIF_SPACE;
+ }
+ OBD_FREE_PTR(oqctl_tmp);
+ }
+out:
QCTL_COPY(qctl, oqctl);
OBD_FREE_PTR(oqctl);
}
RETURN(rc);
}
-static int ll_dir_ioctl(struct inode *inode, struct file *file,
+#ifdef HAVE_UNLOCKED_IOCTL
+static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#else
+static int ll_dir_ioctl(struct inode *unuse, struct file *file,
unsigned int cmd, unsigned long arg)
+#endif
{
+ struct inode *inode = file->f_dentry->d_inode;
struct ll_sb_info *sbi = ll_i2sbi(inode);
struct obd_ioctl_data *data;
int rc = 0;
op_data = ll_prep_md_op_data(NULL, inode, NULL, filename, namelen,
0, LUSTRE_OPC_ANY, NULL);
- if (op_data == NULL)
- GOTO(out_free, rc = -ENOMEM);
+ if (IS_ERR(op_data))
+ GOTO(out_free, rc = PTR_ERR(op_data));
op_data->op_valid = OBD_MD_FLID;
rc = md_getattr_name(sbi->ll_md_exp, op_data, &request);
OBD_FREE_PTR(qctl);
RETURN(rc);
}
- case OBD_IOC_GETNAME: {
- struct obd_device *obd = class_exp2obd(sbi->ll_dt_exp);
- if (!obd)
- RETURN(-EFAULT);
- if (cfs_copy_to_user((void *)arg, obd->obd_name,
- strlen(obd->obd_name) + 1))
- RETURN (-EFAULT);
- RETURN(0);
- }
+ case OBD_IOC_GETDTNAME:
+ case OBD_IOC_GETMDNAME:
+ RETURN(ll_get_obd_name(inode, cmd, arg));
case LL_IOC_FLUSHCTX:
RETURN(ll_flush_ctx(inode));
#ifdef CONFIG_FS_POSIX_ACL
.release = ll_dir_release,
.read = generic_read_dir,
.readdir = ll_readdir,
- .ioctl = ll_dir_ioctl,
- .fsync = ll_fsync
+#ifdef HAVE_UNLOCKED_IOCTL
+ .unlocked_ioctl = ll_dir_ioctl,
+#else
+ .ioctl = ll_dir_ioctl,
+#endif
+ .fsync = ll_fsync,
};