diff options
Diffstat (limited to 'drivers/staging/lustre/lustre/llite/llite_lib.c')
-rw-r--r-- | drivers/staging/lustre/lustre/llite/llite_lib.c | 126 |
1 files changed, 63 insertions, 63 deletions
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 25f5aed97f63..b229cbc7bb33 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -103,6 +103,7 @@ static struct ll_sb_info *ll_init_sbi(struct super_block *sb) sbi->ll_flags |= LL_SBI_CHECKSUM; sbi->ll_flags |= LL_SBI_LRU_RESIZE; + sbi->ll_flags |= LL_SBI_LAZYSTATFS; for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) { spin_lock_init(&sbi->ll_rw_extents_info.pp_extents[i]. @@ -303,6 +304,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sb->s_magic = LL_SUPER_MAGIC; sb->s_maxbytes = MAX_LFS_FILESIZE; sbi->ll_namelen = osfs->os_namelen; + sbi->ll_mnt.mnt = current->fs->root.mnt; if ((sbi->ll_flags & LL_SBI_USER_XATTR) && !(data->ocd_connect_flags & OBD_CONNECT_XATTR)) { @@ -1402,7 +1404,11 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data) * cache is not cleared yet. */ op_data->op_attr.ia_valid &= ~(TIMES_SET_FLAGS | ATTR_SIZE); + if (S_ISREG(inode->i_mode)) + inode_lock(inode); rc = simple_setattr(dentry, &op_data->op_attr); + if (S_ISREG(inode->i_mode)) + inode_unlock(inode); op_data->op_attr.ia_valid = ia_valid; rc = ll_update_inode(inode, &md); @@ -1431,7 +1437,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) struct inode *inode = d_inode(dentry); struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; - bool file_is_released = false; int rc = 0; CDEBUG(D_VFSTRACE, "%s: setattr inode "DFID"(%p) from %llu to %llu, valid %x, hsm_import %d\n", @@ -1486,76 +1491,35 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime), (s64)ktime_get_real_seconds()); - /* We always do an MDS RPC, even if we're only changing the size; - * only the MDS knows whether truncate() should fail with -ETXTBUSY - */ - - op_data = kzalloc(sizeof(*op_data), GFP_NOFS); - if (!op_data) - return -ENOMEM; - - if (!S_ISDIR(inode->i_mode)) + if (S_ISREG(inode->i_mode)) inode_unlock(inode); - /* truncate on a released file must failed with -ENODATA, - * so size must not be set on MDS for released file - * but other attributes must be set + /* + * We always do an MDS RPC, even if we're only changing the size; + * only the MDS knows whether truncate() should fail with -ETXTBUSY */ - if (S_ISREG(inode->i_mode)) { - struct cl_layout cl = { - .cl_is_released = false, - }; - struct lu_env *env; - int refcheck; - __u32 gen; + op_data = kzalloc(sizeof(*op_data), GFP_NOFS); + if (!op_data) { + rc = -ENOMEM; + goto out; + } - rc = ll_layout_refresh(inode, &gen); - if (rc < 0) - goto out; + op_data->op_attr = *attr; + if (!hsm_import && attr->ia_valid & ATTR_SIZE) { /* - * XXX: the only place we need to know the layout type, - * this will be removed by a later patch. -Jinshan + * If we are changing file size, file content is + * modified, flag it. */ - env = cl_env_get(&refcheck); - if (IS_ERR(env)) { - rc = PTR_ERR(env); - goto out; - } - - rc = cl_object_layout_get(env, lli->lli_clob, &cl); - cl_env_put(env, &refcheck); - if (rc < 0) - goto out; - - file_is_released = cl.cl_is_released; - - if (!hsm_import && attr->ia_valid & ATTR_SIZE) { - if (file_is_released) { - rc = ll_layout_restore(inode, 0, attr->ia_size); - if (rc < 0) - goto out; - - file_is_released = false; - ll_layout_refresh(inode, &gen); - } - - /* - * If we are changing file size, file content is - * modified, flag it. - */ - attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; - op_data->op_bias |= MDS_DATA_MODIFIED; - } + attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + op_data->op_bias |= MDS_DATA_MODIFIED; } - memcpy(&op_data->op_attr, attr, sizeof(*attr)); - rc = ll_md_setattr(dentry, op_data); if (rc) goto out; - if (!S_ISREG(inode->i_mode) || file_is_released) { + if (!S_ISREG(inode->i_mode) || hsm_import) { rc = 0; goto out; } @@ -1572,11 +1536,40 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) */ rc = cl_setattr_ost(ll_i2info(inode)->lli_clob, attr, 0); } + + /* + * If the file was restored, it needs to set dirty flag. + * + * We've already sent MDS_DATA_MODIFIED flag in + * ll_md_setattr() for truncate. However, the MDT refuses to + * set the HS_DIRTY flag on released files, so we have to set + * it again if the file has been restored. Please check how + * LLIF_DATA_MODIFIED is set in vvp_io_setattr_fini(). + * + * Please notice that if the file is not released, the previous + * MDS_DATA_MODIFIED has taken effect and usually + * LLIF_DATA_MODIFIED is not set(see vvp_io_setattr_fini()). + * This way we can save an RPC for common open + trunc + * operation. + */ + if (test_and_clear_bit(LLIF_DATA_MODIFIED, &lli->lli_flags)) { + struct hsm_state_set hss = { + .hss_valid = HSS_SETMASK, + .hss_setmask = HS_DIRTY, + }; + int rc2; + + rc2 = ll_hsm_state_set(inode, &hss); + if (rc2 < 0) + CERROR(DFID "HSM set dirty failed: rc2 = %d\n", + PFID(ll_inode2fid(inode)), rc2); + } + out: if (op_data) ll_finish_md_op_data(op_data); - if (!S_ISDIR(inode->i_mode)) { + if (S_ISREG(inode->i_mode)) { inode_lock(inode); if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) inode_dio_wait(inode); @@ -1599,7 +1592,7 @@ int ll_setattr(struct dentry *de, struct iattr *attr) if (((attr->ia_valid & (ATTR_MODE | ATTR_FORCE | ATTR_SIZE)) == (ATTR_SIZE | ATTR_MODE)) && (((mode & S_ISUID) && !(attr->ia_mode & S_ISUID)) || - (((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) && + (((mode & (S_ISGID | 0010)) == (S_ISGID | 0010)) && !(attr->ia_mode & S_ISGID)))) attr->ia_valid |= ATTR_FORCE; @@ -1610,7 +1603,7 @@ int ll_setattr(struct dentry *de, struct iattr *attr) attr->ia_valid |= ATTR_KILL_SUID; if ((attr->ia_valid & ATTR_MODE) && - ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) && + ((mode & (S_ISGID | 0010)) == (S_ISGID | 0010)) && !(attr->ia_mode & S_ISGID) && !(attr->ia_valid & ATTR_KILL_SGID)) attr->ia_valid |= ATTR_KILL_SGID; @@ -1998,6 +1991,8 @@ void ll_umount_begin(struct super_block *sb) struct ll_sb_info *sbi = ll_s2sbi(sb); struct obd_device *obd; struct obd_ioctl_data *ioc_data; + wait_queue_head_t waitq; + struct l_wait_info lwi; CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb, sb->s_count, atomic_read(&sb->s_active)); @@ -2030,9 +2025,14 @@ void ll_umount_begin(struct super_block *sb) } /* Really, we'd like to wait until there are no requests outstanding, - * and then continue. For now, we just invalidate the requests, - * schedule() and sleep one second if needed, and hope. + * and then continue. For now, we just periodically checking for vfs + * to decrement mnt_cnt and hope to finish it within 10sec. */ + init_waitqueue_head(&waitq); + lwi = LWI_TIMEOUT_INTERVAL(cfs_time_seconds(10), + cfs_time_seconds(1), NULL, NULL); + l_wait_event(waitq, may_umount(sbi->ll_mnt.mnt), &lwi); + schedule(); } |