sbi->ll_flags |= LL_SBI_LRU_RESIZE;
#endif
-#ifdef HAVE_EXPORT___IGET
- CFS_INIT_LIST_HEAD(&sbi->ll_deathrow);
- cfs_spin_lock_init(&sbi->ll_deathrow_lock);
-#endif
for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) {
cfs_spin_lock_init(&sbi->ll_rw_extents_info.pp_extents[i]. \
pp_r_hist.oh_lock);
}
}
-#ifdef HAVE_EXPORT___IGET
-static void prune_dir_dentries(struct inode *inode)
-{
- struct dentry *dentry, *prev = NULL;
-
- /* due to lustre specific logic, a directory
- * can have few dentries - a bug from VFS POV */
-restart:
- spin_lock(&dcache_lock);
- if (!list_empty(&inode->i_dentry)) {
- dentry = list_entry(inode->i_dentry.prev,
- struct dentry, d_alias);
- /* in order to prevent infinite loops we
- * break if previous dentry is busy */
- if (dentry != prev) {
- prev = dentry;
- dget_locked(dentry);
- spin_unlock(&dcache_lock);
-
- /* try to kill all child dentries */
- lock_dentry(dentry);
- shrink_dcache_parent(dentry);
- unlock_dentry(dentry);
- dput(dentry);
-
- /* now try to get rid of current dentry */
- d_prune_aliases(inode);
- goto restart;
- }
- }
- spin_unlock(&dcache_lock);
-}
-
-static void prune_deathrow_one(struct ll_inode_info *lli)
-{
- struct inode *inode = ll_info2i(lli);
-
- /* first, try to drop any dentries - they hold a ref on the inode */
- if (S_ISDIR(inode->i_mode))
- prune_dir_dentries(inode);
- else
- d_prune_aliases(inode);
-
-
- /* if somebody still uses it, leave it */
- LASSERT(atomic_read(&inode->i_count) > 0);
- if (atomic_read(&inode->i_count) > 1)
- goto out;
-
- CDEBUG(D_INODE, "inode %lu/%u(%d) looks a good candidate for prune\n",
- inode->i_ino,inode->i_generation,
- atomic_read(&inode->i_count));
-
- /* seems nobody uses it anymore */
- inode->i_nlink = 0;
-
-out:
- iput(inode);
- return;
-}
-
-static void prune_deathrow(struct ll_sb_info *sbi, int try)
-{
- struct ll_inode_info *lli;
- int empty;
-
- do {
- if (need_resched() && try)
- break;
-
- if (try) {
- if (!cfs_spin_trylock(&sbi->ll_deathrow_lock))
- break;
- } else {
- cfs_spin_lock(&sbi->ll_deathrow_lock);
- }
-
- empty = 1;
- lli = NULL;
- if (!cfs_list_empty(&sbi->ll_deathrow)) {
- lli = cfs_list_entry(sbi->ll_deathrow.next,
- struct ll_inode_info,
- lli_dead_list);
- cfs_list_del_init(&lli->lli_dead_list);
- if (!cfs_list_empty(&sbi->ll_deathrow))
- empty = 0;
- }
- cfs_spin_unlock(&sbi->ll_deathrow_lock);
-
- if (lli)
- prune_deathrow_one(lli);
-
- } while (empty == 0);
-}
-#else /* !HAVE_EXPORT___IGET */
-#define prune_deathrow(sbi, try) do {} while (0)
-#endif /* HAVE_EXPORT___IGET */
-
void client_common_put_super(struct super_block *sb)
{
struct ll_sb_info *sbi = ll_s2sbi(sb);
cl_sb_fini(sb);
- /* destroy inodes in deathrow */
- prune_deathrow(sbi, 0);
-
cfs_list_del(&sbi->ll_conn_chain);
obd_fid_fini(sbi->ll_dt_exp);
#endif
lli->lli_inode_magic = LLI_INODE_DEAD;
-#ifdef HAVE_EXPORT___IGET
- cfs_spin_lock(&sbi->ll_deathrow_lock);
- cfs_list_del_init(&lli->lli_dead_list);
- cfs_spin_unlock(&sbi->ll_deathrow_lock);
-#endif
ll_clear_inode_capas(inode);
/*
* XXX This has to be done before lsm is freed below, because
RETURN(rc);
}
-static int ll_setattr_do_truncate(struct inode *inode, loff_t size)
+static int ll_setattr_ost(struct inode *inode, struct iattr *attr)
{
- struct obd_capa *capa = ll_osscapa_get(inode, CAPA_OPC_OSS_TRUNC);
+ struct obd_capa *capa;
int rc;
- rc = cl_setattr_do_truncate(inode, size, capa);
- ll_truncate_free_capa(capa);
- return rc;
-}
+ if (attr->ia_valid & ATTR_SIZE)
+ capa = ll_osscapa_get(inode, CAPA_OPC_OSS_TRUNC);
+ else
+ capa = ll_mdscapa_get(inode);
-static int ll_setattr_ost(struct inode *inode)
-{
- struct obd_capa *capa = ll_mdscapa_get(inode);
- int rc;
+ rc = cl_setattr_ost(inode, attr, capa);
- rc = cl_setattr_ost(inode, capa);
- capa_put(capa);
+ if (attr->ia_valid & ATTR_SIZE)
+ ll_truncate_free_capa(capa);
+ else
+ capa_put(capa);
return rc;
}
attr->ia_mtime = CFS_CURRENT_TIME;
attr->ia_valid |= ATTR_MTIME_SET;
}
- if ((attr->ia_valid & ATTR_CTIME) && !(attr->ia_valid & ATTR_MTIME)) {
- /* To avoid stale mtime on mds, obtain it from ost and send
- to mds. */
- rc = cl_glimpse_size(inode);
- if (rc)
- RETURN(rc);
-
- attr->ia_valid |= ATTR_MTIME_SET | ATTR_MTIME;
- attr->ia_mtime = inode->i_mtime;
- }
if (attr->ia_valid & (ATTR_MTIME | ATTR_CTIME))
CDEBUG(D_INODE, "setting mtime %lu, ctime %lu, now = %lu\n",
memcpy(&op_data->op_attr, attr, sizeof(*attr));
/* Open epoch for truncate. */
- if (exp_connect_som(ll_i2mdexp(inode)) && (ia_valid & ATTR_SIZE))
+ if (exp_connect_som(ll_i2mdexp(inode)) &&
+ (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET)))
op_data->op_flags = MF_EPOCH_OPEN;
rc = ll_md_setattr(inode, op_data, &mod);
}
if (ia_valid & ATTR_SIZE)
- rc = ll_setattr_do_truncate(inode, attr->ia_size);
- else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) {
- CDEBUG(D_INODE, "set mtime on OST inode %lu to %lu\n",
- inode->i_ino, LTIME_S(attr->ia_mtime));
- rc = ll_setattr_ost(inode);
- }
+ attr->ia_valid |= ATTR_SIZE;
+ if ((ia_valid & ATTR_SIZE) |
+ ((ia_valid | ATTR_ATIME | ATTR_ATIME_SET) &&
+ LTIME_S(attr->ia_atime) < LTIME_S(attr->ia_ctime)) ||
+ ((ia_valid | ATTR_MTIME | ATTR_MTIME_SET) &&
+ LTIME_S(attr->ia_mtime) < LTIME_S(attr->ia_ctime)))
+ /* perform truncate and setting mtime/atime to past under PW
+ * 0:EOF extent lock (new_size:EOF for truncate) */
+ rc = ll_setattr_ost(inode, attr);
EXIT;
out:
if (op_data) {
inode->i_ino = cl_fid_build_ino(&body->fid1);
inode->i_generation = cl_fid_build_gen(&body->fid1);
- if (body->valid & OBD_MD_FLATIME &&
- body->atime > LTIME_S(inode->i_atime))
- LTIME_S(inode->i_atime) = body->atime;
-
- /* mtime is always updated with ctime, but can be set in past.
- As write and utime(2) may happen within 1 second, and utime's
- mtime has a priority over write's one, so take mtime from mds
- for the same ctimes. */
- if (body->valid & OBD_MD_FLCTIME &&
- body->ctime >= LTIME_S(inode->i_ctime)) {
- LTIME_S(inode->i_ctime) = body->ctime;
- if (body->valid & OBD_MD_FLMTIME) {
- CDEBUG(D_INODE, "setting ino %lu mtime "
- "from %lu to "LPU64"\n", inode->i_ino,
+ if (body->valid & OBD_MD_FLATIME) {
+ if (body->atime > LTIME_S(inode->i_atime))
+ LTIME_S(inode->i_atime) = body->atime;
+ lli->lli_lvb.lvb_atime = body->atime;
+ }
+ if (body->valid & OBD_MD_FLMTIME) {
+ if (body->mtime > LTIME_S(inode->i_mtime)) {
+ CDEBUG(D_INODE, "setting ino %lu mtime from %lu "
+ "to "LPU64"\n", inode->i_ino,
LTIME_S(inode->i_mtime), body->mtime);
LTIME_S(inode->i_mtime) = body->mtime;
}
+ lli->lli_lvb.lvb_mtime = body->mtime;
+ }
+ if (body->valid & OBD_MD_FLCTIME) {
+ if (body->ctime > LTIME_S(inode->i_ctime))
+ LTIME_S(inode->i_ctime) = body->ctime;
+ lli->lli_lvb.lvb_ctime = body->ctime;
}
if (body->valid & OBD_MD_FLMODE)
inode->i_mode = (inode->i_mode & S_IFMT)|(body->mode & ~S_IFMT);
LASSERT(*inode || sb);
sbi = sb ? ll_s2sbi(sb) : ll_i2sbi(*inode);
- prune_deathrow(sbi, 1);
memset(&md, 0, sizeof(struct lustre_md));
rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp,