/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
- * convert quota format.
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
*
- * from
- * linux/fs/quota_v2.c
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/lvfs/lustre_quota_fmt_convert.c
+ *
+ * convert quota format.
+ * from linux/fs/quota_v2.c
*/
#ifndef EXPORT_SYMTAB
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/quotaio_v1.h>
+#ifdef HAVE_QUOTAIO_V1_H
+# include <linux/quotaio_v1.h>
+#endif
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#include <obd_support.h>
#include "lustre_quota_fmt.h"
+#ifdef HAVE_QUOTA_SUPPORT
+
static int admin_convert_dqinfo(struct file *fp_v1, struct file *fp_v2,
struct lustre_quota_info *lqi, int type)
{
return rc;
}
-static int admin_convert_v1_to_v2(struct file *fp_v1, struct file *fp_v2,
+static int quota_convert_v1_to_v2(struct file *fp_v1, struct file *fp_v2,
struct lustre_quota_info *lqi, int type)
{
struct list_head blk_list;
struct lustre_disk_dqblk fakedquot;
memset(buf, 0, LUSTRE_DQBLKSIZE);
- if ((ret = quota_read(fp_v1, NULL, type, blk_item->blk, buf))<0) {
+
+ if ((ret = lustre_read_quota(fp_v1, NULL, type, buf, LUSTRE_DQBLKSIZE,
+ blk_item->blk << LUSTRE_DQBLKSIZE_BITS)) < 0) {
CERROR("VFS: Can't read quota tree block %u.\n",
blk_item->blk);
GOTO(out_free, rc = ret);
f_v1 = filp_open(name, O_RDONLY, 0);
if (!IS_ERR(f_v1)) {
if (!check_quota_file(f_v1, NULL, type, LUSTRE_QUOTA_V1)) {
- rc = admin_convert_v1_to_v2(f_v1, f_v2, lqi, type);
+ rc = quota_convert_v1_to_v2(f_v1, f_v2, lqi, type);
if (rc)
CERROR("failed to convert v1 quota file"
" to v2 quota file.\n");
RETURN(rc);
}
-
EXPORT_SYMBOL(lustre_quota_convert);
+
+#ifdef HAVE_QUOTA64
+/*
+ * convert operational quota files to the requested version
+ * returns: -ESTALE if upgrading to qfmt version is not supported
+ * -ENOMEM if memory was not allocated for conv. structures
+ *
+ * other error codes can be returned by VFS and have the
+ * appropriate meaning
+ */
+int lustre_slave_quota_convert(lustre_quota_version_t qfmt, int type)
+{
+ struct lustre_quota_info *lqi;
+ struct file *f_v1, *f_v2;
+ const char *name[][MAXQUOTAS] = LUSTRE_OPQFILES_NAMES;
+ int rc;
+
+ ENTRY;
+
+ /* we convert only to v2 version */
+ if (qfmt != LUSTRE_QUOTA_V2)
+ GOTO(out, rc = -ESTALE);
+
+ OBD_ALLOC_PTR(lqi);
+ if (lqi == NULL)
+ GOTO(out, rc = -ENOMEM);
+
+ /* now that we support only v1 and v2 formats,
+ * only upgrade from v1 is possible,
+ * let's check if v1 file exists so that we convert it to v2 */
+ f_v1 = filp_open(name[LUSTRE_QUOTA_V1][type], O_RDONLY, 0);
+ if (IS_ERR(f_v1))
+ GOTO(out_free, rc = PTR_ERR(f_v1));
+
+ /* make sure it is really a v1 file */
+ if (check_quota_file(f_v1, NULL, type, LUSTRE_QUOTA_V1))
+ GOTO(out_f_v1, rc = -EINVAL);
+
+ /* create new quota file for v2 version, follow the same rationale as
+ * mds_admin_quota_on: if the file already exists, then do not try to
+ * overwrite it, user has to fix the quotaon issue manually,
+ * e.g. through running quotacheck */
+ f_v2 = filp_open(name[LUSTRE_QUOTA_V2][type],
+ O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0644);
+ if (IS_ERR(f_v2))
+ GOTO(out_f_v1, rc = PTR_ERR(f_v2));
+
+ lqi->qi_version = LUSTRE_QUOTA_V2;
+ lqi->qi_files[type] = f_v2;
+
+ /* initialize quota file with defaults, marking it invalid,
+ * this will help us not to get confused with partially converted
+ * operational quota files if we crash during conversion */
+ rc = lustre_init_quota_info_generic(lqi, type, 1);
+ if (rc)
+ GOTO(out_f_v2, rc);
+
+ rc = quota_convert_v1_to_v2(f_v1, f_v2, lqi, type);
+ if (!rc) {
+ /* we dont want good magic to store before the quota data,
+ * just to be safe if ldiskfs is running in writeback mode */
+ LOCK_INODE_MUTEX(f_v2->f_dentry->d_inode);
+ rc = lustre_fsync(f_v2);
+ if (rc)
+ CERROR("error from fsync, rc=%d\n", rc);
+ UNLOCK_INODE_MUTEX(f_v2->f_dentry->d_inode);
+
+ /* now that conversion successfully finished we mark
+ * this operational quota file with the correct magic,
+ * since this moment quotaon will treat it as a correct
+ * quota file */
+ rc = lustre_init_quota_header(lqi, type, 0);
+ }
+
+ EXIT;
+
+out_f_v2:
+ filp_close(f_v2, 0);
+out_f_v1:
+ filp_close(f_v1, 0);
+out_free:
+ OBD_FREE_PTR(lqi);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(lustre_slave_quota_convert);
+#endif /* HAVE_QUOTA64 */
+#endif /* HAVE_QUOTA_SUPPORT */