X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fllite_lib.c;h=3623dbd4d77604f44a23a6fc022cf880ac8ca799;hb=d39b08def6512ee6ae883a0db62cebd808646208;hp=a1a24084fba3eb586e4b5dd834d051d94b299dd1;hpb=fd2b619ca59739b1978fb3f09690526afa9d00dc;p=fs%2Flustre-release.git diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index a1a2408..3623dbd 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -56,7 +56,7 @@ #include #include "llite_internal.h" -cfs_mem_cache_t *ll_file_data_slab; +struct kmem_cache *ll_file_data_slab; CFS_LIST_HEAD(ll_super_blocks); DEFINE_SPINLOCK(ll_sb_lock); @@ -93,7 +93,7 @@ static struct ll_sb_info *ll_init_sbi(void) si_meminfo(&si); pages = si.totalram - si.totalhigh; - if (pages >> (20 - CFS_PAGE_SHIFT) < 512) { + if (pages >> (20 - PAGE_CACHE_SHIFT) < 512) { lru_page_max = pages / 2; } else { lru_page_max = (pages / 4) * 3; @@ -218,7 +218,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH| OBD_CONNECT_EINPROGRESS | OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | - OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS; + OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS | + OBD_CONNECT_MAX_EASIZE; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -309,15 +310,15 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, valid != CLIENT_CONNECT_MDT_REQD) { char *buf; - OBD_ALLOC_WAIT(buf, CFS_PAGE_SIZE); - obd_connect_flags2str(buf, CFS_PAGE_SIZE, + OBD_ALLOC_WAIT(buf, PAGE_CACHE_SIZE); + obd_connect_flags2str(buf, PAGE_CACHE_SIZE, valid ^ CLIENT_CONNECT_MDT_REQD, ","); LCONSOLE_ERROR_MSG(0x170, "Server %s does not support " "feature(s) needed for correct operation " "of this client (%s). Please upgrade " "server or downgrade client.\n", sbi->ll_md_exp->exp_obd->obd_name, buf); - OBD_FREE(buf, CFS_PAGE_SIZE); + OBD_FREE(buf, PAGE_CACHE_SIZE); GOTO(out_md_fid, err = -EPROTO); } @@ -387,13 +388,23 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) sbi->ll_md_brw_size = data->ocd_brw_size; else - sbi->ll_md_brw_size = CFS_PAGE_SIZE; + sbi->ll_md_brw_size = PAGE_CACHE_SIZE; if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) { LCONSOLE_INFO("Layout lock feature supported.\n"); sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; } + if (data->ocd_ibits_known & MDS_INODELOCK_XATTR) { + if (!(data->ocd_connect_flags & OBD_CONNECT_MAX_EASIZE)) { + LCONSOLE_INFO("%s: disabling xattr cache due to " + "unknown maximum xattr size.\n", dt); + } else { + sbi->ll_flags |= LL_SBI_XATTR_CACHE; + sbi->ll_xattr_cache_enabled = 1; + } + } + obd = class_name2obd(dt); if (!obd) { CERROR("DT %s: not setup or attached\n", dt); @@ -529,7 +540,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, LASSERT(fid_is_sane(&sbi->ll_root_fid)); root = ll_iget(sb, cl_fid_build_ino(&sbi->ll_root_fid, - ll_need_32bit_api(sbi)), + sbi->ll_flags & LL_SBI_32BIT_API), &lmd); md_free_lustre_md(sbi->ll_md_exp, &lmd); ptlrpc_req_finished(request); @@ -595,8 +606,10 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, /* s_dev is also used in lt_compare() to compare two fs, but that is * only a node-local comparison. */ uuid = obd_get_uuid(sbi->ll_md_exp); - if (uuid != NULL) - sb->s_dev = get_uuid2int(uuid->uuid, strlen(uuid->uuid)); + if (uuid != NULL) { + sb->s_dev = get_uuid2int(uuid->uuid, strlen(uuid->uuid)); + get_uuid2fsid(uuid->uuid, strlen(uuid->uuid), &sbi->ll_fsid); + } if (data != NULL) OBD_FREE_PTR(data); @@ -945,6 +958,9 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_layout_gen = LL_LAYOUT_GEN_NONE; lli->lli_clob = NULL; + init_rwsem(&lli->lli_xattrs_list_rwsem); + mutex_init(&lli->lli_xattrs_enq_lock); + LASSERT(lli->lli_vfs_inode.i_mode != 0); if (S_ISDIR(lli->lli_vfs_inode.i_mode)) { mutex_init(&lli->lli_readdir_mutex); @@ -971,17 +987,11 @@ void ll_lli_init(struct ll_inode_info *lli) static inline int ll_bdi_register(struct backing_dev_info *bdi) { -#ifdef HAVE_BDI_REGISTER static atomic_t ll_bdi_num = ATOMIC_INIT(0); -#ifdef HAVE_BDI_NAME bdi->name = "lustre"; -#endif return bdi_register(bdi, NULL, "lustre-%d", atomic_inc_return(&ll_bdi_num)); -#else - return 0; -#endif } int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) @@ -1026,9 +1036,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) if (err) GOTO(out_free, err); -#ifdef HAVE_SB_BDI sb->s_bdi = &lsi->lsi_bdi; -#endif /* Generate a string unique to this super, in case some joker tries to mount the same fs at two mount points. @@ -1211,7 +1219,9 @@ void ll_clear_inode(struct inode *inode) LASSERT(lli->lli_opendir_pid == 0); } + spin_lock(&lli->lli_lock); ll_i2info(inode)->lli_flags &= ~LLIF_MDS_SIZE_LOCK; + spin_unlock(&lli->lli_lock); md_null_inode(sbi->ll_md_exp, ll_inode2fid(inode)); LASSERT(!lli->lli_open_fd_write_count); @@ -1231,6 +1241,8 @@ void ll_clear_inode(struct inode *inode) lli->lli_symlink_name = NULL; } + ll_xattr_cache_destroy(inode); + if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { LASSERT(lli->lli_posix_acl == NULL); if (lli->lli_remote_perms) { @@ -1374,50 +1386,6 @@ static int ll_setattr_ost(struct inode *inode, struct iattr *attr) return rc; } -#ifndef HAVE_VFS_INODE_NEWSIZE_OK -/** - * inode_newsize_ok - may this inode be truncated to a given size - * @inode: the inode to be truncated - * @offset: the new size to assign to the inode - * @Returns: 0 on success, -ve errno on failure - * - * inode_newsize_ok will check filesystem limits and ulimits to check that the - * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ - * when necessary. Caller must not proceed with inode size change if failure is - * returned. @inode must be a file (not directory), with appropriate - * permissions to allow truncate (inode_newsize_ok does NOT check these - * conditions). - * - * inode_newsize_ok must be called with i_mutex held. - */ -int inode_newsize_ok(const struct inode *inode, loff_t offset) -{ - if (inode->i_size < offset) { - unsigned long limit; - - limit = rlimit(RLIMIT_FSIZE); - if (limit != RLIM_INFINITY && offset > limit) - goto out_sig; - if (offset > inode->i_sb->s_maxbytes) - goto out_big; - } else { - /* - * truncation of in-use swapfiles is disallowed - it would - * cause subsequent swapout to scribble on the now-freed - * blocks. - */ - if (IS_SWAPFILE(inode)) - return -ETXTBSY; - } - - return 0; -out_sig: - send_sig(SIGXFSZ, current, 0); -out_big: - return -EFBIG; -} -#endif - /* If this inode has objects allocated to it (lsm != NULL), then the OST * object(s) determine the file size and mtime. Otherwise, the MDS will * keep these values until such a time that objects are allocated for it. @@ -1430,20 +1398,24 @@ out_big: * to the OST with the punch RPC, otherwise we do an explicit setattr RPC. * I don't believe it is possible to get e.g. ATTR_MTIME_SET and ATTR_SIZE * at the same time. + * + * In case of HSMimport, we only set attr on MDS. */ -int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) +int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) { struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; struct md_open_data *mod = NULL; + bool file_is_released = false; int rc = 0, rc1 = 0; ENTRY; CDEBUG(D_VFSTRACE, "%s: setattr inode %p/fid:"DFID" from %llu to %llu, " - "valid %x\n", ll_get_fsname(inode->i_sb, NULL, 0), inode, + "valid %x, hsm_import %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), inode, PFID(&lli->lli_fid), i_size_read(inode), attr->ia_size, - attr->ia_valid); + attr->ia_valid, hsm_import); if (attr->ia_valid & ATTR_SIZE) { /* Check new size against VFS/VM file size limit and rlimit */ @@ -1521,10 +1493,40 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) (attr->ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) op_data->op_flags = MF_EPOCH_OPEN; + /* 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 + */ + if (S_ISREG(inode->i_mode)) { + struct lov_stripe_md *lsm; + __u32 gen; + + ll_layout_refresh(inode, &gen); + lsm = ccc_inode_lsm_get(inode); + if (lsm && lsm->lsm_pattern & LOV_PATTERN_F_RELEASED) + file_is_released = true; + ccc_inode_lsm_put(inode, lsm); + } + + /* if not in HSM import mode, clear size attr for released file + * we clear the attribute send to MDT in op_data, not the original + * received from caller in attr which is used later to + * decide return code */ + if (file_is_released && (attr->ia_valid & ATTR_SIZE) && !hsm_import) + op_data->op_attr.ia_valid &= ~ATTR_SIZE; + rc = ll_md_setattr(dentry, op_data, &mod); if (rc) GOTO(out, rc); + /* truncate failed (only when non HSM import), others succeed */ + if (file_is_released) { + if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) + GOTO(out, rc = -ENODATA); + else + GOTO(out, rc = 0); + } + /* RPC to MDT is sent, cancel data modification flag */ if (rc == 0 && (op_data->op_bias & MDS_DATA_MODIFIED)) { spin_lock(&lli->lli_lock); @@ -1538,7 +1540,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) if (attr->ia_valid & (ATTR_SIZE | ATTR_ATIME | ATTR_ATIME_SET | - ATTR_MTIME | ATTR_MTIME_SET)) + ATTR_MTIME | ATTR_MTIME_SET)) { /* For truncate and utimes sending attributes to OSTs, setting * mtime/atime to the past will be performed under PW [0:EOF] * extent lock (new_size:EOF for truncate). It may seem @@ -1546,6 +1548,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) * setting times to past, but it is necessary due to possible * time de-synchronization between MDT inode and OST objects */ rc = ll_setattr_ost(inode, attr); + } EXIT; out: if (op_data) { @@ -1559,7 +1562,7 @@ out: if (!S_ISDIR(inode->i_mode)) { up_write(&lli->lli_trunc_sem); mutex_lock(&inode->i_mutex); - if (attr->ia_valid & ATTR_SIZE) + if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) inode_dio_wait(inode); } @@ -1571,30 +1574,30 @@ out: int ll_setattr(struct dentry *de, struct iattr *attr) { - int mode = de->d_inode->i_mode; - - if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) == - (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) - attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; - - 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)) && - !(attr->ia_mode & S_ISGID)))) - attr->ia_valid |= ATTR_FORCE; - - if ((mode & S_ISUID) && - !(attr->ia_mode & S_ISUID) && - !(attr->ia_valid & ATTR_KILL_SUID)) - attr->ia_valid |= ATTR_KILL_SUID; - - if (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && - !(attr->ia_mode & S_ISGID) && - !(attr->ia_valid & ATTR_KILL_SGID)) - attr->ia_valid |= ATTR_KILL_SGID; - - return ll_setattr_raw(de, attr); + int mode = de->d_inode->i_mode; + + if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) == + (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) + attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + + 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)) && + !(attr->ia_mode & S_ISGID)))) + attr->ia_valid |= ATTR_FORCE; + + if ((mode & S_ISUID) && + !(attr->ia_mode & S_ISUID) && + !(attr->ia_valid & ATTR_KILL_SUID)) + attr->ia_valid |= ATTR_KILL_SUID; + + if (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && + !(attr->ia_mode & S_ISGID) && + !(attr->ia_valid & ATTR_KILL_SGID)) + attr->ia_valid |= ATTR_KILL_SGID; + + return ll_setattr_raw(de, attr, false); } int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, @@ -1681,8 +1684,8 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) sfs->f_blocks = osfs.os_blocks; sfs->f_bfree = osfs.os_bfree; sfs->f_bavail = osfs.os_bavail; - - return 0; + sfs->f_fsid = ll_s2sbi(sb)->ll_fsid; + return 0; } void ll_inode_size_lock(struct inode *inode) @@ -1739,7 +1742,8 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) spin_unlock(&lli->lli_lock); } #endif - inode->i_ino = cl_fid_build_ino(&body->fid1, ll_need_32bit_api(sbi)); + inode->i_ino = cl_fid_build_ino(&body->fid1, + sbi->ll_flags & LL_SBI_32BIT_API); inode->i_generation = cl_fid_build_gen(&body->fid1); if (body->valid & OBD_MD_FLATIME) { @@ -1807,7 +1811,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) * lock on the client and set LLIF_MDS_SIZE_LOCK holding * it. */ mode = ll_take_md_lock(inode, MDS_INODELOCK_UPDATE, - &lockh, LDLM_FL_CBPENDING); + &lockh, LDLM_FL_CBPENDING, + LCK_CR | LCK_CW | + LCK_PR | LCK_PW); if (mode) { if (lli->lli_flags & (LLIF_DONE_WRITING | LLIF_EPOCH_PENDING | @@ -1820,7 +1826,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) /* Use old size assignment to avoid * deadlock bz14138 & bz14326 */ i_size_write(inode, body->size); + spin_lock(&lli->lli_lock); lli->lli_flags |= LLIF_MDS_SIZE_LOCK; + spin_unlock(&lli->lli_lock); } ldlm_lock_decref(&lockh, mode); } @@ -1845,6 +1853,11 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT(md->oss_capa); ll_add_capa(inode, md->oss_capa); } + + if (body->valid & OBD_MD_TSTATE) { + if (body->t_state & MS_RESTORE) + lli->lli_flags |= LLIF_FILE_RESTORING; + } } void ll_read_inode2(struct inode *inode, void *opaque) @@ -1990,8 +2003,10 @@ int ll_iocontrol(struct inode *inode, struct file *file, inode->i_flags = ll_ext_to_inode_flags(flags); lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) + if (!lsm_has_objects(lsm)) { + ccc_inode_lsm_put(inode, lsm); RETURN(0); + } OBDO_ALLOC(oinfo.oi_oa); if (!oinfo.oi_oa) { @@ -2038,26 +2053,13 @@ int ll_flush_ctx(struct inode *inode) } /* umount -f client means force down, don't save state */ -#ifdef HAVE_UMOUNTBEGIN_VFSMOUNT -void ll_umount_begin(struct vfsmount *vfsmnt, int flags) -{ - struct super_block *sb = vfsmnt->mnt_sb; -#else void ll_umount_begin(struct super_block *sb) { -#endif struct ll_sb_info *sbi = ll_s2sbi(sb); struct obd_device *obd; struct obd_ioctl_data *ioc_data; ENTRY; -#ifdef HAVE_UMOUNTBEGIN_VFSMOUNT - if (!(flags & MNT_FORCE)) { - EXIT; - return; - } -#endif - CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb, sb->s_count, atomic_read(&sb->s_active)); @@ -2095,17 +2097,6 @@ void ll_umount_begin(struct super_block *sb) * schedule() and sleep one second if needed, and hope. */ cfs_schedule(); -#ifdef HAVE_UMOUNTBEGIN_VFSMOUNT - if (atomic_read(&vfsmnt->mnt_count) > 2) { - cfs_schedule_timeout_and_set_state(CFS_TASK_INTERRUPTIBLE, - cfs_time_seconds(1)); - if (atomic_read(&vfsmnt->mnt_count) > 2) - LCONSOLE_WARN("Mount still busy with %d refs! You " - "may try to umount it a bit later\n", - atomic_read(&vfsmnt->mnt_count)); - } -#endif - EXIT; } @@ -2168,7 +2159,7 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, LASSERT(fid_is_sane(&md.body->fid1)); *inode = ll_iget(sb, cl_fid_build_ino(&md.body->fid1, - ll_need_32bit_api(sbi)), + sbi->ll_flags & LL_SBI_32BIT_API), &md); if (*inode == NULL || IS_ERR(*inode)) { #ifdef CONFIG_FS_POSIX_ACL @@ -2423,11 +2414,11 @@ int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg) if (!obd) RETURN(-ENOENT); - if (cfs_copy_to_user((void *)arg, obd->obd_name, - strlen(obd->obd_name) + 1)) - RETURN(-EFAULT); + if (copy_to_user((void *)arg, obd->obd_name, + strlen(obd->obd_name) + 1)) + RETURN(-EFAULT); - RETURN(0); + RETURN(0); } /** @@ -2482,7 +2473,7 @@ static char* ll_d_path(struct dentry *dentry, char *buf, int bufsize) return path; } -void ll_dirty_page_discard_warn(cfs_page_t *page, int ioret) +void ll_dirty_page_discard_warn(struct page *page, int ioret) { char *buf, *path = NULL; struct dentry *dentry = NULL;