X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Flvfs%2Flvfs_linux.c;h=a4538cc28c1375b38549c84824e44f197143c3f5;hp=fbd038d06bcc6926e017e49db2a7e2eb456f0d4b;hb=1e149bef8d832aade6c04b65b8308b71c6d523ed;hpb=6dbf1ffdec1240fbc8a86210b439d31a6c80c8de diff --git a/lustre/lvfs/lvfs_linux.c b/lustre/lvfs/lvfs_linux.c index fbd038d..a4538cc 100644 --- a/lustre/lvfs/lvfs_linux.c +++ b/lustre/lvfs/lvfs_linux.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,8 +24,10 @@ * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2011, 2012, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -38,10 +38,6 @@ * Author: Andreas Dilger */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif - #define DEBUG_SUBSYSTEM S_FILTER #include @@ -58,16 +54,12 @@ #include #include #include -#include "lvfs_internal.h" #include #include -#include -__u64 obd_max_pages = 0; -__u64 obd_max_alloc = 0; struct lprocfs_stats *obd_memory = NULL; -cfs_spinlock_t obd_updatemax_lock = CFS_SPIN_LOCK_UNLOCKED; +EXPORT_SYMBOL(obd_memory); /* refine later and change to seqlock or simlar from libcfs */ /* Debugging check only needed during development */ @@ -120,16 +112,20 @@ static void pop_group_info(struct lvfs_run_ctxt *save, void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx, struct lvfs_ucred *uc) { + /* if there is underlaying dt_device then push_ctxt is not needed */ + if (new_ctx->dt != NULL) + return; + //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n"); ASSERT_CTXT_MAGIC(new_ctx->magic); OBD_SET_CTXT_MAGIC(save); save->fs = get_fs(); - LASSERT(cfs_atomic_read(&cfs_fs_pwd(current->fs)->d_count)); - LASSERT(cfs_atomic_read(&new_ctx->pwd->d_count)); + LASSERT(d_refcount(cfs_fs_pwd(current->fs))); + LASSERT(d_refcount(new_ctx->pwd)); save->pwd = dget(cfs_fs_pwd(current->fs)); save->pwdmnt = mntget(cfs_fs_mnt(current->fs)); - save->luc.luc_umask = current->fs->umask; + save->luc.luc_umask = cfs_curproc_umask(); save->ngroups = current_cred()->group_info->ngroups; LASSERT(save->pwd); @@ -168,6 +164,10 @@ EXPORT_SYMBOL(push_ctxt); void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx, struct lvfs_ucred *uc) { + /* if there is underlaying dt_device then pop_ctxt is not needed */ + if (new_ctx->dt != NULL) + return; + ASSERT_CTXT_MAGIC(saved->magic); ASSERT_KERNEL_CTXT("popping non-kernel context!\n"); @@ -201,100 +201,6 @@ void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx, } EXPORT_SYMBOL(pop_ctxt); -/* utility to make a file */ -struct dentry *simple_mknod(struct dentry *dir, char *name, int mode, int fix) -{ - struct dentry *dchild; - int err = 0; - ENTRY; - - // ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n"); - CDEBUG(D_INODE, "creating file %.*s\n", (int)strlen(name), name); - - dchild = ll_lookup_one_len(name, dir, strlen(name)); - if (IS_ERR(dchild)) - GOTO(out_up, dchild); - - if (dchild->d_inode) { - int old_mode = dchild->d_inode->i_mode; - if (!S_ISREG(old_mode)) - GOTO(out_err, err = -EEXIST); - - /* Fixup file permissions if necessary */ - if (fix && (old_mode & S_IALLUGO) != (mode & S_IALLUGO)) { - CWARN("fixing permissions on %s from %o to %o\n", - name, old_mode, mode); - dchild->d_inode->i_mode = (mode & S_IALLUGO) | - (old_mode & ~S_IALLUGO); - mark_inode_dirty(dchild->d_inode); - } - GOTO(out_up, dchild); - } - - err = ll_vfs_create(dir->d_inode, dchild, (mode & ~S_IFMT) | S_IFREG, - NULL); - if (err) - GOTO(out_err, err); - - RETURN(dchild); - -out_err: - dput(dchild); - dchild = ERR_PTR(err); -out_up: - return dchild; -} -EXPORT_SYMBOL(simple_mknod); - -/* utility to make a directory */ -struct dentry *simple_mkdir(struct dentry *dir, struct vfsmount *mnt, - const char *name, int mode, int fix) -{ - struct dentry *dchild; - int err = 0; - ENTRY; - - // ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n"); - CDEBUG(D_INODE, "creating directory %.*s\n", (int)strlen(name), name); - dchild = ll_lookup_one_len(name, dir, strlen(name)); - if (IS_ERR(dchild)) - GOTO(out_up, dchild); - - if (dchild->d_inode) { - int old_mode = dchild->d_inode->i_mode; - if (!S_ISDIR(old_mode)) { - CERROR("found %s (%lu/%u) is mode %o\n", name, - dchild->d_inode->i_ino, - dchild->d_inode->i_generation, old_mode); - GOTO(out_err, err = -ENOTDIR); - } - - /* Fixup directory permissions if necessary */ - if (fix && (old_mode & S_IALLUGO) != (mode & S_IALLUGO)) { - CDEBUG(D_CONFIG, - "fixing permissions on %s from %o to %o\n", - name, old_mode, mode); - dchild->d_inode->i_mode = (mode & S_IALLUGO) | - (old_mode & ~S_IALLUGO); - mark_inode_dirty(dchild->d_inode); - } - GOTO(out_up, dchild); - } - - err = ll_vfs_mkdir(dir->d_inode, dchild, mnt, mode); - if (err) - GOTO(out_err, err); - - RETURN(dchild); - -out_err: - dput(dchild); - dchild = ERR_PTR(err); -out_up: - return dchild; -} -EXPORT_SYMBOL(simple_mkdir); - /* utility to rename a file */ int lustre_rename(struct dentry *dir, struct vfsmount *mnt, char *oldname, char *newname) @@ -328,300 +234,58 @@ put_old: } EXPORT_SYMBOL(lustre_rename); -/* - * Read a file from within kernel context. Prior to calling this - * function we should already have done a push_ctxt(). - */ -int lustre_fread(struct file *file, void *buf, int len, loff_t *off) -{ - ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n"); - if (!file || !file->f_op || !file->f_op->read || !off) - RETURN(-ENOSYS); - - return file->f_op->read(file, buf, len, off); -} -EXPORT_SYMBOL(lustre_fread); - -/* - * Write a file from within kernel context. Prior to calling this - * function we should already have done a push_ctxt(). - */ -int lustre_fwrite(struct file *file, const void *buf, int len, loff_t *off) -{ - ENTRY; - ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n"); - if (!file) - RETURN(-ENOENT); - if (!file->f_op) - RETURN(-ENOSYS); - if (!off) - RETURN(-EINVAL); - - if (!file->f_op->write) - RETURN(-EROFS); - - RETURN(file->f_op->write(file, buf, len, off)); -} -EXPORT_SYMBOL(lustre_fwrite); - -/* - * Sync a file from within kernel context. Prior to calling this - * function we should already have done a push_ctxt(). - */ -int lustre_fsync(struct file *file) -{ - ENTRY; - ASSERT_KERNEL_CTXT("kernel doing sync outside kernel context\n"); - if (!file || !file->f_op || !file->f_op->fsync) - RETURN(-ENOSYS); - - RETURN(file->f_op->fsync(file, file->f_dentry, 0)); -} -EXPORT_SYMBOL(lustre_fsync); - -/* Note: dput(dchild) will be called if there is an error */ +/* Note: dput(dchild) will *not* be called if there is an error */ struct l_file *l_dentry_open(struct lvfs_run_ctxt *ctxt, struct l_dentry *de, - int flags) + int flags) { - mntget(ctxt->pwdmnt); - return ll_dentry_open(de, ctxt->pwdmnt, flags, current_cred()); + struct path path = { + .dentry = de, + .mnt = ctxt->pwdmnt, + }; + return ll_dentry_open(&path, flags, current_cred()); } EXPORT_SYMBOL(l_dentry_open); -#ifdef HAVE_VFS_READDIR_U64_INO -static int l_filldir(void *__buf, const char *name, int namlen, loff_t offset, - u64 ino, unsigned int d_type) -#else -static int l_filldir(void *__buf, const char *name, int namlen, loff_t offset, - ino_t ino, unsigned int d_type) -#endif -{ - struct l_linux_dirent *dirent; - struct l_readdir_callback *buf = (struct l_readdir_callback *)__buf; - - dirent = buf->lrc_dirent; - if (dirent) - dirent->lld_off = offset; - - OBD_ALLOC(dirent, sizeof(*dirent)); - - if (!dirent) - return -ENOMEM; - - cfs_list_add_tail(&dirent->lld_list, buf->lrc_list); - - buf->lrc_dirent = dirent; - dirent->lld_ino = ino; - LASSERT(sizeof(dirent->lld_name) >= namlen + 1); - memcpy(dirent->lld_name, name, namlen); - - return 0; -} - -long l_readdir(struct file *file, cfs_list_t *dentry_list) -{ - struct l_linux_dirent *lastdirent; - struct l_readdir_callback buf; - int error; - - buf.lrc_dirent = NULL; - buf.lrc_list = dentry_list; - - error = vfs_readdir(file, l_filldir, &buf); - if (error < 0) - return error; - - lastdirent = buf.lrc_dirent; - if (lastdirent) - lastdirent->lld_off = file->f_pos; - - return 0; -} -EXPORT_SYMBOL(l_readdir); - -int l_notify_change(struct vfsmount *mnt, struct dentry *dchild, - struct iattr *newattrs) -{ - int rc; - - LOCK_INODE_MUTEX(dchild->d_inode); -#ifdef HAVE_SECURITY_PLUG - rc = notify_change(dchild, mnt, newattrs); -#else - rc = notify_change(dchild, newattrs); -#endif - UNLOCK_INODE_MUTEX(dchild->d_inode); - return rc; -} -EXPORT_SYMBOL(l_notify_change); - -/* utility to truncate a file */ -int simple_truncate(struct dentry *dir, struct vfsmount *mnt, - char *name, loff_t length) -{ - struct dentry *dchild; - struct iattr newattrs; - int err = 0; - ENTRY; - - CDEBUG(D_INODE, "truncating file %.*s to %lld\n", (int)strlen(name), - name, (long long)length); - dchild = ll_lookup_one_len(name, dir, strlen(name)); - if (IS_ERR(dchild)) - GOTO(out, err = PTR_ERR(dchild)); - - if (dchild->d_inode) { - int old_mode = dchild->d_inode->i_mode; - if (S_ISDIR(old_mode)) { - CERROR("found %s (%lu/%u) is mode %o\n", name, - dchild->d_inode->i_ino, - dchild->d_inode->i_generation, old_mode); - GOTO(out_dput, err = -EISDIR); - } - - newattrs.ia_size = length; - newattrs.ia_valid = ATTR_SIZE; - err = l_notify_change(mnt, dchild, &newattrs); - } - EXIT; -out_dput: - dput(dchild); -out: - return err; -} -EXPORT_SYMBOL(simple_truncate); - -#ifdef LUSTRE_KERNEL_VERSION -#ifndef HAVE_CLEAR_RDONLY_ON_PUT -#error rdonly patchset must be updated [cfs bz11248] -#endif -void dev_set_rdonly(lvfs_sbdev_type dev); -int dev_check_rdonly(lvfs_sbdev_type dev); - -void __lvfs_set_rdonly(lvfs_sbdev_type dev, lvfs_sbdev_type jdev) -{ - if (jdev && (jdev != dev)) { - CDEBUG(D_IOCTL | D_HA, "set journal dev %lx rdonly\n", - (long)jdev); - dev_set_rdonly(jdev); - } - CDEBUG(D_IOCTL | D_HA, "set dev %lx rdonly\n", (long)dev); - dev_set_rdonly(dev); -} - -int lvfs_check_rdonly(lvfs_sbdev_type dev) -{ - return dev_check_rdonly(dev); -} - -EXPORT_SYMBOL(__lvfs_set_rdonly); -EXPORT_SYMBOL(lvfs_check_rdonly); - -int lvfs_check_io_health(struct obd_device *obd, struct file *file) -{ - char *write_page = NULL; - loff_t offset = 0; - int rc = 0; - ENTRY; - - OBD_ALLOC(write_page, CFS_PAGE_SIZE); - if (!write_page) - RETURN(-ENOMEM); - - rc = fsfilt_write_record(obd, file, write_page, CFS_PAGE_SIZE, &offset, 1); - - OBD_FREE(write_page, CFS_PAGE_SIZE); - - CDEBUG(D_INFO, "write 1 page synchronously for checking io rc %d\n",rc); - RETURN(rc); -} -EXPORT_SYMBOL(lvfs_check_io_health); -#endif /* LUSTRE_KERNEL_VERSION */ - -void obd_update_maxusage() -{ - __u64 max1, max2; - - max1 = obd_pages_sum(); - max2 = obd_memory_sum(); - - cfs_spin_lock(&obd_updatemax_lock); - if (max1 > obd_max_pages) - obd_max_pages = max1; - if (max2 > obd_max_alloc) - obd_max_alloc = max2; - cfs_spin_unlock(&obd_updatemax_lock); - -} - -__u64 obd_memory_max(void) -{ - __u64 ret; - - cfs_spin_lock(&obd_updatemax_lock); - ret = obd_max_alloc; - cfs_spin_unlock(&obd_updatemax_lock); - - return ret; -} - -__u64 obd_pages_max(void) -{ - __u64 ret; - - cfs_spin_lock(&obd_updatemax_lock); - ret = obd_max_pages; - cfs_spin_unlock(&obd_updatemax_lock); - - return ret; -} - -EXPORT_SYMBOL(obd_update_maxusage); -EXPORT_SYMBOL(obd_pages_max); -EXPORT_SYMBOL(obd_memory_max); -EXPORT_SYMBOL(obd_memory); - #ifdef LPROCFS __s64 lprocfs_read_helper(struct lprocfs_counter *lc, - enum lprocfs_fields_flags field) + struct lprocfs_counter_header *header, + enum lprocfs_stats_flags flags, + enum lprocfs_fields_flags field) { - __s64 ret = 0; - int centry; - - if (!lc) - RETURN(0); - do { - centry = cfs_atomic_read(&lc->lc_cntl.la_entry); - - switch (field) { - case LPROCFS_FIELDS_FLAGS_CONFIG: - ret = lc->lc_config; - break; - case LPROCFS_FIELDS_FLAGS_SUM: - ret = lc->lc_sum + lc->lc_sum_irq; - break; - case LPROCFS_FIELDS_FLAGS_MIN: - ret = lc->lc_min; - break; - case LPROCFS_FIELDS_FLAGS_MAX: - ret = lc->lc_max; - break; - case LPROCFS_FIELDS_FLAGS_AVG: - ret = (lc->lc_max - lc->lc_min)/2; - break; - case LPROCFS_FIELDS_FLAGS_SUMSQUARE: - ret = lc->lc_sumsquare; - break; - case LPROCFS_FIELDS_FLAGS_COUNT: - ret = lc->lc_count; - break; - default: - break; - }; - } while (centry != cfs_atomic_read(&lc->lc_cntl.la_entry) && - centry != cfs_atomic_read(&lc->lc_cntl.la_exit)); - - RETURN(ret); + __s64 ret = 0; + + if (lc == NULL || header == NULL) + RETURN(0); + + switch (field) { + case LPROCFS_FIELDS_FLAGS_CONFIG: + ret = header->lc_config; + break; + case LPROCFS_FIELDS_FLAGS_SUM: + ret = lc->lc_sum; + if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) + ret += lc->lc_sum_irq; + break; + case LPROCFS_FIELDS_FLAGS_MIN: + ret = lc->lc_min; + break; + case LPROCFS_FIELDS_FLAGS_MAX: + ret = lc->lc_max; + break; + case LPROCFS_FIELDS_FLAGS_AVG: + ret = (lc->lc_max - lc->lc_min) / 2; + break; + case LPROCFS_FIELDS_FLAGS_SUMSQUARE: + ret = lc->lc_sumsquare; + break; + case LPROCFS_FIELDS_FLAGS_COUNT: + ret = lc->lc_count; + break; + default: + break; + }; + + RETURN(ret); } EXPORT_SYMBOL(lprocfs_read_helper); #endif /* LPROCFS */