未验证 提交 b5d0cd88 编写于 作者: D Davies Liu 提交者: GitHub

support read-only mode (#520)

* support read-only mode

* fix build and update docs

* fix json tag
上级 69b05e0a
......@@ -143,8 +143,9 @@ func (g *GateWay) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, er
c := g.ctx
addr := c.Args().Get(0)
m := meta.NewClient(addr, &meta.Config{
Retries: 10,
Strict: true,
Retries: 10,
Strict: true,
ReadOnly: c.Bool("read-only"),
})
format, err := m.Load()
if err != nil {
......
......@@ -84,10 +84,17 @@ func mount(c *cli.Context) error {
logger.Fatalf("create %s: %s", mp, err)
}
}
var readOnly = c.Bool("read-only")
for _, o := range strings.Split(c.String("o"), ",") {
if o == "ro" {
readOnly = true
}
}
m := meta.NewClient(addr, &meta.Config{
Retries: 10,
Strict: true,
CaseInsensi: strings.HasSuffix(mp, ":") && runtime.GOOS == "windows",
ReadOnly: readOnly,
MountPoint: mp,
})
format, err := m.Load()
......
......@@ -109,6 +109,10 @@ func mount_flags() []cli.Flag {
Name: "enable-xattr",
Usage: "enable extended attributes (xattr)",
},
&cli.BoolFlag{
Name: "read-only",
Usage: "allow lookup/read operations only",
},
}
}
......
......@@ -143,6 +143,9 @@ dir entry cache timeout in seconds (default: 1)
`--enable-xattr`\
enable extended attributes (xattr) (default: false)
`--read-only`\
allow lookup/read operations only (default: false)
`--get-timeout value`\
the max number of seconds to download an object (default: 60)
......
......@@ -145,6 +145,9 @@ dir entry cache timeout in seconds (default: 1)
`--enable-xattr`\
enable extended attributes (xattr) (default: false)
`--read-only`\
allow lookup/read operations only (default: false)
`--get-timeout value`\
the max number of seconds to download an object (default: 60)
......
......@@ -263,7 +263,13 @@ func (fs *FileSystem) Open(ctx meta.Context, path string, flags uint32) (f *File
if err != 0 {
return nil, err
}
err = fs.m.Open(ctx, fi.inode, uint8(flags), nil)
var oflags uint32 = syscall.O_RDONLY
if flags == vfs.MODE_MASK_W {
oflags = syscall.O_WRONLY
} else if flags&vfs.MODE_MASK_W != 0 {
oflags = syscall.O_RDWR
}
err = fs.m.Open(ctx, fi.inode, oflags, nil)
if err != 0 {
return
}
......
......@@ -20,6 +20,7 @@ type Config struct {
Strict bool // update ctime
Retries int
CaseInsensi bool
ReadOnly bool
MountPoint string
}
......
......@@ -265,7 +265,7 @@ type Meta interface {
// Create creates a file in a directory with given name.
Create(ctx Context, parent Ino, name string, mode uint16, cumask uint16, inode *Ino, attr *Attr) syscall.Errno
// Open checks permission on a node and track it as open.
Open(ctx Context, inode Ino, flags uint8, attr *Attr) syscall.Errno
Open(ctx Context, inode Ino, flags uint32, attr *Attr) syscall.Errno
// Close a file.
Close(ctx Context, inode Ino) syscall.Errno
// Read returns the list of slices on the given chunk.
......
......@@ -243,6 +243,9 @@ func (r *redisMeta) Load() (*Format, error) {
}
func (r *redisMeta) NewSession() error {
if r.conf.ReadOnly {
return nil
}
var err error
r.sid, err = r.rdb.Incr(Background, "nextsession").Result()
if err != nil {
......@@ -852,6 +855,9 @@ func shouldRetry(err error, retryOnFailure bool) bool {
}
func (r *redisMeta) txn(ctx Context, txf func(tx *redis.Tx) error, keys ...string) syscall.Errno {
if r.conf.ReadOnly {
return syscall.EROFS
}
var err error
var khash = fnv.New32()
_, _ = khash.Write([]byte(keys[0]))
......@@ -1902,11 +1908,14 @@ func (r *redisMeta) deleteInode(inode Ino) error {
return err
}
func (r *redisMeta) Open(ctx Context, inode Ino, flags uint8, attr *Attr) syscall.Errno {
func (r *redisMeta) Open(ctx Context, inode Ino, flags uint32, attr *Attr) syscall.Errno {
var err syscall.Errno
if attr != nil {
err = r.GetAttr(ctx, inode, attr)
}
if r.conf.ReadOnly && flags&(syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC|syscall.O_APPEND) != 0 {
return syscall.EROFS
}
if err == 0 {
r.Lock()
r.openFiles[inode] = r.openFiles[inode] + 1
......@@ -1965,7 +1974,7 @@ func (r *redisMeta) Read(ctx Context, inode Ino, indx uint32, chunks *[]Slice) s
}
ss := readSlices(vals)
*chunks = buildSlice(ss)
if len(vals) >= 5 || len(*chunks) >= 5 {
if !r.conf.ReadOnly && (len(vals) >= 5 || len(*chunks) >= 5) {
go r.compactChunk(inode, indx, false)
}
return 0
......
......@@ -285,6 +285,9 @@ func (m *dbMeta) NewSession() error {
if err := m.engine.Sync2(new(session)); err != nil { // old client has no info field
return err
}
if m.conf.ReadOnly {
return nil
}
v, err := m.incrCounter("nextSession", 1)
if err != nil {
return fmt.Errorf("create session: %s", err)
......@@ -484,6 +487,9 @@ func (m *dbMeta) shouldRetry(err error) bool {
}
func (m *dbMeta) txn(f func(s *xorm.Session) error) error {
if m.conf.ReadOnly {
return syscall.EROFS
}
start := time.Now()
defer func() { txDist.Observe(time.Since(start).Seconds()) }()
var err error
......@@ -1665,11 +1671,14 @@ func (m *dbMeta) deleteInode(inode Ino) error {
return err
}
func (m *dbMeta) Open(ctx Context, inode Ino, flags uint8, attr *Attr) syscall.Errno {
func (m *dbMeta) Open(ctx Context, inode Ino, flags uint32, attr *Attr) syscall.Errno {
var err syscall.Errno
if attr != nil {
err = m.GetAttr(ctx, inode, attr)
}
if m.conf.ReadOnly && flags&(syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC|syscall.O_APPEND) != 0 {
return syscall.EROFS
}
if err == 0 {
m.Lock()
m.openFiles[inode] = m.openFiles[inode] + 1
......@@ -1709,7 +1718,7 @@ func (m *dbMeta) Read(ctx Context, inode Ino, indx uint32, chunks *[]Slice) sysc
}
ss := readSliceBuf(c.Slices)
*chunks = buildSlice(ss)
if len(c.Slices)/sliceBytes >= 5 || len(*chunks) >= 5 {
if !m.conf.ReadOnly && (len(c.Slices)/sliceBytes >= 5 || len(*chunks) >= 5) {
go m.compactChunk(inode, indx, false)
}
return 0
......
......@@ -94,7 +94,7 @@ func resolve(p string, inode *Ino, attr *Attr) syscall.Errno {
break
}
if i > 0 {
if err = m.Access(ctx, parent, 1, attr); err != 0 {
if err = m.Access(ctx, parent, MODE_MASK_R|MODE_MASK_X, attr); err != 0 {
return err
}
}
......
......@@ -23,6 +23,12 @@ import (
"github.com/juicedata/juicefs/pkg/meta"
)
const (
MODE_MASK_R = 4
MODE_MASK_W = 2
MODE_MASK_X = 1
)
func strerr(errno syscall.Errno) string {
if errno == 0 {
return "OK"
......
......@@ -412,7 +412,7 @@ func Open(ctx Context, ino Ino, flags uint32) (entry *meta.Entry, fh uint64, err
return
}
err = m.Open(ctx, ino, uint8(flags), attr)
err = m.Open(ctx, ino, flags, attr)
if err != 0 {
return
}
......
......@@ -31,12 +31,6 @@ import (
const O_ACCMODE = syscall.O_ACCMODE
const F_UNLCK = syscall.F_UNLCK
const (
MODE_MASK_R = 4
MODE_MASK_W = 2
MODE_MASK_X = 1
)
type Statfs struct {
Bsize uint32
Blocks uint64
......
......@@ -214,6 +214,7 @@ func freeHandle(fd int) {
type javaConf struct {
MetaURL string `json:"meta"`
ReadOnly bool `json:"readOnly"`
CacheDir string `json:"cacheDir"`
CacheSize int64 `json:"cacheSize"`
FreeSpace string `json:"freeSpace"`
......@@ -313,7 +314,7 @@ func jfs_init(cname, jsonConf, user, group, superuser, supergroup *C.char) uintp
utils.InitLoggers(false)
addr := jConf.MetaURL
m := meta.NewClient(addr, &meta.Config{Retries: 10, Strict: true})
m := meta.NewClient(addr, &meta.Config{Retries: 10, Strict: true, ReadOnly: jConf.ReadOnly})
format, err := m.Load()
if err != nil {
logger.Fatalf("load setting: %s", err)
......
......@@ -310,6 +310,7 @@ public class JuiceFileSystemImpl extends FileSystem {
for (String key : bkeys) {
obj.put(key, Boolean.valueOf(getConf(conf, key, "false")));
}
obj.put("readOnly", Boolean.valueOf(getConf(conf, "read-only", "false")));
obj.put("cacheDir", getConf(conf, "cache-dir", "memory"));
obj.put("cacheSize", Integer.valueOf(getConf(conf, "cache-size", "100")));
obj.put("cacheFullBlock", Boolean.valueOf(getConf(conf, "cache-full-block", "true")));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册