mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 01:49:36 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull Ceph fixes from Sage Weil: "We have some patches fixing up ACL support issues from Zheng and Guangliang and a mount option to enable/disable this support. (These fixes were somewhat delayed by the Chinese holiday.) There is also a small fix for cached readdir handling when directories are fragmented" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: ceph: fix __dcache_readdir() ceph: add acl, noacl options for cephfs mount ceph: make ceph_forget_all_cached_acls() static inline ceph: add missing init_acl() for mkdir() and atomic_open() ceph: fix ceph_set_acl() ceph: fix ceph_removexattr() ceph: remove xattr when null value is given to setxattr() ceph: properly handle XATTR_CREATE and XATTR_REPLACE
This commit is contained in:
commit
87eeff7974
7 changed files with 96 additions and 37 deletions
|
@ -54,11 +54,6 @@ static inline struct posix_acl *ceph_get_cached_acl(struct inode *inode,
|
|||
return acl;
|
||||
}
|
||||
|
||||
void ceph_forget_all_cached_acls(struct inode *inode)
|
||||
{
|
||||
forget_all_cached_acls(inode);
|
||||
}
|
||||
|
||||
struct posix_acl *ceph_get_acl(struct inode *inode, int type)
|
||||
{
|
||||
int size;
|
||||
|
@ -160,11 +155,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
|
|||
goto out_dput;
|
||||
}
|
||||
|
||||
if (value)
|
||||
ret = __ceph_setxattr(dentry, name, value, size, 0);
|
||||
else
|
||||
ret = __ceph_removexattr(dentry, name);
|
||||
|
||||
ret = __ceph_setxattr(dentry, name, value, size, 0);
|
||||
if (ret) {
|
||||
if (new_mode != old_mode) {
|
||||
newattrs.ia_mode = old_mode;
|
||||
|
|
|
@ -100,6 +100,14 @@ static unsigned fpos_off(loff_t p)
|
|||
return p & 0xffffffff;
|
||||
}
|
||||
|
||||
static int fpos_cmp(loff_t l, loff_t r)
|
||||
{
|
||||
int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r));
|
||||
if (v)
|
||||
return v;
|
||||
return (int)(fpos_off(l) - fpos_off(r));
|
||||
}
|
||||
|
||||
/*
|
||||
* When possible, we try to satisfy a readdir by peeking at the
|
||||
* dcache. We make this work by carefully ordering dentries on
|
||||
|
@ -156,7 +164,7 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx)
|
|||
if (!d_unhashed(dentry) && dentry->d_inode &&
|
||||
ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
|
||||
ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
|
||||
ctx->pos <= di->offset)
|
||||
fpos_cmp(ctx->pos, di->offset) <= 0)
|
||||
break;
|
||||
dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry,
|
||||
dentry->d_name.len, dentry->d_name.name, di->offset,
|
||||
|
@ -695,9 +703,8 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
|
|||
ceph_mdsc_put_request(req);
|
||||
|
||||
if (!err)
|
||||
err = ceph_init_acl(dentry, dentry->d_inode, dir);
|
||||
|
||||
if (err)
|
||||
ceph_init_acl(dentry, dentry->d_inode, dir);
|
||||
else
|
||||
d_drop(dentry);
|
||||
return err;
|
||||
}
|
||||
|
@ -735,7 +742,9 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
|
|||
if (!err && !req->r_reply_info.head->is_dentry)
|
||||
err = ceph_handle_notrace_create(dir, dentry);
|
||||
ceph_mdsc_put_request(req);
|
||||
if (err)
|
||||
if (!err)
|
||||
ceph_init_acl(dentry, dentry->d_inode, dir);
|
||||
else
|
||||
d_drop(dentry);
|
||||
return err;
|
||||
}
|
||||
|
@ -776,7 +785,9 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
err = ceph_handle_notrace_create(dir, dentry);
|
||||
ceph_mdsc_put_request(req);
|
||||
out:
|
||||
if (err < 0)
|
||||
if (!err)
|
||||
ceph_init_acl(dentry, dentry->d_inode, dir);
|
||||
else
|
||||
d_drop(dentry);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -286,6 +286,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
|
|||
} else {
|
||||
dout("atomic_open finish_open on dn %p\n", dn);
|
||||
if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
|
||||
ceph_init_acl(dentry, dentry->d_inode, dir);
|
||||
*opened |= FILE_CREATED;
|
||||
}
|
||||
err = finish_open(file, dentry, ceph_open, opened);
|
||||
|
|
|
@ -144,7 +144,11 @@ enum {
|
|||
Opt_ino32,
|
||||
Opt_noino32,
|
||||
Opt_fscache,
|
||||
Opt_nofscache
|
||||
Opt_nofscache,
|
||||
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||
Opt_acl,
|
||||
#endif
|
||||
Opt_noacl
|
||||
};
|
||||
|
||||
static match_table_t fsopt_tokens = {
|
||||
|
@ -172,6 +176,10 @@ static match_table_t fsopt_tokens = {
|
|||
{Opt_noino32, "noino32"},
|
||||
{Opt_fscache, "fsc"},
|
||||
{Opt_nofscache, "nofsc"},
|
||||
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||
{Opt_acl, "acl"},
|
||||
#endif
|
||||
{Opt_noacl, "noacl"},
|
||||
{-1, NULL}
|
||||
};
|
||||
|
||||
|
@ -271,6 +279,14 @@ static int parse_fsopt_token(char *c, void *private)
|
|||
case Opt_nofscache:
|
||||
fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE;
|
||||
break;
|
||||
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||
case Opt_acl:
|
||||
fsopt->sb_flags |= MS_POSIXACL;
|
||||
break;
|
||||
#endif
|
||||
case Opt_noacl:
|
||||
fsopt->sb_flags &= ~MS_POSIXACL;
|
||||
break;
|
||||
default:
|
||||
BUG_ON(token);
|
||||
}
|
||||
|
@ -438,6 +454,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
|
|||
else
|
||||
seq_puts(m, ",nofsc");
|
||||
|
||||
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||
if (fsopt->sb_flags & MS_POSIXACL)
|
||||
seq_puts(m, ",acl");
|
||||
else
|
||||
seq_puts(m, ",noacl");
|
||||
#endif
|
||||
|
||||
if (fsopt->wsize)
|
||||
seq_printf(m, ",wsize=%d", fsopt->wsize);
|
||||
if (fsopt->rsize != CEPH_RSIZE_DEFAULT)
|
||||
|
@ -819,9 +842,6 @@ static int ceph_set_super(struct super_block *s, void *data)
|
|||
|
||||
s->s_flags = fsc->mount_options->sb_flags;
|
||||
s->s_maxbytes = 1ULL << 40; /* temp value until we get mdsmap */
|
||||
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||
s->s_flags |= MS_POSIXACL;
|
||||
#endif
|
||||
|
||||
s->s_xattr = ceph_xattr_handlers;
|
||||
s->s_fs_info = fsc;
|
||||
|
@ -911,6 +931,10 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
|
|||
struct ceph_options *opt = NULL;
|
||||
|
||||
dout("ceph_mount\n");
|
||||
|
||||
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||
flags |= MS_POSIXACL;
|
||||
#endif
|
||||
err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
|
||||
if (err < 0) {
|
||||
res = ERR_PTR(err);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/wait.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/posix_acl.h>
|
||||
|
||||
#include <linux/ceph/libceph.h>
|
||||
|
||||
|
@ -743,7 +744,11 @@ extern const struct xattr_handler *ceph_xattr_handlers[];
|
|||
struct posix_acl *ceph_get_acl(struct inode *, int);
|
||||
int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type);
|
||||
int ceph_init_acl(struct dentry *, struct inode *, struct inode *);
|
||||
void ceph_forget_all_cached_acls(struct inode *inode);
|
||||
|
||||
static inline void ceph_forget_all_cached_acls(struct inode *inode)
|
||||
{
|
||||
forget_all_cached_acls(inode);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#define XATTR_CEPH_PREFIX "ceph."
|
||||
#define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
|
||||
|
||||
static int __remove_xattr(struct ceph_inode_info *ci,
|
||||
struct ceph_inode_xattr *xattr);
|
||||
|
||||
/*
|
||||
* List of handlers for synthetic system.* attributes. Other
|
||||
* attributes are handled directly.
|
||||
|
@ -319,8 +322,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
|
|||
static int __set_xattr(struct ceph_inode_info *ci,
|
||||
const char *name, int name_len,
|
||||
const char *val, int val_len,
|
||||
int dirty,
|
||||
int should_free_name, int should_free_val,
|
||||
int flags, int update_xattr,
|
||||
struct ceph_inode_xattr **newxattr)
|
||||
{
|
||||
struct rb_node **p;
|
||||
|
@ -349,12 +351,31 @@ static int __set_xattr(struct ceph_inode_info *ci,
|
|||
xattr = NULL;
|
||||
}
|
||||
|
||||
if (update_xattr) {
|
||||
int err = 0;
|
||||
if (xattr && (flags & XATTR_CREATE))
|
||||
err = -EEXIST;
|
||||
else if (!xattr && (flags & XATTR_REPLACE))
|
||||
err = -ENODATA;
|
||||
if (err) {
|
||||
kfree(name);
|
||||
kfree(val);
|
||||
return err;
|
||||
}
|
||||
if (update_xattr < 0) {
|
||||
if (xattr)
|
||||
__remove_xattr(ci, xattr);
|
||||
kfree(name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xattr) {
|
||||
new = 1;
|
||||
xattr = *newxattr;
|
||||
xattr->name = name;
|
||||
xattr->name_len = name_len;
|
||||
xattr->should_free_name = should_free_name;
|
||||
xattr->should_free_name = update_xattr;
|
||||
|
||||
ci->i_xattrs.count++;
|
||||
dout("__set_xattr count=%d\n", ci->i_xattrs.count);
|
||||
|
@ -364,7 +385,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
|
|||
if (xattr->should_free_val)
|
||||
kfree((void *)xattr->val);
|
||||
|
||||
if (should_free_name) {
|
||||
if (update_xattr) {
|
||||
kfree((void *)name);
|
||||
name = xattr->name;
|
||||
}
|
||||
|
@ -379,8 +400,8 @@ static int __set_xattr(struct ceph_inode_info *ci,
|
|||
xattr->val = "";
|
||||
|
||||
xattr->val_len = val_len;
|
||||
xattr->dirty = dirty;
|
||||
xattr->should_free_val = (val && should_free_val);
|
||||
xattr->dirty = update_xattr;
|
||||
xattr->should_free_val = (val && update_xattr);
|
||||
|
||||
if (new) {
|
||||
rb_link_node(&xattr->node, parent, p);
|
||||
|
@ -442,7 +463,7 @@ static int __remove_xattr(struct ceph_inode_info *ci,
|
|||
struct ceph_inode_xattr *xattr)
|
||||
{
|
||||
if (!xattr)
|
||||
return -EOPNOTSUPP;
|
||||
return -ENODATA;
|
||||
|
||||
rb_erase(&xattr->node, &ci->i_xattrs.index);
|
||||
|
||||
|
@ -588,7 +609,7 @@ static int __build_xattrs(struct inode *inode)
|
|||
p += len;
|
||||
|
||||
err = __set_xattr(ci, name, namelen, val, len,
|
||||
0, 0, 0, &xattrs[numattr]);
|
||||
0, 0, &xattrs[numattr]);
|
||||
|
||||
if (err < 0)
|
||||
goto bad;
|
||||
|
@ -850,6 +871,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
|
|||
|
||||
dout("setxattr value=%.*s\n", (int)size, value);
|
||||
|
||||
if (!value)
|
||||
flags |= CEPH_XATTR_REMOVE;
|
||||
|
||||
/* do request */
|
||||
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR,
|
||||
USE_AUTH_MDS);
|
||||
|
@ -892,7 +916,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
|
|||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
int issued;
|
||||
int err;
|
||||
int dirty;
|
||||
int dirty = 0;
|
||||
int name_len = strlen(name);
|
||||
int val_len = size;
|
||||
char *newname = NULL;
|
||||
|
@ -953,12 +977,14 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
|
|||
goto retry;
|
||||
}
|
||||
|
||||
err = __set_xattr(ci, newname, name_len, newval,
|
||||
val_len, 1, 1, 1, &xattr);
|
||||
err = __set_xattr(ci, newname, name_len, newval, val_len,
|
||||
flags, value ? 1 : -1, &xattr);
|
||||
|
||||
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
|
||||
ci->i_xattrs.dirty = true;
|
||||
inode->i_ctime = CURRENT_TIME;
|
||||
if (!err) {
|
||||
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
|
||||
ci->i_xattrs.dirty = true;
|
||||
inode->i_ctime = CURRENT_TIME;
|
||||
}
|
||||
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
if (dirty)
|
||||
|
|
|
@ -373,8 +373,9 @@ extern const char *ceph_mds_op_name(int op);
|
|||
/*
|
||||
* Ceph setxattr request flags.
|
||||
*/
|
||||
#define CEPH_XATTR_CREATE 1
|
||||
#define CEPH_XATTR_REPLACE 2
|
||||
#define CEPH_XATTR_CREATE (1 << 0)
|
||||
#define CEPH_XATTR_REPLACE (1 << 1)
|
||||
#define CEPH_XATTR_REMOVE (1 << 31)
|
||||
|
||||
union ceph_mds_request_args {
|
||||
struct {
|
||||
|
|
Loading…
Reference in a new issue