- cleanups, moving not needed to be widely known llite functions to llite_internal.h
- added test_4a to sanity-gns.sh. It checks how GNS mounting works with 20 concurrent threads aiming to mount the same object.
#define MDS_OPEN_DELAY_CREATE 0100000000 /* delay initial object create */
#define MDS_OPEN_HAS_EA 010000000000 /* specify object create pattern */
-#define MDS_OPEN_HAS_OBJS 020000000000 /* Just set the EA the obj exist */
+#define MDS_OPEN_HAS_OBJS 020000000000 /* just set the EA the obj exist */
struct mds_rec_create {
__u32 cr_opcode;
};
#define LUSTRE_IT(it) ((struct lustre_intent_data *)((it)->d.fs_data))
-static inline void
-ll_inode2id(struct lustre_id *id, struct inode *inode)
-{
- struct lustre_id *lid = &ll_i2info(inode)->lli_id;
-
- mdc_pack_id(id, inode->i_ino, inode->i_generation,
- (inode->i_mode & S_IFMT), id_group(lid),
- id_fid(lid));
-}
-
-static inline void
-ll_prepare_mdc_data(struct mdc_op_data *data, struct inode *i1,
- struct inode *i2, const char *name, int namelen,
- int mode)
-{
- LASSERT(i1);
-
- ll_inode2id(&data->id1, i1);
-
- /* it could be directory with mea */
- data->mea1 = ll_i2info(i1)->lli_mea;
-
- if (i2) {
- ll_inode2id(&data->id2, i2);
- data->mea2 = ll_i2info(i2)->lli_mea;
- }
-
- data->valid = 0;
- data->name = name;
- data->namelen = namelen;
- data->create_mode = mode;
- data->mod_time = LTIME_S(CURRENT_TIME);
-}
-
#else
#include <linux/lustre_idl.h>
#endif /* __KERNEL__ */
if (rc)
LBUG(); /* Can't think of better idea just yet */
-
rc = md_intent_lock(exp, &pid, de->d_name.name,
de->d_name.len, NULL, 0, &cid, &lookup_it,
flags, &req, ll_mdc_blocking_ast);
(*och_usecount)++;
if (!it || !LUSTRE_IT(it) || !LUSTRE_IT(it)->it_disposition) {
- /* We are going to replace intent here, and that may
- possibly change access mode (FMODE_EXEC can only be
- set in intent), but I hope it never happens (I was
- not able to trigger it yet at least) -- green */
+ /*
+ * we are going to replace intent here, and that may
+ * possibly change access mode (FMODE_EXEC can only be
+ * set in intent), but I hope it never happens (I was
+ * not able to trigger it yet at least) -- green
+ */
+
/* FIXME: FMODE_EXEC is not covered by O_ACCMODE! */
LASSERT(!(it->it_flags & FMODE_EXEC));
LASSERTF((it->it_flags & O_ACCMODE) ==
(oit.it_flags & O_ACCMODE), "Changing intent "
- "flags %x to incompatible %x\n",it->it_flags,
+ "flags %x to incompatible %x\n", it->it_flags,
oit.it_flags);
it = &oit;
rc = ll_intent_file_open(file, NULL, 0, it);
LASSERTF(rc == 0, "rc = %d\n", rc);
}
up(&lli->lli_och_sem);
- /* Must do this outside lli_och_sem lock to prevent deadlock where
- different kind of OPEN lock for this same inode gets cancelled
- by ldlm_cancel_lru */
+
+ /*
+ * must do this outside lli_och_sem lock to prevent deadlock where
+ * different kind of OPEN lock for this same inode gets cancelled by
+ * ldlm_cancel_lru
+ */
if (!S_ISREG(inode->i_mode))
GOTO(out, rc);
return ll_i2info(inode)->lli_maxbytes;
}
+static inline void
+ll_inode2id(struct lustre_id *id, struct inode *inode)
+{
+ struct lustre_id *lid = &ll_i2info(inode)->lli_id;
+
+ mdc_pack_id(id, inode->i_ino, inode->i_generation,
+ (inode->i_mode & S_IFMT), id_group(lid),
+ id_fid(lid));
+}
+
+static inline void
+ll_prepare_mdc_data(struct mdc_op_data *data, struct inode *i1,
+ struct inode *i2, const char *name, int namelen,
+ int mode)
+{
+ LASSERT(i1);
+ ll_inode2id(&data->id1, i1);
+
+ /* it could be directory with mea */
+ data->mea1 = ll_i2info(i1)->lli_mea;
+
+ if (i2) {
+ ll_inode2id(&data->id2, i2);
+ data->mea2 = ll_i2info(i2)->lli_mea;
+ }
+
+ data->valid = 0;
+ data->name = name;
+ data->namelen = namelen;
+ data->create_mode = mode;
+ data->mod_time = LTIME_S(CURRENT_TIME);
+}
+
#endif /* LLITE_INTERNAL_H */
/* packing of MDS records */
void mdc_open_pack(struct lustre_msg *msg, int offset,
- struct mdc_op_data *op_data, __u32 mode, __u64 rdev,
- __u32 flags, const void *lmm, int lmmlen)
+ struct mdc_op_data *op_data, __u32 mode,
+ __u64 rdev, __u32 flags, const void *lmm,
+ int lmmlen)
{
struct mds_rec_create *rec;
char *tmp;
+
rec = lustre_msg_buf(msg, offset, sizeof (*rec));
/* XXX do something about time, uid, gid */
if (op_data != NULL)
rec->cr_id = op_data->id1;
memset(&rec->cr_replayid, 0, sizeof(rec->cr_replayid));
- rec->cr_mode = mode;
rec->cr_flags = mds_pack_open_flags(flags);
- rec->cr_rdev = rdev;
rec->cr_time = op_data->mod_time;
+ rec->cr_mode = mode;
+ rec->cr_rdev = rdev;
if (op_data->name) {
tmp = lustre_msg_buf(msg, offset + 1,
RETURN(-EIO);
}
- //reqsize[0] = mdc_get_secdesc_size();
- //mdc_pack_secdesc(req, reqsize[0]);
-
req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
MDS_CLOSE, 3, reqsize, NULL);
if (req == NULL)
GOTO(out, rc = -ENOMEM);
+ //reqsize[0] = mdc_get_secdesc_size();
+ //mdc_pack_secdesc(req, reqsize[0]);
+
/* Ensure that this close's handle is fixed up during replay. */
LASSERT(och != NULL);
mod = och->och_mod;
RETURN(rc);
}
-static int is_mount_object(struct dentry *dparent)
-{
- struct dentry *dchild;
-
- if (!(dparent->d_inode->i_mode & S_ISUID))
- return 0;
-
- dchild = lookup_one_len(".mntinfo", dparent, strlen(".mntinfo"));
- if (IS_ERR(dchild) || dchild == NULL)
- return 0;
-
- dput(dchild);
- return 1;
-}
-
int mds_open(struct mds_update_record *rec, int offset,
struct ptlrpc_request *req, struct lustre_handle *child_lockh)
{
if (S_ISDIR(dchild->d_inode->i_mode)) {
if (rec->ur_flags & MDS_OPEN_CREAT ||
rec->ur_flags & FMODE_WRITE) {
- /*we are trying to create or write a exist dir*/
+ /* we are trying to create or write a exist dir */
GOTO(cleanup, rc = -EISDIR);
}
if (ll_permission(dchild->d_inode, acc_mode, NULL))
GOTO(cleanup, rc = -EACCES);
- if (is_mount_object(dchild)) {
- CERROR("Found possible GNS mount object %*s; not "
- "opening.\n", dchild->d_name.len,
- dchild->d_name.name);
+ /* skip GNS suid bit marked directories. */
+ if (dchild->d_inode->i_mode & S_ISUID) {
+ CDEBUG(D_INODE, "found GNS mount object %*s, not opening.\n",
+ dchild->d_name.len, dchild->d_name.name);
GOTO(cleanup, rc = 0); // success, but don't really open
}
}
/* Step 5: mds_open it */
rc = mds_finish_open(req, dchild, body, rec->ur_flags, &handle,
rec, rep);
- GOTO(cleanup, rc);
+ EXIT;
cleanup:
rc = mds_finish_transno(mds, dchild ? dchild->d_inode : NULL, handle,
req, rc, rep ? rep->lock_policy_res1 : 0);
local OBJECT=$2
local TIMOUT=$3
local TICK=$4
+ local MODE=$5
rm -fr $LOG >/dev/null 2>&1
UPCALL_PATH="/tmp/gns-upcall-$UPCALL.sh"
echo "$UPCALL_PATH" > /proc/fs/lustre/llite/fs0/gns_upcall || return $?
echo "upcall: $(cat /proc/fs/lustre/llite/fs0/gns_upcall)"
- echo -n "mount on open $OBJECT/test_file1: "
- echo -n "test data" > $OBJECT/test_file1 >/dev/null 2>&1 || return $?
+ test "x$MODE" = "xGENERIC" && {
+ echo -n "mount on open $OBJECT/test_file1 (generic): "
+
+ echo -n "test data" > $OBJECT/test_file1 >/dev/null 2>&1 || return $?
+ } || {
+ local i=1
+ local nr=20
+
+ echo -n "mount on open $OBJECT/test_file1 ($nr threads): "
+
+ for ((;i<=$nr;i++)); do
+ echo -n "test data" > $OBJECT/test_file$i >/dev/null 2>&1 &
+ done
+
+ wait
+ }
local ENTRY="`basename $OBJECT`"
echo ""
echo "testing GNS with GENERIC upcall 3 times on the row"
for ((i=0;i<3;i++)); do
- check_gns GENERIC $DIR/gns_test_1a $TIMOUT $TICK || {
+ check_gns GENERIC $DIR/gns_test_1a $TIMOUT $TICK GENERIC || {
cleanup_object $DIR/gns_test_1a
cleanup_loop $LOOP_DEV $LOOP_FILE
error
echo ""
echo "testing GNS with DEADLOCK upcall 3 times on the row"
for ((i=0;i<3;i++)); do
- check_gns DEADLOCK $DIR/gns_test_2a $TIMOUT $TICK || {
+ check_gns DEADLOCK $DIR/gns_test_2a $TIMOUT $TICK GENERIC || {
cleanup_object $DIR/gns_test_2a
cleanup_loop $LOOP_DEV $LOOP_FILE
error
echo ""
echo "testing GNS with DEADLOCK upcall 4 times on the row"
- for ((i=0;i<4;i++)); do
+ local i=0
+
+ for ((;i<4;i++)); do
local MODE="GENERIC"
test $(($i%2)) -eq 1 && MODE="DEADLOCK"
- check_gns $MODE $DIR/gns_test_3a $TIMOUT $TICK || {
+ check_gns $MODE $DIR/gns_test_3a $TIMOUT $TICK GENERIC || {
cleanup_object $DIR/gns_test_3a
cleanup_loop $LOOP_DEV $LOOP_FILE
error
run_test 3a " general GNS test - mounting/umount (GENERIC/DEADLOCK) ====="
test_4a() {
- echo "Not implemented yet!"
+ local LOOP_DEV=$(find_free_loop 2>/dev/null)
+ local UPCALL="/tmp/gns-upcall.sh"
+ local LOOP_FILE="/tmp/gns_loop_4a"
+ local OBJECT=".mntinfo"
+ local TIMOUT=5
+ local TICK=1
+
+ test "x$LOOP_DEV" != "x" && test -b $LOOP_DEV ||
+ error "can't find free loop device"
+
+ echo "preparing loop device $LOOP_DEV <-> $LOOP_FILE..."
+ cleanup_loop $LOOP_DEV $LOOP_FILE
+ setup_loop $LOOP_DEV $LOOP_FILE || error
+
+ echo "setting up GNS timeouts and mount object..."
+ setup_gns $OBJECT $TIMOUT $TICK || error
+
+ echo "preparing mount object at $DIR/gns_test_4a/$OBJECT..."
+ setup_object $DIR/gns_test_4a $OBJECT "-t ext2 $LOOP_DEV" || error
+
+ echo ""
+ echo "testing GNS with DEADLOCK upcall 4 times on the row"
+ local i=0
+
+ for ((;i<4;i++)); do
+ local MODE="GENERIC"
+
+ test $(($i%2)) -eq 1 && MODE="DEADLOCK"
+
+ check_gns $MODE $DIR/gns_test_4a $TIMOUT $TICK CONCURRENT || {
+ cleanup_object $DIR/gns_test_4a
+ cleanup_loop $LOOP_DEV $LOOP_FILE
+ error
+ }
+ done
+
+ cleanup_object $DIR/gns_test_4a
+ cleanup_loop $LOOP_DEV $LOOP_FILE
}
run_test 4a " general GNS test - concurrent mounting/umount ============="
print "detach " + dev + " <-> " + realfile
ret, out = run('losetup -d', dev)
if ret:
- log('unable to clean loop device:', dev, 'for file:', realfile)
+ log('unable to clean loop device', dev, 'for file', realfile)
logall(out)
# finilizes passed device