From 17b1b04c128e1823345020c969126ec10b4040c2 Mon Sep 17 00:00:00 2001 From: yury Date: Thu, 7 Apr 2005 10:49:37 +0000 Subject: [PATCH] - removed hardcoded checking for ".mntinfo" on MDS to see if we are trying to open GNS mount object. By now only suid bit on directory is checked. This should not break anything, as it is not used for any purpose. - 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. --- lustre/include/linux/lustre_idl.h | 2 +- lustre/include/linux/lustre_lite.h | 34 ------------------- lustre/llite/dcache.c | 1 - lustre/llite/file.c | 22 +++++++----- lustre/llite/llite_internal.h | 33 ++++++++++++++++++ lustre/mdc/mdc_lib.c | 10 +++--- lustre/mdc/mdc_request.c | 6 ++-- lustre/mds/mds_open.c | 27 ++++----------- lustre/tests/sanity-gns.sh | 68 ++++++++++++++++++++++++++++++++++---- lustre/utils/lconf | 2 +- 10 files changed, 125 insertions(+), 80 deletions(-) diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index 903d713..0ea4291 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -717,7 +717,7 @@ extern void lustre_swab_mds_rec_setattr (struct mds_rec_setattr *sa); #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; diff --git a/lustre/include/linux/lustre_lite.h b/lustre/include/linux/lustre_lite.h index cdd5875..8d295ce 100644 --- a/lustre/include/linux/lustre_lite.h +++ b/lustre/include/linux/lustre_lite.h @@ -168,40 +168,6 @@ struct lustre_intent_data { }; #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 #endif /* __KERNEL__ */ diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index beb5f53..d74dc8b 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -364,7 +364,6 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd, 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); diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 3b75acf..3c4cadb 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -429,15 +429,18 @@ int ll_file_open(struct inode *inode, struct file *file) (*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); @@ -455,9 +458,12 @@ int ll_file_open(struct inode *inode, struct file *file) 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); diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 5839ba9..8b6102d 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -453,4 +453,37 @@ static inline __u64 ll_file_maxbytes(struct inode *inode) 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 */ diff --git a/lustre/mdc/mdc_lib.c b/lustre/mdc/mdc_lib.c index c52644f..895b2a5 100644 --- a/lustre/mdc/mdc_lib.c +++ b/lustre/mdc/mdc_lib.c @@ -67,11 +67,13 @@ static __u32 mds_pack_open_flags(__u32 flags) /* 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 */ @@ -79,10 +81,10 @@ void mdc_open_pack(struct lustre_msg *msg, int offset, 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, diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 7a751af..8bd309a 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -638,14 +638,14 @@ int mdc_close(struct obd_export *exp, struct obdo *oa, 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; diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c index 6948dd4..1c1b41f 100644 --- a/lustre/mds/mds_open.c +++ b/lustre/mds/mds_open.c @@ -836,21 +836,6 @@ int mds_lock_new_child(struct obd_device *obd, struct inode *inode, 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) { @@ -1191,16 +1176,16 @@ got_child: 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 } } @@ -1262,8 +1247,8 @@ got_child: /* 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); diff --git a/lustre/tests/sanity-gns.sh b/lustre/tests/sanity-gns.sh index cff80a1..c30efc2 100644 --- a/lustre/tests/sanity-gns.sh +++ b/lustre/tests/sanity-gns.sh @@ -280,6 +280,7 @@ check_gns() { 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" @@ -293,8 +294,22 @@ check_gns() { 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`" @@ -393,7 +408,7 @@ test_1a() { 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 @@ -430,7 +445,7 @@ test_2a() { 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 @@ -466,12 +481,14 @@ test_3a() { 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 @@ -485,7 +502,44 @@ test_3a() { 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 =============" diff --git a/lustre/utils/lconf b/lustre/utils/lconf index 49d6fe6b..1accff7 100755 --- a/lustre/utils/lconf +++ b/lustre/utils/lconf @@ -1005,7 +1005,7 @@ def clean_loop(dev, fstype, backfstype, backdev): 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 -- 1.8.3.1