} while(0)
#ifdef __KERNEL__
+
+/*
+ * sleep_on() is known to be racy, using wait_event() interface instead as
+ * recommended. --umka
+ */
+#define OBD_SLEEP_ON(wq) \
+do { \
+ DEFINE_WAIT(__wait); \
+ prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
+ schedule(); \
+ finish_wait(&wq, &__wait); \
+} while (0)
+
/* The idea here is to synchronise two threads to force a race. The
* first thread that calls this with a matching fail_loc is put to
* sleep. The next thread that calls with the same fail_loc wakes up
do { \
if (OBD_FAIL_CHECK_ONCE(id)) { \
CERROR("obd_race id %x sleeping\n", (id)); \
- sleep_on(&obd_race_waitq); \
+ OBD_SLEEP_ON(obd_race_waitq); \
CERROR("obd_fail_race id %x awake\n", (id)); \
} else if ((obd_fail_loc & OBD_FAIL_MASK_LOC) == \
((id) & OBD_FAIL_MASK_LOC)) { \
int m_size;
};
+void lvfs_memdbg_show(void);
void lvfs_memdbg_insert(struct mem_track *mt);
void lvfs_memdbg_remove(struct mem_track *mt);
struct mem_track *lvfs_memdbg_find(void *ptr);
GOTO(err_import, rc = -ENOSYS);
}
- register_f = inter_module_get("mgmtcli_register_for_events");
+ register_f = (mgmtcli_register_for_events_t)symbol_get("mgmtcli_register_for_events");
if (!register_f) {
CERROR("can't i_m_g mgmtcli_register_for_events\n");
GOTO(err_import, rc = -ENOSYS);
}
rc = register_f(mgmt_obd, obddev, &imp->imp_target_uuid);
- inter_module_put("mgmtcli_register_for_events");
+ symbol_put("mgmtcli_register_for_events");
if (!rc)
cli->cl_mgmtcli_obd = mgmt_obd;
if (cli->cl_mgmtcli_obd) {
mgmtcli_deregister_for_events_t dereg_f;
- dereg_f = inter_module_get("mgmtcli_deregister_for_events");
+ dereg_f = symbol_get("mgmtcli_deregister_for_events");
dereg_f(cli->cl_mgmtcli_obd, obddev);
- inter_module_put("mgmtcli_deregister_for_events");
+ symbol_put("mgmtcli_deregister_for_events");
}
/* Here we try to drop the security structure after destroy import,
EXIT;
}
-void ll_intent_free(struct lookup_intent *it)
-{
- if (it->d.fs_data) {
- OBD_SLAB_FREE(it->d.fs_data, ll_intent_slab,
- sizeof(struct lustre_intent_data));
- it->d.fs_data = NULL;
- }
-}
-
void ll_unhash_aliases(struct inode *inode)
{
struct list_head *tmp, *head;
return 0;
}
OBD_SLAB_ALLOC(it->d.fs_data, ll_intent_slab, SLAB_KERNEL,
- sizeof(struct lustre_intent_data));
+ sizeof(struct lustre_intent_data));
if (!it->d.fs_data) {
CERROR("Failed to allocate memory for lustre specific intent "
"data\n");
}
it->it_op_release = ll_intent_release;
-
return 0;
}
+void ll_intent_free(struct lookup_intent *it)
+{
+ if (it->d.fs_data) {
+ OBD_SLAB_FREE(it->d.fs_data, ll_intent_slab,
+ sizeof(struct lustre_intent_data));
+ it->d.fs_data = NULL;
+ }
+}
+
static inline int
ll_special_name(struct dentry *de)
{
* lookup control path, which is always made with parent's i_sem taken.
* --umka
*/
- if (!((de->d_inode->i_mode & S_ISUID) && S_ISDIR(de->d_inode->i_mode)) ||
- !(flags & LOOKUP_CONTINUE || (orig_it & (IT_CHDIR | IT_OPEN))))
+ if (((de->d_inode->i_mode & S_ISUID) && S_ISDIR(de->d_inode->i_mode)) ||
+ !(flags & LOOKUP_CONTINUE || (orig_it & (IT_CHDIR | IT_OPEN)))) {
+
+ /* special "." and ".." has to be always revalidated */
+ if (rc && !ll_special_name(de) && nd != NULL && !(nd->flags & LOOKUP_LAST)) {
+ ll_intent_drop_lock(it);
+ rc = 0;
+ }
+
+ ll_intent_release(it);
return rc;
-
- /* special "." and ".." has to be always revalidated */
- if (rc && !ll_special_name(de) && nd != NULL && !(nd->flags & LOOKUP_LAST)) {
- ll_intent_drop_lock(it);
- return 0;
}
-
+
return rc;
do_lookup:
it = &lookup_it;
de->d_name.len, NULL, 0, NULL,
it, 0, &req, ll_mdc_blocking_ast);
if (rc >= 0) {
- struct mds_body *mds_body = lustre_msg_buf(req->rq_repmsg, 1, sizeof(*mds_body));
+ struct mds_body *mds_body = lustre_msg_buf(req->rq_repmsg, 1,
+ sizeof(*mds_body));
/* See if we got same inode, if not - return error */
if (id_equal_stc(&cid, &mds_body->id1))
RETURN(-ETIME);
}
+/*
+ * sending a signal known to be ignored to cause restarting syscall if GNS mount
+ * function returns -ERESTARTSYS.
+ */
+static void
+ll_gns_send_signal(void)
+{
+ struct task_struct *task = current;
+ int signal = SIGCONT;
+
+ read_lock(&tasklist_lock);
+ spin_lock_irq(&task->sighand->siglock);
+ sigaddset(&task->pending.signal, signal);
+ spin_unlock_irq(&task->sighand->siglock);
+ read_unlock(&tasklist_lock);
+ set_tsk_thread_flag(task, TIF_SIGPENDING);
+}
+
/*
* tries to mount the mount object under passed @dentry. In the case of success
* @dentry will become mount point and 0 will be returned. Error code will be
RETURN(-EINVAL);
}
+ if (mnt == NULL) {
+ CERROR("suid directory found, but no "
+ "vfsmount available.\n");
+ RETURN(-EINVAL);
+ }
+
/*
* another thead is in progress or just finished mounting the
* dentry. Handling that.
if (sbi->ll_gns_state == LL_GNS_MOUNTING ||
sbi->ll_gns_state == LL_GNS_FINISHED) {
/*
- * check if another thread is trying to mount some GNS dentry
- * too. Letting it know that we busy and make ll_lookup_it() to
- * restart syscall and try again later.
+ * another thread is trying to mount GNS dentry. We'd like to
+ * handling that.
*/
spin_unlock(&sbi->ll_gns_lock);
- RETURN(-EAGAIN);
- }
- LASSERT(sbi->ll_gns_state == LL_GNS_IDLE);
- if (mnt == NULL) {
- CERROR("suid directory found, but no "
- "vfsmount available.\n");
- RETURN(-EINVAL);
+ /*
+ * check if dentry is mount point already, if so, do not restart
+ * syscal.
+ */
+ if (d_mountpoint(dentry))
+ RETURN(0);
+
+ /*
+ * causing syscall to restart and find this dentry already
+ * mounted.
+ */
+ ll_gns_send_signal();
+ RETURN(-ERESTARTSYS);
+
+#if 0
+ wait_for_completion(&sbi->ll_gns_mount_finished);
+ if (d_mountpoint(dentry))
+ RETURN(0);
+#endif
}
+ LASSERT(sbi->ll_gns_state == LL_GNS_IDLE);
CDEBUG(D_INODE, "mounting dentry %p\n", dentry);
up(&sbi->ll_gns_sem);
- rc = USERMODEHELPER(argv[0], argv, NULL);
+ /* do not wait for helper complete here. */
+ rc = call_usermodehelper(argv[0], argv, NULL, 0);
if (rc) {
CERROR("failed to call GNS upcall %s, err = %d\n",
sbi->ll_gns_upcall, rc);
}
/*
- * wait for mount completion. This is actually not needed, because
- * USERMODEHELPER() returns only when usermode process finishes. But we
- * doing this just for case USERMODEHELPER() semantics will be changed
- * or usermode upcall program will start mounting in backgound and
- * return instantly. --umka
+ * waiting for dentry become mount point GNS_WAIT_ATTEMPTS times by 1
+ * second.
*/
rc = ll_gns_wait_for_mount(dentry, 1, GNS_WAIT_ATTEMPTS);
+ complete_all(&sbi->ll_gns_mount_finished);
if (rc == 0) {
struct dentry *rdentry;
struct vfsmount *rmnt;
dput(dchild);
case 1:
free_page((unsigned long)pathpage);
+ complete_all(&sbi->ll_gns_mount_finished);
case 0:
spin_lock(&sbi->ll_gns_lock);
sbi->ll_gns_state = LL_GNS_IDLE;
int ll_gns_state;
struct timer_list ll_gns_timer;
struct list_head ll_gns_sbi_head;
+ struct completion ll_gns_mount_finished;
unsigned long ll_gns_tick;
unsigned long ll_gns_timeout;
data->mod_time = LTIME_S(CURRENT_TIME);
}
+#if 0
+/*
+ * this was needed for catching correct calling place of ll_intent_alloc() with
+ * missed ll_intent_free() causing memory leak. --umka
+ */
+#define ll_intent_alloc(it) \
+ ({ \
+ int err; \
+ OBD_SLAB_ALLOC((it)->d.fs_data, ll_intent_slab, SLAB_KERNEL, \
+ sizeof(struct lustre_intent_data)); \
+ if (!(it)->d.fs_data) { \
+ err = -ENOMEM; \
+ } else { \
+ err = 0; \
+ } \
+ (it)->it_op_release = ll_intent_release; \
+ err; \
+ })
+
+#define ll_intent_free(it) \
+ do { \
+ if ((it)->d.fs_data) { \
+ OBD_SLAB_FREE((it)->d.fs_data, ll_intent_slab, \
+ sizeof(struct lustre_intent_data)); \
+ (it)->d.fs_data = NULL; \
+ } \
+ } while (0)
+#endif
+
#endif /* LLITE_INTERNAL_H */
spin_lock_init(&sbi->ll_gns_lock);
INIT_LIST_HEAD(&sbi->ll_gns_sbi_head);
init_waitqueue_head(&sbi->ll_gns_waitq);
+ init_completion(&sbi->ll_gns_mount_finished);
/* this later may be reset via /proc/fs/... */
memcpy(sbi->ll_gns_oname, ".mntinfo", strlen(".mntinfo"));
struct ptlrpc_request *request = NULL;
struct mdc_op_data *op_data;
int ia_valid = attr->ia_valid;
- int rc = 0;
+ int err, rc = 0;
ENTRY;
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu\n", inode->i_ino);
* NB: ATTR_SIZE will only be set at this point if the size
* resides on the MDS, ie, this file has no objects. */
attr->ia_valid &= ~ATTR_SIZE;
- inode_setattr(inode, attr);
+ err = inode_setattr(inode, attr);
+ if (err) {
+ CERROR("inode_setattr() failed, inode=%lu/%u(%p), "
+ "err = %d\n", (unsigned long)inode->i_ino,
+ inode->i_generation, inode, err);
+ /* should we go to error path here? --umka */
+ }
ll_update_inode(inode, &md);
ptlrpc_req_finished(request);
}
/* Won't invoke vmtruncate, as we already cleared ATTR_SIZE */
- inode_setattr(inode, attr);
+ err = inode_setattr(inode, attr);
+ if (err) {
+ CERROR("inode_setattr() failed, inode=%lu/%u(%p), "
+ "err = %d\n", (unsigned long)inode->i_ino,
+ inode->i_generation, inode, err);
+ /* should we go to error path here? --umka */
+ }
}
/* We really need to get our PW lock before we change inode->i_size.
((flags & LOOKUP_CONTINUE) || (orig_it & (IT_CHDIR | IT_OPEN))))
{
rc = ll_gns_mount_object(dentry, nd->mnt);
- if (rc == -EAGAIN) {
- /*
- * making system to restart syscall as currently GNS is
- * in mounting progress.
- */
+ if (rc == -ERESTARTSYS) {
+ /* causing syscall restart */
GOTO(out, retval = ERR_PTR(-ERESTARTSYS));
}
* reg file.
*/
CDEBUG(D_INODE, "failed to mount %*s, err %d\n",
- (int)dentry->d_name.len, dentry->d_name.name);
+ (int)dentry->d_name.len, dentry->d_name.name, rc);
}
}
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/lprocfs_status.h>
+#include <linux/obd_support.h>
#include "llite_internal.h"
struct super_block * ll_get_sb(struct file_system_type *fs_type,
EXPORT_SYMBOL(lvfs_memdbg_check_remove);
#endif
-static void lvfs_memdbg_show(void)
+void lvfs_memdbg_show(void)
{
#if defined (CONFIG_DEBUG_MEMORY) && defined(__KERNEL__)
struct hlist_node *node = NULL;
#endif
}
}
+EXPORT_SYMBOL(lvfs_memdbg_show);
static int __init lvfs_linux_init(void)
{
static int __init obdfilter_init(void)
{
struct lprocfs_static_vars lvars;
- int rc;
+ int size, rc;
printk(KERN_INFO "Lustre: Filtering OBD driver; info@clusterfs.com\n");
lprocfs_init_vars(filter, &lvars);
- OBD_ALLOC(obdfilter_created_scratchpad,
- OBDFILTER_CREATED_SCRATCHPAD_ENTRIES *
- sizeof(*obdfilter_created_scratchpad));
+ size = OBDFILTER_CREATED_SCRATCHPAD_ENTRIES *
+ sizeof(*obdfilter_created_scratchpad);
+
+ OBD_ALLOC(obdfilter_created_scratchpad, size);
if (obdfilter_created_scratchpad == NULL) {
CERROR ("Can't allocate scratchpad\n");
return -ENOMEM;
rc = class_register_type(&filter_obd_ops, NULL, lvars.module_vars,
OBD_FILTER_DEVICENAME);
if (rc) {
- OBD_FREE(obdfilter_created_scratchpad,
- OBDFILTER_CREATED_SCRATCHPAD_ENTRIES *
- sizeof(*obdfilter_created_scratchpad));
+ OBD_FREE(obdfilter_created_scratchpad, size);
return rc;
}
OBD_FILTER_SAN_DEVICENAME);
if (rc) {
class_unregister_type(OBD_FILTER_DEVICENAME);
- OBD_FREE(obdfilter_created_scratchpad,
- OBDFILTER_CREATED_SCRATCHPAD_ENTRIES *
- sizeof(*obdfilter_created_scratchpad));
+ OBD_FREE(obdfilter_created_scratchpad, size);
}
return rc;
}
}
run_one() {
- if ! mount | grep -q $DIR; then
+ if ! cat /proc/mounts | grep -q $DIR; then
$START
fi
echo $PTLDEBUG >/proc/sys/portals/debug
disable_gns
+ echo ""
+ echo "turning SUID on $DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT off"
chmod u-s $DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT
enable_gns