From c3ad3dfcd0b90f82ee733e92c8335400beb86aa9 Mon Sep 17 00:00:00 2001 From: nathan Date: Sat, 2 Jul 2005 15:26:07 +0000 Subject: [PATCH] Branch b1_4 b=6931 r=adilger land flock support for b1_4 --- lustre/ChangeLog | 8 ++ lustre/include/linux/lustre_cfg.h | 3 +- lustre/llite/file.c | 16 ++++ lustre/llite/llite_internal.h | 3 + lustre/llite/llite_lib.c | 30 +++++- lustre/tests/flock.c | 196 ++++++++++++++++++++++++++++++++++++++ lustre/utils/llmount.c | 55 ++++++----- lustre/utils/module_setup.sh | 68 +++++++++++++ lustre/utils/rmmod_all.sh | 19 ++++ 9 files changed, 368 insertions(+), 30 deletions(-) create mode 100644 lustre/tests/flock.c create mode 100755 lustre/utils/module_setup.sh create mode 100755 lustre/utils/rmmod_all.sh diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 0fb9dff..db5aabb 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -65,6 +65,14 @@ Details : Processes doing readahead might match a lock that hasn't been (original lock is CBPENDING), while OST waits for that process to cancel CBPENDING read lock and eventually evicts client. +Severity : enhancement +Bugzilla : 6931 +Description: Provide flock support for clients +Details : Implement fcntl advisory locking and file status functions. + This feature is provided as an optional mount flag: + mount -t lustre -o [flock|noflock] ... + + ------------------------------------------------------------------------------ 2005-06-20 Cluster File Systems, Inc. diff --git a/lustre/include/linux/lustre_cfg.h b/lustre/include/linux/lustre_cfg.h index bfc66a4..b32f6f8 100644 --- a/lustre/include/linux/lustre_cfg.h +++ b/lustre/include/linux/lustre_cfg.h @@ -235,7 +235,7 @@ static inline int lustre_cfg_sanity_check(void *buf, int len) /* Passed by mount */ struct lustre_mount_data { uint32_t lmd_magic; - uint32_t lmd_version; + uint32_t lmd_flags; uint64_t lmd_local_nid; uint64_t lmd_server_nid; uint32_t lmd_nal; @@ -245,5 +245,6 @@ struct lustre_mount_data { char lmd_profile[64]; }; +#define LMD_FLG_FLOCK 0x0001 #endif // _LUSTRE_CFG_H diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 856079f..9487a59 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1550,6 +1550,22 @@ struct file_operations ll_file_operations = { /* .lock = ll_file_flock */ }; +struct file_operations ll_file_operations_flock = { + .read = ll_file_read, + .write = ll_file_write, + .ioctl = ll_file_ioctl, + .open = ll_file_open, + .release = ll_file_release, + .mmap = ll_file_mmap, + .llseek = ll_file_seek, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + .sendfile = generic_file_sendfile, +#endif + .fsync = ll_fsync, + .lock = ll_file_flock +}; + + struct inode_operations ll_file_inode_operations = { .setattr_raw = ll_setattr_raw, .setattr = ll_setattr, diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index dab0979..19ef784 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -119,6 +119,7 @@ struct ll_ra_info { /* flags for sbi->ll_flags */ #define LL_SBI_NOLCK 0x1 /* DLM locking disabled (directio-only) */ #define LL_SBI_CHECKSUM 0x2 /* checksum each page as it's written */ +#define LL_SBI_FLOCK 0x4 struct ll_sb_info { struct list_head ll_list; @@ -148,6 +149,7 @@ struct ll_sb_info { struct ll_ra_info ll_ra_info; unsigned int ll_namelen; + struct file_operations *ll_fop; }; struct ll_readahead_state { @@ -300,6 +302,7 @@ void ll_truncate(struct inode *inode); /* llite/file.c */ extern struct file_operations ll_file_operations; +extern struct file_operations ll_file_operations_flock; extern struct inode_operations ll_file_inode_operations; extern int ll_inode_revalidate_it(struct dentry *, struct lookup_intent *); int ll_extent_lock(struct ll_file_data *, struct inode *, diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 16ce609..4ba568b 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -157,6 +157,12 @@ int lustre_common_fill_super(struct super_block *sb, char *mdc, char *osc) if (sb->s_flags & MS_RDONLY) data->ocd_connect_flags |= OBD_CONNECT_RDONLY; + if (sbi->ll_flags & LL_SBI_FLOCK) { + sbi->ll_fop = &ll_file_operations_flock; + } else { + sbi->ll_fop = &ll_file_operations; + } + err = obd_connect(&mdc_conn, obd, &sbi->ll_sb_uuid, data); if (err == -EBUSY) { CERROR("An MDS (mdc %s) is performing recovery, of which this" @@ -401,6 +407,7 @@ int ll_set_opt(const char *opt, char *data, int fl) void ll_options(char *options, char **ost, char **mdc, int *flags) { + int tmp; char *this_char; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) char *opt_ptr = options; @@ -425,11 +432,21 @@ void ll_options(char *options, char **ost, char **mdc, int *flags) continue; if (!*mdc && (*mdc = ll_read_opt("mdc", this_char))) continue; - if (!(*flags & LL_SBI_NOLCK) && - ((*flags) = (*flags) | - ll_set_opt("nolock", this_char, - LL_SBI_NOLCK))) + tmp = ll_set_opt("nolock", this_char, LL_SBI_NOLCK); + if (tmp) { + *flags |= tmp; + continue; + } + tmp = ll_set_opt("flock", this_char, LL_SBI_FLOCK); + if (tmp) { + *flags |= tmp; + continue; + } + tmp = ll_set_opt("noflock", this_char, LL_SBI_FLOCK); + if (tmp) { + *flags &= ~tmp; continue; + } } EXIT; } @@ -720,6 +737,8 @@ int lustre_fill_super(struct super_block *sb, void *data, int silent) if (sbi->ll_lmd == NULL) GOTO(out_free, err = -ENOMEM); memcpy(sbi->ll_lmd, lmd, sizeof(*lmd)); + if (lmd->lmd_flags & LMD_FLG_FLOCK) + sbi->ll_flags |= LL_SBI_FLOCK; /* generate a string unique to this super, let's try the address of the super itself.*/ @@ -1289,8 +1308,9 @@ void ll_read_inode2(struct inode *inode, void *opaque) /* OIDEBUG(inode); */ if (S_ISREG(inode->i_mode)) { + struct ll_sb_info *sbi = ll_i2sbi(inode); inode->i_op = &ll_file_inode_operations; - inode->i_fop = &ll_file_operations; + inode->i_fop = sbi->ll_fop; inode->i_mapping->a_ops = &ll_aops; EXIT; } else if (S_ISDIR(inode->i_mode)) { diff --git a/lustre/tests/flock.c b/lustre/tests/flock.c new file mode 100644 index 0000000..83da7c5 --- /dev/null +++ b/lustre/tests/flock.c @@ -0,0 +1,196 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Lustre Light user test program + * + * Copyright (c) 2002, 2003 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define _BSD_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char lustre_path[] = "/mnt/lustre"; + +#define ENTRY(str) \ + do { \ + char buf[100]; \ + int len; \ + sprintf(buf, "===== START %s: %s ", __FUNCTION__, (str)); \ + len = strlen(buf); \ + if (len < 79) { \ + memset(buf+len, '=', 100-len); \ + buf[79] = '\n'; \ + buf[80] = 0; \ + } \ + printf("%s", buf); \ + } while (0) + +#define LEAVE() \ + do { \ + char buf[100]; \ + int len; \ + sprintf(buf, "===== END TEST %s: successfully ", \ + __FUNCTION__); \ + len = strlen(buf); \ + if (len < 79) { \ + memset(buf+len, '=', 100-len); \ + buf[79] = '\n'; \ + buf[80] = 0; \ + } \ + printf("%s", buf); \ + } while (0) + +#define EXIT return + +#define MAX_PATH_LENGTH 4096 + + +int t_fcntl(int fd, int cmd, ...) +{ + va_list ap; + long arg; + struct flock *lock; + int rc = -1; + + va_start(ap, cmd); + switch (cmd) { + case F_GETFL: + va_end(ap); + rc = fcntl(fd, cmd); + if (rc == -1) { + printf("fcntl GETFL failed: %s\n", + strerror(errno)); + EXIT(1); + } + break; + case F_SETFL: + arg = va_arg(ap, long); + va_end(ap); + rc = fcntl(fd, cmd, arg); + if (rc == -1) { + printf("fcntl SETFL %ld failed: %s\n", + arg, strerror(errno)); + EXIT(1); + } + break; + case F_GETLK: + case F_SETLK: + case F_SETLKW: + lock = va_arg(ap, struct flock *); + va_end(ap); + rc = fcntl(fd, cmd, lock); + if (rc == -1) { + printf("fcntl cmd %d failed: %s\n", + cmd, strerror(errno)); + EXIT(1); + } + break; + case F_DUPFD: + arg = va_arg(ap, long); + va_end(ap); + rc = fcntl(fd, cmd, arg); + if (rc == -1) { + printf("fcntl F_DUPFD %d failed: %s\n", + (int)arg, strerror(errno)); + EXIT(1); + } + break; + default: + va_end(ap); + printf("fcntl cmd %d not supported\n", cmd); + EXIT(1); + } + printf("fcntl %d = %d, ltype = %d\n", cmd, rc, lock->l_type); + return rc; +} + +int t_unlink(const char *path) +{ + int rc; + + rc = unlink(path); + if (rc) { + printf("unlink(%s) error: %s\n", path, strerror(errno)); + EXIT(-1); + } + return rc; +} + +void t21() +{ + char file[MAX_PATH_LENGTH] = ""; + int fd, ret; + struct flock lock = { + .l_type = F_RDLCK, + .l_whence = SEEK_SET, + }; + + ENTRY("basic fcntl support"); + snprintf(file, MAX_PATH_LENGTH, "%s/test_t21_file", lustre_path); + + fd = open(file, O_RDWR|O_CREAT, (mode_t)0666); + if (fd < 0) { + printf("error open file: %m\n", file); + exit(-1); + } + + t_fcntl(fd, F_SETFL, O_APPEND); + if (!(ret = t_fcntl(fd, F_GETFL)) & O_APPEND) { + printf("error get flag: ret %x\n", ret); + exit(-1); + } + + t_fcntl(fd, F_SETLK, &lock); + t_fcntl(fd, F_GETLK, &lock); + lock.l_type = F_WRLCK; + t_fcntl(fd, F_SETLKW, &lock); + t_fcntl(fd, F_GETLK, &lock); + lock.l_type = F_UNLCK; + t_fcntl(fd, F_SETLK, &lock); + + close(fd); + t_unlink(file); + LEAVE(); +} + + +int main(int argc, char * const argv[]) +{ + /* Set D_VFSTRACE to see messages from ll_file_flock. + The test passes either with -o flock or -o noflock + mount -o flock -t lustre uml1:/mds1/client /mnt/lustre */ + t21(); + + printf("completed successfully\n"); + return 0; +} diff --git a/lustre/utils/llmount.c b/lustre/utils/llmount.c index 131b480..0dac2ba 100644 --- a/lustre/utils/llmount.c +++ b/lustre/utils/llmount.c @@ -68,6 +68,7 @@ void usage(FILE *out) "\t-n|--nomtab: do not update /etc/mtab after mount\n" "\t-v|--verbose: print verbose config settings\n" "\t-o: filesystem mount options:\n" + "\t\tflock/noflock: enable/disable flock support\n" "\t\tnettype={tcp,elan,iibnal,lonal}: network type\n" "\t\tcluster_id=0xNNNN: cluster this node is part of\n" "\t\tlocal_nid=0xNNNN: client ID (default ipaddr or nodenum)\n" @@ -247,40 +248,46 @@ struct opt_map { const char *opt; /* option name */ int skip; /* skip in mtab option string */ int inv; /* true if flag value should be inverted */ - int mask; /* flag mask value */ + int ms_mask; /* MS flag mask value */ + int lmd_mask; /* LMD flag mask value */ }; static const struct opt_map opt_map[] = { - { "defaults", 0, 0, 0 }, /* default options */ - { "rw", 1, 1, MS_RDONLY }, /* read-write */ - { "ro", 0, 0, MS_RDONLY }, /* read-only */ - { "exec", 0, 1, MS_NOEXEC }, /* permit execution of binaries */ - { "noexec", 0, 0, MS_NOEXEC }, /* don't execute binaries */ - { "suid", 0, 1, MS_NOSUID }, /* honor suid executables */ - { "nosuid", 0, 0, MS_NOSUID }, /* don't honor suid executables */ - { "dev", 0, 1, MS_NODEV }, /* interpret device files */ - { "nodev", 0, 0, MS_NODEV }, /* don't interpret devices */ - { "async", 0, 1, MS_SYNCHRONOUS}, /* asynchronous I/O */ - { "auto", 0, 0, 0 }, /* Can be mounted using -a */ - { "noauto", 0, 0, 0 }, /* Can only be mounted explicitly */ - { "nousers", 0, 1, 0 }, /* Forbid ordinary user to mount */ - { "nouser", 0, 1, 0 }, /* Forbid ordinary user to mount */ - { "noowner", 0, 1, 0 }, /* Device owner has no special privs */ - { "_netdev", 0, 0, 0 }, /* Device accessible only via network */ - { NULL, 0, 0, 0 } + { "defaults", 0, 0, 0, 0 }, /* default options */ + { "rw", 1, 1, MS_RDONLY, 0 }, /* read-write */ + { "ro", 0, 0, MS_RDONLY, 0 }, /* read-only */ + { "exec", 0, 1, MS_NOEXEC, 0 }, /* permit execution of binaries */ + { "noexec", 0, 0, MS_NOEXEC, 0 }, /* don't execute binaries */ + { "suid", 0, 1, MS_NOSUID, 0 }, /* honor suid executables */ + { "nosuid", 0, 0, MS_NOSUID, 0 }, /* don't honor suid executables */ + { "dev", 0, 1, MS_NODEV, 0 }, /* interpret device files */ + { "nodev", 0, 0, MS_NODEV, 0 }, /* don't interpret devices */ + { "async", 0, 1, MS_SYNCHRONOUS, 0}, /* asynchronous I/O */ + { "auto", 0, 0, 0, 0 }, /* Can be mounted using -a */ + { "noauto", 0, 0, 0, 0 }, /* Can only be mounted explicitly */ + { "nousers", 0, 1, 0, 0 }, /* Forbid ordinary user to mount */ + { "nouser", 0, 1, 0, 0 }, /* Forbid ordinary user to mount */ + { "noowner", 0, 1, 0, 0 }, /* Device owner has no special privs */ + { "_netdev", 0, 0, 0, 0 }, /* Device accessible only via network */ + { "flock", 0, 0, 0, LMD_FLG_FLOCK}, /* Enable flock support */ + { "noflock", 1, 1, 0, LMD_FLG_FLOCK}, /* Disable flock support */ + { NULL, 0, 0, 0, 0 } }; /****************************************************************************/ -static int parse_one_option(const char *check, int *flagp) +static int parse_one_option(const char *check, int *ms_flags, int *lmd_flags) { const struct opt_map *opt; for (opt = &opt_map[0]; opt->opt != NULL; opt++) { if (strcmp(check, opt->opt) == 0) { - if (opt->inv) - *flagp &= ~(opt->mask); - else - *flagp |= opt->mask; + if (opt->inv) { + *ms_flags &= ~(opt->ms_mask); + *lmd_flags &= ~(opt->lmd_mask); + } else { + *ms_flags |= opt->ms_mask; + *lmd_flags |= opt->lmd_mask; + } return 1; } } @@ -349,7 +356,7 @@ int parse_options(char *options, struct lustre_mount_data *lmd, int *flagp) usage(stderr); } } else { - if (parse_one_option(opt, flagp)) + if (parse_one_option(opt, flagp, &lmd->lmd_flags)) continue; fprintf(stderr, "%s: unknown option '%s'\n", diff --git a/lustre/utils/module_setup.sh b/lustre/utils/module_setup.sh new file mode 100755 index 0000000..79e41dc --- /dev/null +++ b/lustre/utils/module_setup.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +MDIR=/lib/modules/`uname -r`/lustre + +KVER=24 +EXT=o +FSFLT=fsfilt_ext3 +MODFILE="/etc/modules.conf" +if [ `uname -r | cut -c 3` -eq 6 ]; then + KVER=26 + EXT=ko + FSFLT=fsfilt_ldiskfs + MODFILE="/etc/modprobe.conf" +fi + +echo "Copying modules from local build dir to "$MDIR + +mkdir -p $MDIR + +cp ../../portals/libcfs/libcfs.$EXT $MDIR +cp ../../portals/portals/portals.$EXT $MDIR +cp ../../portals/knals/socknal/ksocknal.$EXT $MDIR +cp ../lvfs/lvfs.$EXT $MDIR +cp ../obdclass/obdclass.$EXT $MDIR +cp ../ptlrpc/ptlrpc.$EXT $MDIR +#cp ../obdclass/confobd.$EXT $MDIR +cp ../mdc/mdc.$EXT $MDIR +cp ../osc/osc.$EXT $MDIR +cp ../lov/lov.$EXT $MDIR +cp ../mds/mds.$EXT $MDIR +cp ../lvfs/$FSFLT.$EXT $MDIR +[ $KVER == "26" ] && cp ../ldiskfs/ldiskfs.$EXT $MDIR +cp ../ost/ost.$EXT $MDIR +cp ../obdfilter/obdfilter.$EXT $MDIR +cp ../llite/llite.$EXT $MDIR + +# prevent warnings on my uml +rm -f /lib/modules/`uname -r`/modules.* +echo "Depmod" +depmod -a -e + +echo "Copying mount and acceptor from local build dir to "$MDIR +cp ../../portals/utils/acceptor /sbin/. +cp ../utils/mount.lustre /sbin/. + +if [ `grep -c lustre $MODFILE` -eq 0 ]; then + echo Modifying $MODFILE + echo "# Lustre modules added by $0" >> $MODFILE + if [ $KVER -eq 24 ]; then + echo alias lustre null >> $MODFILE + echo above lustre llite osc mdc >> $MODFILE + echo above mds llite confobd osc >> $MODFILE + echo alias oss ost >> $MODFILE + echo above ost llite confobd obdfilter >> $MODFILE + echo above confobd $FSFLT >> $MODFILE + echo below ptlrpc ksocknal >> $MODFILE + else + MP="/sbin/modprobe" + MPI="$MP --ignore-install" + echo "install ptlrpc $MP ksocknal && $MPI ptlrpc" >> $MODFILE + echo "install confobd $MP $FSFLT && $MPI confobd" >> $MODFILE + echo "install ost $MP llite confobd obdfilter && $MPI ost" >> $MODFILE + echo "install oss $MP ost && $MPI oss" >> $MODFILE + echo "install mds $MP llite confobd osc && $MPI mds" >> $MODFILE + echo "install lustre $MP llite osc mdc" >> $MODFILE + fi + echo "# end Lustre modules" >> $MODFILE +fi diff --git a/lustre/utils/rmmod_all.sh b/lustre/utils/rmmod_all.sh new file mode 100755 index 0000000..4e9376a --- /dev/null +++ b/lustre/utils/rmmod_all.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +rmmod llite +rmmod mdc +rmmod lov +rmmod osc +rmmod confobd +rmmod obdfilter +rmmod fsfilt_ext3 +rmmod fsfilt_ldiskfs +rmmod ldiskfs +rmmod ost +rmmod mds +rmmod ptlrpc +rmmod obdclass +rmmod lvfs +rmmod ksocknal +rmmod portals +rmmod libcfs -- 1.8.3.1