*/
/*
* This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
*
* lustre/llite/llite_lib.c
*
#include <linux/user_namespace.h>
#include <linux/delay.h>
#include <linux/uidgid.h>
-#include <linux/security.h>
+#include <linux/fs_struct.h>
#ifndef HAVE_CPUS_READ_LOCK
#include <libcfs/linux/linux-cpu.h>
if (sbi->ll_cache == NULL)
GOTO(out_destroy_ra, rc = -ENOMEM);
- sbi->ll_ra_info.ra_max_pages_per_file = min(pages / 32,
- SBI_DEFAULT_READ_AHEAD_MAX);
+ /* initialize foreign symlink prefix path */
+ OBD_ALLOC(sbi->ll_foreign_symlink_prefix, sizeof("/mnt/"));
+ if (sbi->ll_foreign_symlink_prefix == NULL)
+ GOTO(out_destroy_ra, rc = -ENOMEM);
+ memcpy(sbi->ll_foreign_symlink_prefix, "/mnt/", sizeof("/mnt/"));
+ sbi->ll_foreign_symlink_prefix_size = sizeof("/mnt/");
+
+ /* initialize foreign symlink upcall path, none by default */
+ OBD_ALLOC(sbi->ll_foreign_symlink_upcall, sizeof("none"));
+ if (sbi->ll_foreign_symlink_upcall == NULL)
+ GOTO(out_destroy_ra, rc = -ENOMEM);
+ memcpy(sbi->ll_foreign_symlink_upcall, "none", sizeof("none"));
+ sbi->ll_foreign_symlink_upcall_items = NULL;
+ sbi->ll_foreign_symlink_upcall_nb_items = 0;
+ init_rwsem(&sbi->ll_foreign_symlink_sem);
+ /* foreign symlink support (LL_SBI_FOREIGN_SYMLINK in ll_flags)
+ * not enabled by default
+ */
+
+ sbi->ll_ra_info.ra_max_pages =
+ min(pages / 32, SBI_DEFAULT_READ_AHEAD_MAX);
+ sbi->ll_ra_info.ra_max_pages_per_file =
+ min(sbi->ll_ra_info.ra_max_pages / 4,
+ SBI_DEFAULT_READ_AHEAD_PER_FILE_MAX);
sbi->ll_ra_info.ra_async_pages_per_file_threshold =
sbi->ll_ra_info.ra_max_pages_per_file;
- sbi->ll_ra_info.ra_max_pages = sbi->ll_ra_info.ra_max_pages_per_file;
+ sbi->ll_ra_info.ra_range_pages = SBI_DEFAULT_RA_RANGE_PAGES;
sbi->ll_ra_info.ra_max_read_ahead_whole_pages = -1;
atomic_set(&sbi->ll_ra_info.ra_async_inflight, 0);
sbi->ll_flags |= LL_SBI_AGL_ENABLED;
sbi->ll_flags |= LL_SBI_FAST_READ;
sbi->ll_flags |= LL_SBI_TINY_WRITE;
+ sbi->ll_flags |= LL_SBI_PARALLEL_DIO;
ll_sbi_set_encrypt(sbi, true);
/* root squash */
/* Per-filesystem file heat */
sbi->ll_heat_decay_weight = SBI_DEFAULT_HEAT_DECAY_WEIGHT;
sbi->ll_heat_period_second = SBI_DEFAULT_HEAT_PERIOD_SECOND;
+
+ /* Per-fs open heat level before requesting open lock */
+ sbi->ll_oc_thrsh_count = SBI_DEFAULT_OPENCACHE_THRESHOLD_COUNT;
+ sbi->ll_oc_max_ms = SBI_DEFAULT_OPENCACHE_THRESHOLD_MAX_MS;
+ sbi->ll_oc_thrsh_ms = SBI_DEFAULT_OPENCACHE_THRESHOLD_MS;
RETURN(sbi);
out_destroy_ra:
+ if (sbi->ll_foreign_symlink_prefix)
+ OBD_FREE(sbi->ll_foreign_symlink_prefix, sizeof("/mnt/"));
+ if (sbi->ll_cache) {
+ cl_cache_decref(sbi->ll_cache);
+ sbi->ll_cache = NULL;
+ }
destroy_workqueue(sbi->ll_ra_info.ll_readahead_wq);
out_pcc:
pcc_super_fini(&sbi->ll_pcc_super);
cl_cache_decref(sbi->ll_cache);
sbi->ll_cache = NULL;
}
+ if (sbi->ll_foreign_symlink_prefix) {
+ OBD_FREE(sbi->ll_foreign_symlink_prefix,
+ sbi->ll_foreign_symlink_prefix_size);
+ sbi->ll_foreign_symlink_prefix = NULL;
+ }
+ if (sbi->ll_foreign_symlink_upcall) {
+ OBD_FREE(sbi->ll_foreign_symlink_upcall,
+ strlen(sbi->ll_foreign_symlink_upcall) +
+ 1);
+ sbi->ll_foreign_symlink_upcall = NULL;
+ }
+ if (sbi->ll_foreign_symlink_upcall_items) {
+ int i;
+ int nb_items = sbi->ll_foreign_symlink_upcall_nb_items;
+ struct ll_foreign_symlink_upcall_item *items =
+ sbi->ll_foreign_symlink_upcall_items;
+
+ for (i = 0 ; i < nb_items; i++)
+ if (items[i].type == STRING_TYPE)
+ OBD_FREE(items[i].string,
+ items[i].size);
+
+ OBD_FREE_LARGE(items, nb_items *
+ sizeof(struct ll_foreign_symlink_upcall_item));
+ sbi->ll_foreign_symlink_upcall_items = NULL;
+ }
pcc_super_fini(&sbi->ll_pcc_super);
OBD_FREE(sbi, sizeof(*sbi));
}
OBD_CONNECT2_LSOM |
OBD_CONNECT2_ASYNC_DISCARD |
OBD_CONNECT2_PCC |
- OBD_CONNECT2_CRUSH;
+ OBD_CONNECT2_CRUSH | OBD_CONNECT2_LSEEK |
+ OBD_CONNECT2_GETATTR_PFID |
+ OBD_CONNECT2_DOM_LVB |
+ OBD_CONNECT2_REP_MBITS |
+ OBD_CONNECT2_ATOMIC_OPEN_LOCK;
#ifdef HAVE_LRU_RESIZE_SUPPORT
if (sbi->ll_flags & LL_SBI_LRU_RESIZE)
data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE;
#endif
-#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
- data->ocd_connect_flags |= OBD_CONNECT_ACL | OBD_CONNECT_UMASK |
- OBD_CONNECT_LARGE_ACL;
-#endif
+ data->ocd_connect_flags |= OBD_CONNECT_ACL_FLAGS;
data->ocd_cksum_types = obd_cksum_types_supported_client();
*/
sb->s_flags |= SB_NOSEC;
#endif
-
- if (sbi->ll_flags & LL_SBI_FLOCK)
- sbi->ll_fop = &ll_file_operations_flock;
- else if (sbi->ll_flags & LL_SBI_LOCALFLOCK)
- sbi->ll_fop = &ll_file_operations;
- else
- sbi->ll_fop = &ll_file_operations_noflock;
+ sbi->ll_fop = ll_select_file_operations(sbi);
/* always ping even if server suppress_pings */
if (sbi->ll_flags & LL_SBI_ALWAYS_PING)
OBD_CONNECT_BULK_MBITS | OBD_CONNECT_SHORTIO |
OBD_CONNECT_FLAGS2 | OBD_CONNECT_GRANT_SHRINK;
data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD |
- OBD_CONNECT2_INC_XID;
+ OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK |
+ OBD_CONNECT2_REP_MBITS;
if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM))
data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM;
GOTO(out_lock_cn_cb, err);
}
- err = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp,
- sbi->ll_md_exp, &lmd);
+ err = md_get_lustre_md(sbi->ll_md_exp, &request->rq_pill,
+ sbi->ll_dt_exp, sbi->ll_md_exp, &lmd);
if (err) {
CERROR("failed to understand root inode md: rc = %d\n", err);
ptlrpc_req_finished(request);
ptlrpc_req_finished(request);
if (IS_ERR(root)) {
-#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
- if (lmd.posix_acl) {
- posix_acl_release(lmd.posix_acl);
- lmd.posix_acl = NULL;
- }
-#endif
+ lmd_clear_acl(&lmd);
err = IS_ERR(root) ? PTR_ERR(root) : -EBADF;
root = NULL;
CERROR("%s: bad ll_iget() for root: rc = %d\n",
RETURN(err);
out_root:
- if (root)
- iput(root);
+ iput(root);
out_lock_cn_cb:
obd_fid_fini(sbi->ll_dt_exp->exp_obd);
out_dt:
#endif
goto next;
}
+ tmp = ll_set_opt("foreign_symlink", s1, LL_SBI_FOREIGN_SYMLINK);
+ if (tmp) {
+ int prefix_pos = sizeof("foreign_symlink=") - 1;
+ int equal_pos = sizeof("foreign_symlink=") - 2;
+
+ /* non-default prefix provided ? */
+ if (strlen(s1) >= sizeof("foreign_symlink=") &&
+ *(s1 + equal_pos) == '=') {
+ char *old = sbi->ll_foreign_symlink_prefix;
+ size_t old_len =
+ sbi->ll_foreign_symlink_prefix_size;
+
+ /* path must be absolute */
+ if (*(s1 + sizeof("foreign_symlink=")
+ - 1) != '/') {
+ LCONSOLE_ERROR_MSG(0x152,
+ "foreign prefix '%s' must be an absolute path\n",
+ s1 + prefix_pos);
+ RETURN(-EINVAL);
+ }
+ /* last option ? */
+ s2 = strchrnul(s1 + prefix_pos, ',');
+
+ if (sbi->ll_foreign_symlink_prefix) {
+ sbi->ll_foreign_symlink_prefix = NULL;
+ sbi->ll_foreign_symlink_prefix_size = 0;
+ }
+ /* alloc for path length and '\0' */
+ OBD_ALLOC(sbi->ll_foreign_symlink_prefix,
+ s2 - (s1 + prefix_pos) + 1);
+ if (!sbi->ll_foreign_symlink_prefix) {
+ /* restore previous */
+ sbi->ll_foreign_symlink_prefix = old;
+ sbi->ll_foreign_symlink_prefix_size =
+ old_len;
+ RETURN(-ENOMEM);
+ }
+ if (old)
+ OBD_FREE(old, old_len);
+ strncpy(sbi->ll_foreign_symlink_prefix,
+ s1 + prefix_pos,
+ s2 - (s1 + prefix_pos));
+ sbi->ll_foreign_symlink_prefix_size =
+ s2 - (s1 + prefix_pos) + 1;
+ } else {
+ LCONSOLE_ERROR_MSG(0x152,
+ "invalid %s option\n", s1);
+ }
+ /* enable foreign symlink support */
+ *flags |= tmp;
+ goto next;
+ }
LCONSOLE_ERROR_MSG(0x152, "Unknown option '%s', won't mount.\n",
s1);
RETURN(-EINVAL);
CDEBUG(D_VFSTRACE, "VFS Op: cfg_instance %s-%016lx (sb %p)\n",
profilenm, cfg_instance, sb);
+ OBD_RACE(OBD_FAIL_LLITE_RACE_MOUNT);
+
OBD_ALLOC_PTR(cfg);
if (cfg == NULL)
GOTO(out_free_cfg, err = -ENOMEM);
cl_env_cache_purge(~0);
- module_put(THIS_MODULE);
-
EXIT;
} /* client_put_super */
const struct lu_fid *fid,
struct lustre_md *md)
{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct mdt_body *body = md->body;
- struct inode *inode;
- ino_t ino;
+ struct ll_sb_info *sbi = ll_s2sbi(sb);
+ struct ll_inode_info *lli;
+ struct mdt_body *body = md->body;
+ struct inode *inode;
+ ino_t ino;
+
ENTRY;
+ LASSERT(md->lmv);
ino = cl_fid_build_ino(fid, sbi->ll_flags & LL_SBI_32BIT_API);
inode = iget_locked(sb, ino);
if (inode == NULL) {
RETURN(ERR_PTR(-ENOENT));
}
+ lli = ll_i2info(inode);
if (inode->i_state & I_NEW) {
- struct ll_inode_info *lli = ll_i2info(inode);
- struct lmv_stripe_md *lsm = md->lmv;
-
inode->i_mode = (inode->i_mode & ~S_IFMT) |
(body->mbo_mode & S_IFMT);
LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode "DFID"\n",
lli->lli_fid = *fid;
ll_lli_init(lli);
- LASSERT(lsm != NULL);
/* master object FID */
lli->lli_pfid = body->mbo_fid1;
CDEBUG(D_INODE, "lli %p slave "DFID" master "DFID"\n",
lli, PFID(fid), PFID(&lli->lli_pfid));
unlock_new_inode(inode);
+ } else {
+ /* in directory restripe/auto-split, a directory will be
+ * transformed to a stripe if it's plain, set its pfid here,
+ * otherwise ll_lock_cancel_bits() can't find the master inode.
+ */
+ lli->lli_pfid = body->mbo_fid1;
}
RETURN(inode);
}
up_write(&lli->lli_lsm_sem);
}
- } else if (lli->lli_default_lsm_md) {
- /* update default lsm if it changes */
+ return;
+ }
+
+ if (lli->lli_default_lsm_md) {
+ /* do nonthing if default lsm isn't changed */
down_read(&lli->lli_lsm_sem);
if (lli->lli_default_lsm_md &&
- !lsm_md_eq(lli->lli_default_lsm_md, md->default_lmv)) {
- up_read(&lli->lli_lsm_sem);
- down_write(&lli->lli_lsm_sem);
- if (lli->lli_default_lsm_md)
- lmv_free_memmd(lli->lli_default_lsm_md);
- lli->lli_default_lsm_md = md->default_lmv;
- lsm_md_dump(D_INODE, md->default_lmv);
- md->default_lmv = NULL;
- up_write(&lli->lli_lsm_sem);
- } else {
+ lsm_md_eq(lli->lli_default_lsm_md, md->default_lmv)) {
up_read(&lli->lli_lsm_sem);
+ return;
}
- } else {
- /* init default lsm */
- down_write(&lli->lli_lsm_sem);
- lli->lli_default_lsm_md = md->default_lmv;
- lsm_md_dump(D_INODE, md->default_lmv);
- md->default_lmv = NULL;
- up_write(&lli->lli_lsm_sem);
+ up_read(&lli->lli_lsm_sem);
}
+
+ down_write(&lli->lli_lsm_sem);
+ if (lli->lli_default_lsm_md)
+ lmv_free_memmd(lli->lli_default_lsm_md);
+ lli->lli_default_lsm_md = md->default_lmv;
+ lsm_md_dump(D_INODE, md->default_lmv);
+ md->default_lmv = NULL;
+ up_write(&lli->lli_lsm_sem);
}
static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
if (md->default_lmv)
ll_update_default_lsm_md(inode, md);
+ /* after dir migration/restripe, a stripe may be turned into a
+ * directory, in this case, zero out its lli_pfid.
+ */
+ if (unlikely(fid_is_norm(&lli->lli_pfid)))
+ fid_zero(&lli->lli_pfid);
+
/*
* no striped information from request, lustre_md from req does not
* include stripeEA, see ll_md_setattr()
ll_xattr_cache_destroy(inode);
-#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
forget_all_cached_acls(inode);
- if (lli->lli_posix_acl) {
- posix_acl_release(lli->lli_posix_acl);
- lli->lli_posix_acl = NULL;
- }
-#endif
+ lli_clear_acl(lli);
lli->lli_inode_magic = LLI_INODE_DEAD;
if (S_ISDIR(inode->i_mode))
RETURN(rc);
}
- rc = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp,
- sbi->ll_md_exp, &md);
+ rc = md_get_lustre_md(sbi->ll_md_exp, &request->rq_pill, sbi->ll_dt_exp,
+ sbi->ll_md_exp, &md);
if (rc) {
ptlrpc_req_finished(request);
RETURN(rc);
anchor = &vvp_env_info(env)->vti_anchor;
cl_sync_io_init(anchor, 1);
clpage->cp_sync_io = anchor;
- cl_2queue_add(queue, clpage);
+ cl_2queue_add(queue, clpage, true);
rc = cl_io_submit_rw(env, io, CRT_WRITE, queue);
if (rc)
GOTO(queuefini1, rc);
/* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */
if (attr->ia_valid & TIMES_SET_FLAGS) {
if ((!uid_eq(current_fsuid(), inode->i_uid)) &&
- !cfs_capable(CFS_CAP_FOWNER))
+ !capable(CAP_FOWNER))
RETURN(-EPERM);
}
*/
xvalid |= OP_XVALID_OWNEROVERRIDE;
op_data->op_bias |= MDS_DATA_MODIFIED;
- ll_file_clear_flag(lli, LLIF_DATA_MODIFIED);
+ clear_bit(LLIF_DATA_MODIFIED, &lli->lli_flags);
}
if (attr->ia_valid & ATTR_FILE) {
* it is necessary due to possible time
* de-synchronization between MDT inode and OST objects
*/
- if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode) &&
- attr->ia_valid & ATTR_SIZE) {
+ if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) {
xvalid |= OP_XVALID_FLAGS;
flags = LUSTRE_ENCRYPT_FL;
- if (attr->ia_size & ~PAGE_MASK) {
+ /* Call to ll_io_zero_page is not necessary if
+ * truncating on PAGE_SIZE boundary, because
+ * whole pages will be wiped.
+ * In case of Direct IO, all we need is to set
+ * new size.
+ */
+ if (attr->ia_valid & ATTR_SIZE &&
+ attr->ia_size & ~PAGE_MASK &&
+ !(attr->ia_valid & ATTR_FILE &&
+ attr->ia_file->f_flags & O_DIRECT)) {
pgoff_t offset =
attr->ia_size & (PAGE_SIZE - 1);
* LLIF_DATA_MODIFIED is not set(see vvp_io_setattr_fini()).
* This way we can save an RPC for common open + trunc
* operation. */
- if (ll_file_test_and_clear_flag(lli, LLIF_DATA_MODIFIED)) {
+ if (test_and_clear_bit(LLIF_DATA_MODIFIED, &lli->lli_flags)) {
struct hsm_state_set hss = {
.hss_valid = HSS_SETMASK,
.hss_setmask = HS_DIRTY,
RETURN(rc);
}
+static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs)
+{
+ struct if_quotactl qctl = {
+ .qc_cmd = LUSTRE_Q_GETQUOTA,
+ .qc_type = PRJQUOTA,
+ .qc_valid = QC_GENERAL,
+ };
+ u64 limit, curblock;
+ int ret;
+
+ qctl.qc_id = ll_i2info(inode)->lli_projid;
+ ret = quotactl_ioctl(ll_i2sbi(inode), &qctl);
+ if (ret) {
+ /* ignore errors if project ID does not have
+ * a quota limit or feature unsupported.
+ */
+ if (ret == -ESRCH || ret == -EOPNOTSUPP)
+ ret = 0;
+ return ret;
+ }
+
+ limit = ((qctl.qc_dqblk.dqb_bsoftlimit ?
+ qctl.qc_dqblk.dqb_bsoftlimit :
+ qctl.qc_dqblk.dqb_bhardlimit) * 1024) / sfs->f_bsize;
+ if (limit && sfs->f_blocks > limit) {
+ curblock = (qctl.qc_dqblk.dqb_curspace +
+ sfs->f_bsize - 1) / sfs->f_bsize;
+ sfs->f_blocks = limit;
+ sfs->f_bfree = sfs->f_bavail =
+ (sfs->f_blocks > curblock) ?
+ (sfs->f_blocks - curblock) : 0;
+ }
+
+ limit = qctl.qc_dqblk.dqb_isoftlimit ?
+ qctl.qc_dqblk.dqb_isoftlimit :
+ qctl.qc_dqblk.dqb_ihardlimit;
+ if (limit && sfs->f_files > limit) {
+ sfs->f_files = limit;
+ sfs->f_ffree = (sfs->f_files >
+ qctl.qc_dqblk.dqb_curinodes) ?
+ (sfs->f_files - qctl.qc_dqblk.dqb_curinodes) : 0;
+ }
+
+ return 0;
+}
+
int ll_statfs(struct dentry *de, struct kstatfs *sfs)
{
struct super_block *sb = de->d_sb;
sfs->f_bavail = osfs.os_bavail;
sfs->f_fsid.val[0] = (__u32)fsid;
sfs->f_fsid.val[1] = (__u32)(fsid >> 32);
+ if (ll_i2info(de->d_inode)->lli_projid)
+ return ll_statfs_project(de->d_inode, sfs);
ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_STATFS,
ktime_us_delta(ktime_get(), kstart));
mutex_unlock(&lli->lli_size_mutex);
}
-void ll_update_inode_flags(struct inode *inode, int ext_flags)
+void ll_update_inode_flags(struct inode *inode, unsigned int ext_flags)
{
/* do not clear encryption flag */
ext_flags |= ll_inode_to_ext_flags(inode->i_flags) & LUSTRE_ENCRYPT_FL;
inode->i_flags = ll_ext_to_inode_flags(ext_flags);
if (ext_flags & LUSTRE_PROJINHERIT_FL)
- ll_file_set_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT);
+ set_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags);
else
- ll_file_clear_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT);
+ clear_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags);
}
int ll_update_inode(struct inode *inode, struct lustre_md *md)
return rc;
}
-#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
- if (body->mbo_valid & OBD_MD_FLACL) {
- spin_lock(&lli->lli_lock);
- if (lli->lli_posix_acl)
- posix_acl_release(lli->lli_posix_acl);
- lli->lli_posix_acl = md->posix_acl;
- spin_unlock(&lli->lli_lock);
- }
-#endif
+ if (body->mbo_valid & OBD_MD_FLACL)
+ lli_replace_acl(lli, md);
+
inode->i_ino = cl_fid_build_ino(&body->mbo_fid1,
sbi->ll_flags & LL_SBI_32BIT_API);
inode->i_generation = cl_fid_build_gen(&body->mbo_fid1);
* glimpsing updated attrs
*/
if (body->mbo_t_state & MS_RESTORE)
- ll_file_set_flag(lli, LLIF_FILE_RESTORING);
+ set_bit(LLIF_FILE_RESTORING, &lli->lli_flags);
else
- ll_file_clear_flag(lli, LLIF_FILE_RESTORING);
+ clear_bit(LLIF_FILE_RESTORING, &lli->lli_flags);
}
return 0;
}
+void ll_truncate_inode_pages_final(struct inode *inode)
+{
+ struct address_space *mapping = &inode->i_data;
+ unsigned long nrpages;
+ unsigned long flags;
+
+ truncate_inode_pages_final(mapping);
+
+ /* Workaround for LU-118: Note nrpages may not be totally updated when
+ * truncate_inode_pages() returns, as there can be a page in the process
+ * of deletion (inside __delete_from_page_cache()) in the specified
+ * range. Thus mapping->nrpages can be non-zero when this function
+ * returns even after truncation of the whole mapping. Only do this if
+ * npages isn't already zero.
+ */
+ nrpages = mapping->nrpages;
+ if (nrpages) {
+ ll_xa_lock_irqsave(&mapping->i_pages, flags);
+ nrpages = mapping->nrpages;
+ ll_xa_unlock_irqrestore(&mapping->i_pages, flags);
+ } /* Workaround end */
+
+ LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, "
+ "see https://jira.whamcloud.com/browse/LU-118\n",
+ ll_i2sbi(inode)->ll_fsname,
+ PFID(ll_inode2fid(inode)), inode, nrpages);
+}
+
int ll_read_inode2(struct inode *inode, void *opaque)
{
struct lustre_md *md = opaque;
void ll_delete_inode(struct inode *inode)
{
struct ll_inode_info *lli = ll_i2info(inode);
- struct address_space *mapping = &inode->i_data;
- unsigned long nrpages;
- unsigned long flags;
-
ENTRY;
if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL) {
cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, inode->i_nlink ?
CL_FSYNC_LOCAL : CL_FSYNC_DISCARD, 1);
}
- truncate_inode_pages_final(mapping);
-
- /* Workaround for LU-118: Note nrpages may not be totally updated when
- * truncate_inode_pages() returns, as there can be a page in the process
- * of deletion (inside __delete_from_page_cache()) in the specified
- * range. Thus mapping->nrpages can be non-zero when this function
- * returns even after truncation of the whole mapping. Only do this if
- * npages isn't already zero.
- */
- nrpages = mapping->nrpages;
- if (nrpages) {
- ll_xa_lock_irqsave(&mapping->i_pages, flags);
- nrpages = mapping->nrpages;
- ll_xa_unlock_irqrestore(&mapping->i_pages, flags);
- } /* Workaround end */
-
- LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, "
- "see https://jira.whamcloud.com/browse/LU-118\n",
- ll_i2sbi(inode)->ll_fsname,
- PFID(ll_inode2fid(inode)), inode, nrpages);
+ ll_truncate_inode_pages_final(inode);
ll_clear_inode(inode);
clear_inode(inode);
if (flags & LUSTRE_PROJINHERIT_FL)
fa.fsx_xflags = FS_XFLAG_PROJINHERIT;
- rc = ll_ioctl_check_project(inode, &fa);
+ rc = ll_ioctl_check_project(inode, fa.fsx_xflags,
+ fa.fsx_projid);
if (rc)
RETURN(rc);
* \param[in] sb super block for this file-system
* \param[in] open_req pointer to the original open request
*/
-void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req)
+void ll_open_cleanup(struct super_block *sb, struct req_capsule *pill)
{
struct mdt_body *body;
struct md_op_data *op_data;
struct obd_export *exp = ll_s2sbi(sb)->ll_md_exp;
ENTRY;
- body = req_capsule_server_get(&open_req->rq_pill, &RMF_MDT_BODY);
+ body = req_capsule_server_get(pill, &RMF_MDT_BODY);
OBD_ALLOC_PTR(op_data);
if (op_data == NULL) {
CWARN("%s: cannot allocate op_data to release open handle for "
EXIT;
}
-int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
+int ll_prep_inode(struct inode **inode, struct req_capsule *pill,
struct super_block *sb, struct lookup_intent *it)
{
struct ll_sb_info *sbi = NULL;
LASSERT(*inode || sb);
sbi = sb ? ll_s2sbi(sb) : ll_i2sbi(*inode);
- rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp,
+ rc = md_get_lustre_md(sbi->ll_md_exp, pill, sbi->ll_dt_exp,
sbi->ll_md_exp, &md);
if (rc != 0)
GOTO(out, rc);
sbi->ll_flags & LL_SBI_32BIT_API),
&md);
if (IS_ERR(*inode)) {
-#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
- if (md.posix_acl) {
- posix_acl_release(md.posix_acl);
- md.posix_acl = NULL;
- }
-#endif
+ lmd_clear_acl(&md);
rc = IS_ERR(*inode) ? PTR_ERR(*inode) : -ENOMEM;
*inode = NULL;
CERROR("new_inode -fatal: rc %d\n", rc);
if (default_lmv_deleted)
ll_update_default_lsm_md(*inode, &md);
+ /* we may want to apply some policy for foreign file/dir */
+ if (ll_sbi_has_foreign_symlink(sbi)) {
+ rc = ll_manage_foreign(*inode, &md);
+ if (rc < 0)
+ GOTO(out, rc);
+ }
+
GOTO(out, rc = 0);
out:
if (rc != 0 && it != NULL && it->it_op & IT_OPEN) {
ll_intent_drop_lock(it);
- ll_open_cleanup(sb != NULL ? sb : (*inode)->i_sb, req);
+ ll_open_cleanup(sb != NULL ? sb : (*inode)->i_sb, pill);
}
return rc;
int ll_obd_statfs(struct inode *inode, void __user *arg)
{
- struct ll_sb_info *sbi = NULL;
- struct obd_export *exp;
- char *buf = NULL;
- struct obd_ioctl_data *data = NULL;
- __u32 type;
- int len = 0, rc;
-
- if (!inode || !(sbi = ll_i2sbi(inode)))
- GOTO(out_statfs, rc = -EINVAL);
-
- rc = obd_ioctl_getdata(&buf, &len, arg);
- if (rc)
- GOTO(out_statfs, rc);
-
- data = (void*)buf;
- if (!data->ioc_inlbuf1 || !data->ioc_inlbuf2 ||
- !data->ioc_pbuf1 || !data->ioc_pbuf2)
- GOTO(out_statfs, rc = -EINVAL);
-
- if (data->ioc_inllen1 != sizeof(__u32) ||
- data->ioc_inllen2 != sizeof(__u32) ||
- data->ioc_plen1 != sizeof(struct obd_statfs) ||
- data->ioc_plen2 != sizeof(struct obd_uuid))
- GOTO(out_statfs, rc = -EINVAL);
-
- memcpy(&type, data->ioc_inlbuf1, sizeof(__u32));
+ struct ll_sb_info *sbi = NULL;
+ struct obd_export *exp;
+ struct obd_ioctl_data *data = NULL;
+ __u32 type;
+ int len = 0, rc;
+
+ if (inode)
+ sbi = ll_i2sbi(inode);
+ if (!sbi)
+ GOTO(out_statfs, rc = -EINVAL);
+
+ rc = obd_ioctl_getdata(&data, &len, arg);
+ if (rc)
+ GOTO(out_statfs, rc);
+
+ if (!data->ioc_inlbuf1 || !data->ioc_inlbuf2 ||
+ !data->ioc_pbuf1 || !data->ioc_pbuf2)
+ GOTO(out_statfs, rc = -EINVAL);
+
+ if (data->ioc_inllen1 != sizeof(__u32) ||
+ data->ioc_inllen2 != sizeof(__u32) ||
+ data->ioc_plen1 != sizeof(struct obd_statfs) ||
+ data->ioc_plen2 != sizeof(struct obd_uuid))
+ GOTO(out_statfs, rc = -EINVAL);
+
+ memcpy(&type, data->ioc_inlbuf1, sizeof(__u32));
if (type & LL_STATFS_LMV)
- exp = sbi->ll_md_exp;
+ exp = sbi->ll_md_exp;
else if (type & LL_STATFS_LOV)
- exp = sbi->ll_dt_exp;
- else
- GOTO(out_statfs, rc = -ENODEV);
+ exp = sbi->ll_dt_exp;
+ else
+ GOTO(out_statfs, rc = -ENODEV);
- rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, NULL);
- if (rc)
- GOTO(out_statfs, rc);
+ rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, data, NULL);
+ if (rc)
+ GOTO(out_statfs, rc);
out_statfs:
- OBD_FREE_LARGE(buf, len);
+ OBD_FREE_LARGE(data, len);
return rc;
}
void ll_unlock_md_op_lsm(struct md_op_data *op_data)
{
if (op_data->op_mea2_sem) {
- up_read(op_data->op_mea2_sem);
+ up_read_non_owner(op_data->op_mea2_sem);
op_data->op_mea2_sem = NULL;
}
if (op_data->op_mea1_sem) {
- up_read(op_data->op_mea1_sem);
+ up_read_non_owner(op_data->op_mea1_sem);
op_data->op_mea1_sem = NULL;
}
}
if (namelen > ll_i2sbi(i1)->ll_namelen)
return ERR_PTR(-ENAMETOOLONG);
- if (!lu_name_is_valid_2(name, namelen))
+ /* "/" is not valid name, but it's allowed */
+ if (!lu_name_is_valid_2(name, namelen) &&
+ strncmp("/", name, namelen) != 0)
return ERR_PTR(-EINVAL);
}
op_data->op_code = opc;
if (S_ISDIR(i1->i_mode)) {
- down_read(&ll_i2info(i1)->lli_lsm_sem);
+ down_read_non_owner(&ll_i2info(i1)->lli_lsm_sem);
op_data->op_mea1_sem = &ll_i2info(i1)->lli_lsm_sem;
op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md;
op_data->op_default_mea1 = ll_i2info(i1)->lli_default_lsm_md;
op_data->op_fid2 = *ll_inode2fid(i2);
if (S_ISDIR(i2->i_mode)) {
if (i2 != i1) {
- down_read(&ll_i2info(i2)->lli_lsm_sem);
+ /* i2 is typically a child of i1, and MUST be
+ * further from the root to avoid deadlocks.
+ */
+ down_read_non_owner(&ll_i2info(i2)->lli_lsm_sem);
op_data->op_mea2_sem =
&ll_i2info(i2)->lli_lsm_sem;
}
void ll_finish_md_op_data(struct md_op_data *op_data)
{
ll_unlock_md_op_lsm(op_data);
- security_release_secctx(op_data->op_file_secctx,
- op_data->op_file_secctx_size);
- OBD_FREE_PTR(op_data);
+ ll_security_release_secctx(op_data->op_file_secctx,
+ op_data->op_file_secctx_size);
+ llcrypt_free_ctx(op_data->op_file_encctx, op_data->op_file_encctx_size);
+ OBD_FREE_PTR(op_data);
}
int ll_show_options(struct seq_file *seq, struct dentry *dentry)
else
seq_puts(seq, ",noencrypt");
+ if (sbi->ll_flags & LL_SBI_FOREIGN_SYMLINK) {
+ seq_puts(seq, ",foreign_symlink=");
+ seq_puts(seq, sbi->ll_foreign_symlink_prefix);
+ }
+
RETURN(0);
}
struct obd_device *obd;
ENTRY;
- if (cmd == OBD_IOC_GETDTNAME)
+ if (cmd == OBD_IOC_GETNAME_OLD || cmd == OBD_IOC_GETDTNAME)
obd = class_exp2obd(sbi->ll_dt_exp);
else if (cmd == OBD_IOC_GETMDNAME)
obd = class_exp2obd(sbi->ll_md_exp);
ENTRY;
- if (!cfs_capable(CFS_CAP_DAC_READ_SEARCH) &&
+ if (!capable(CAP_DAC_READ_SEARCH) &&
!(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH))
RETURN(-EPERM);