cmd->u.pccc_add.pccc_hsmtool_type = HSMTOOL_UNKNOWN;
/* Enable these features by default */
cmd->u.pccc_add.pccc_flags |= PCC_DATASET_AUTO_ATTACH |
- PCC_DATASET_MMAP_CONV |
PCC_DATASET_PROJ_QUOTA;
break;
case PCC_DEL_DATASET:
if (list_empty(&super->pccs_datasets))
RETURN(0);
+ if (lli->lli_pcc_state & PCC_STATE_FL_ATTACHING)
+ RETURN(0);
+
+ /* Forbid to auto attach the file once mmapped into PCC. */
+ if (atomic_read(&lli->lli_pcc_mapcnt) > 0)
+ RETURN(0);
+
/*
* The file layout lock was cancelled. And this open does not
* obtain valid layout lock from MDT (i.e. the file is being
pcc_inode_lock(inode);
if (rc)
RETURN(rc);
+
+ if (atomic_read(&lli->lli_pcc_mapcnt) > 0)
+ RETURN(0);
}
rc = pcc_get_layout_info(inode, &clt);
return true;
}
+static inline void
+pcc_file_mapping_reset(struct inode *inode, struct file *file)
+{
+ if (file) {
+ struct pcc_inode *pcci = ll_i2pcci(inode);
+ struct file *pcc_file = ll_file2pccf(file)->pccf_file;
+ struct inode *pcc_inode = pcci->pcci_path.dentry->d_inode;
+
+ if (pcc_inode->i_mapping == &pcc_inode->i_data)
+ pcc_file->f_mapping = pcc_inode->i_mapping;
+ }
+}
+
static void pcc_io_init(struct inode *inode, enum pcc_io_type iot,
- bool *cached)
+ struct file *file, bool *cached)
{
struct pcc_inode *pcci;
} else {
*cached = false;
/*
- * FIXME: Forbid auto PCC attach if the file has still been
- * mmapped in PCC.
+ * Forbid to auto PCC attach if the file has still been
+ * mapped in PCC.
*/
if (pcc_may_auto_attach(inode, iot)) {
(void) pcc_try_auto_attach(inode, cached, iot);
if (*cached) {
pcci = ll_i2pcci(inode);
+ pcc_file_mapping_reset(inode, file);
LASSERT(atomic_read(&pcci->pcci_refcount) > 0);
atomic_inc(&pcci->pcci_active_ios);
}
wake_up_all(&pcci->pcci_waitq);
}
+static inline void
+pcc_file_fallback_set(struct ll_inode_info *lli, struct pcc_file *pccf)
+{
+ atomic_inc(&lli->lli_pcc_mapneg);
+ pccf->pccf_fallback = 1;
+}
+
+static inline void
+pcc_file_fallback_reset(struct ll_inode_info *lli, struct pcc_file *pccf)
+{
+ if (pccf->pccf_fallback) {
+ pccf->pccf_fallback = 0;
+ atomic_dec(&lli->lli_pcc_mapneg);
+ }
+}
+
int pcc_file_open(struct inode *inode, struct file *file)
{
struct pcc_inode *pcci;
pcc_inode_lock(inode);
pcci = ll_i2pcci(inode);
- if (lli->lli_pcc_state & PCC_STATE_FL_ATTACHING)
+ if (lli->lli_pcc_state & PCC_STATE_FL_ATTACHING) {
+ pcc_file_fallback_set(lli, pccf);
GOTO(out_unlock, rc = 0);
+ }
if (!pcci || !pcc_inode_has_layout(pcci)) {
if (pcc_may_auto_attach(inode, PIT_OPEN))
if (rc == 0 && !cached && inode_owner_or_capable(inode))
rc = pcc_try_readonly_open_attach(inode, file, &cached);
- if (rc < 0 || !cached)
+ if (rc < 0)
+ GOTO(out_unlock, rc);
+
+ if (!cached) {
+ pcc_file_fallback_set(lli, pccf);
GOTO(out_unlock, rc);
+ }
pcci = ll_i2pcci(inode);
}
pccf = &fd->fd_pcc_file;
pcc_inode_lock(inode);
+ pcc_file_fallback_reset(ll_i2info(inode), pccf);
+
if (pccf->pccf_file == NULL)
goto out;
RETURN(0);
}
- pcc_io_init(inode, PIT_READ, cached);
+ pcc_io_init(inode, PIT_READ, file, cached);
if (!*cached)
RETURN(0);
RETURN(0);
}
- pcc_io_init(inode, PIT_WRITE, cached);
+ pcc_io_init(inode, PIT_WRITE, file, cached);
if (!*cached)
RETURN(0);
RETURN(0);
}
- pcc_io_init(inode, PIT_SETATTR, cached);
+ pcc_io_init(inode, PIT_SETATTR, NULL, cached);
if (!*cached)
RETURN(0);
RETURN(0);
}
- pcc_io_init(inode, PIT_GETATTR, cached);
+ pcc_io_init(inode, PIT_GETATTR, NULL, cached);
if (!*cached)
RETURN(0);
RETURN(default_file_splice_read(in_file, ppos, pipe,
count, flags));
- pcc_io_init(inode, PIT_SPLICE_READ, &cached);
+ pcc_io_init(inode, PIT_SPLICE_READ, in_file, &cached);
if (!cached)
RETURN(default_file_splice_read(in_file, ppos, pipe,
count, flags));
RETURN(0);
}
- pcc_io_init(inode, PIT_FSYNC, cached);
+ pcc_io_init(inode, PIT_FSYNC, file, cached);
if (!*cached)
RETURN(0);
int pcc_file_mmap(struct file *file, struct vm_area_struct *vma,
bool *cached)
{
- struct file *pcc_file = ll_file2pccf(file)->pccf_file;
+ struct pcc_file *pccf = ll_file2pccf(file);
+ struct file *pcc_file = pccf->pccf_file;
struct inode *inode = file_inode(file);
struct pcc_inode *pcci;
int rc = 0;
pcc_inode_lock(inode);
pcci = ll_i2pcci(inode);
if (pcci && pcc_inode_has_layout(pcci)) {
+ struct ll_inode_info *lli = ll_i2info(inode);
struct inode *pcc_inode = file_inode(pcc_file);
struct pcc_vma *pccv;
+ if (pccf->pccf_fallback) {
+ LASSERT(atomic_read(&lli->lli_pcc_mapneg) > 0);
+ GOTO(out, rc);
+ }
+
+ if (atomic_read(&lli->lli_pcc_mapneg) > 0) {
+ pcc_file_fallback_set(lli, pccf);
+ GOTO(out, rc);
+ }
+
LASSERT(atomic_read(&pcci->pcci_refcount) > 1);
*cached = true;
}
run_test 43 "Auto attach at open() should add capacity owner check"
+test_97() {
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
+ local file=$DIR/$tfile
+
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 60
+ do_facet $SINGLEAGT mkdir $hsm_root || error "mkdir $hsm_root failed"
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={0}\ roid=$HSM_ARCHIVE_NUMBER\ ropcc=1\ mmap_conv=0"
+ do_facet $SINGLEAGT $LCTL pcc list $MOUNT
+ do_facet $SINGLEAGT $LCTL set_param llite.*.pcc_async_threshold=1G
+
+ local mpid1
+ local mpid2
+ local lpid
+
+ do_facet $SINGLEAGT dd if=/dev/zero of=$file bs=1M count=50 ||
+ error "Write $file failed"
+
+ (
+ while [ ! -e $DIR/sanity-pcc.97.lck ]; do
+ echo "T1. $MMAP_CAT $file ..."
+ do_facet $SINGLEAGT $MMAP_CAT $file > /dev/null ||
+ error "$MMAP_CAT $file failed"
+ sleep 0.$((RANDON % 4 + 1))
+ done
+ )&
+ mpid1=$!
+
+ (
+ while [ ! -e $DIR/sanity-pcc.97.lck ]; do
+ echo "T2. $MMAP_CAT $file ..."
+ do_facet $SINGLEAGT $MMAP_CAT $file > /dev/null ||
+ error "$MMAP_CAT $file failed"
+ sleep 0.$((RANDOM % 4 + 1))
+ done
+ )&
+ mpid2=$!
+
+ (
+ while [ ! -e $DIR/sanity-pcc.97.lck ]; do
+ do_facet $SINGLEAGT $LCTL set_param -n ldlm.namespaces.*mdc*.lru_size=clear ||
+ error "cancel_lru_locks mdc failed"
+ sleep 0.1
+ done
+ )&
+ lpid=$!
+
+ sleep 120
+ touch $DIR/sanity-pcc.97.lck
+ wait $mpid1 || error "$?: mmap1 failed"
+ wait $mpid2 || error "$?: mmap2 failed"
+ wait $lpid || error "$?: cancel locks failed"
+
+ do_facet $SINGLEAGT $LFS pcc detach $file
+ rm -f $DIR/sanity-pcc.97.lck
+}
+run_test 97 "two mmap I/O and layout lock cancel"
+
+test_98() {
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
+ local file=$DIR/$tfile
+
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 60
+ do_facet $SINGLEAGT mkdir $hsm_root || error "mkdir $hsm_root failed"
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={0}\ roid=$HSM_ARCHIVE_NUMBER\ ropcc=1\ mmap_conv=0"
+ do_facet $SINGLEAGT $LCTL pcc list $MOUNT
+ do_facet $SINGLEAGT $LCTL set_param llite.*.pcc_async_threshold=0
+
+ local rpid
+ local mpid
+ local lpid
+
+ do_facet $SINGLEAGT dd if=/dev/zero of=$file bs=1M count=50 ||
+ error "Write $file failed"
+
+ (
+ while [ ! -e $DIR/sanity-pcc.98.lck ]; do
+ do_facet $SINGLEAGT dd if=$file of=/dev/null bs=1M count=50 ||
+ error "Read $file failed"
+ sleep 0.$((RANDON % 4 + 1))
+ done
+ )&
+ rpid=$!
+
+ (
+ while [ ! -e $DIR/sanity-pcc.98.lck ]; do
+ do_facet $SINGLEAGT $MMAP_CAT $file > /dev/null ||
+ error "$MMAP_CAT $file failed"
+ sleep 0.$((RANDOM % 4 + 1))
+ done
+ )&
+ mpid=$!
+
+ (
+ while [ ! -e $DIR/sanity-pcc.98.lck ]; do
+ do_facet $SINGLEAGT $LCTL set_param -n ldlm.namespaces.*mdc*.lru_size=clear ||
+ error "cancel_lru_locks mdc failed"
+ sleep 0.1
+ done
+ )&
+ lpid=$!
+
+ sleep 60
+ touch $DIR/sanity-pcc.98.lck
+ wait $rpid || error "$?: read failed"
+ wait $mpid || error "$?: mmap failed"
+ wait $lpid || error "$?: cancel locks failed"
+
+ do_facet $SINGLEAGT $LFS pcc detach $file
+ rm -f $DIR/sanity-pcc.98.lck
+}
+run_test 98 "racer between auto attach and mmap I/O"
+
test_99() {
local loopfile="$TMP/$tfile"
local mntpt="/mnt/pcc.$tdir"