提交 56b59b42 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client

Pull Ceph updates for 3.4-rc1 from Sage Weil:
 "Alex has been busy.  There are a range of rbd and libceph cleanups,
  especially surrounding device setup and teardown, and a few critical
  fixes in that code.  There are more cleanups in the messenger code,
  virtual xattrs, a fix for CRC calculation/checks, and lots of other
  miscellaneous stuff.

  There's a patch from Amon Ott to make inos behave a bit better on
  32-bit boxes, some decode check fixes from Xi Wang, and network
  throttling fix from Jim Schutt, and a couple RBD fixes from Josh
  Durgin.

  No new functionality, just a lot of cleanup and bug fixing."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: (65 commits)
  rbd: move snap_rwsem to the device, rename to header_rwsem
  ceph: fix three bugs, two in ceph_vxattrcb_file_layout()
  libceph: isolate kmap() call in write_partial_msg_pages()
  libceph: rename "page_shift" variable to something sensible
  libceph: get rid of zero_page_address
  libceph: only call kernel_sendpage() via helper
  libceph: use kernel_sendpage() for sending zeroes
  libceph: fix inverted crc option logic
  libceph: some simple changes
  libceph: small refactor in write_partial_kvec()
  libceph: do crc calculations outside loop
  libceph: separate CRC calculation from byte swapping
  libceph: use "do" in CRC-related Boolean variables
  ceph: ensure Boolean options support both senses
  libceph: a few small changes
  libceph: make ceph_tcp_connect() return int
  libceph: encapsulate some messenger cleanup code
  libceph: make ceph_msgr_wq private
  libceph: encapsulate connection kvec operations
  libceph: move prepare_write_banner()
  ...
此差异已折叠。
...@@ -41,10 +41,6 @@ ...@@ -41,10 +41,6 @@
#define RBD_HEADER_SIGNATURE "RBD" #define RBD_HEADER_SIGNATURE "RBD"
#define RBD_HEADER_VERSION "001.005" #define RBD_HEADER_VERSION "001.005"
struct rbd_info {
__le64 max_id;
} __attribute__ ((packed));
struct rbd_image_snap_ondisk { struct rbd_image_snap_ondisk {
__le64 id; __le64 id;
__le64 image_size; __le64 image_size;
......
...@@ -677,18 +677,19 @@ static int fill_inode(struct inode *inode, ...@@ -677,18 +677,19 @@ static int fill_inode(struct inode *inode,
case S_IFLNK: case S_IFLNK:
inode->i_op = &ceph_symlink_iops; inode->i_op = &ceph_symlink_iops;
if (!ci->i_symlink) { if (!ci->i_symlink) {
int symlen = iinfo->symlink_len; u32 symlen = iinfo->symlink_len;
char *sym; char *sym;
BUG_ON(symlen != inode->i_size);
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
err = -EINVAL;
if (WARN_ON(symlen != inode->i_size))
goto out;
err = -ENOMEM; err = -ENOMEM;
sym = kmalloc(symlen+1, GFP_NOFS); sym = kstrndup(iinfo->symlink, symlen, GFP_NOFS);
if (!sym) if (!sym)
goto out; goto out;
memcpy(sym, iinfo->symlink, symlen);
sym[symlen] = 0;
spin_lock(&ci->i_ceph_lock); spin_lock(&ci->i_ceph_lock);
if (!ci->i_symlink) if (!ci->i_symlink)
......
...@@ -402,7 +402,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, ...@@ -402,7 +402,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
spin_lock_init(&s->s_gen_ttl_lock); spin_lock_init(&s->s_gen_ttl_lock);
s->s_cap_gen = 0; s->s_cap_gen = 0;
s->s_cap_ttl = 0; s->s_cap_ttl = jiffies - 1;
spin_lock_init(&s->s_cap_lock); spin_lock_init(&s->s_cap_lock);
s->s_renew_requested = 0; s->s_renew_requested = 0;
...@@ -1083,8 +1083,7 @@ static void renewed_caps(struct ceph_mds_client *mdsc, ...@@ -1083,8 +1083,7 @@ static void renewed_caps(struct ceph_mds_client *mdsc,
int wake = 0; int wake = 0;
spin_lock(&session->s_cap_lock); spin_lock(&session->s_cap_lock);
was_stale = is_renew && (session->s_cap_ttl == 0 || was_stale = is_renew && time_after_eq(jiffies, session->s_cap_ttl);
time_after_eq(jiffies, session->s_cap_ttl));
session->s_cap_ttl = session->s_renew_requested + session->s_cap_ttl = session->s_renew_requested +
mdsc->mdsmap->m_session_timeout*HZ; mdsc->mdsmap->m_session_timeout*HZ;
...@@ -2332,7 +2331,7 @@ static void handle_session(struct ceph_mds_session *session, ...@@ -2332,7 +2331,7 @@ static void handle_session(struct ceph_mds_session *session,
session->s_mds); session->s_mds);
spin_lock(&session->s_gen_ttl_lock); spin_lock(&session->s_gen_ttl_lock);
session->s_cap_gen++; session->s_cap_gen++;
session->s_cap_ttl = 0; session->s_cap_ttl = jiffies - 1;
spin_unlock(&session->s_gen_ttl_lock); spin_unlock(&session->s_gen_ttl_lock);
send_renew_caps(mdsc, session); send_renew_caps(mdsc, session);
break; break;
......
...@@ -331,7 +331,7 @@ static int build_snap_context(struct ceph_snap_realm *realm) ...@@ -331,7 +331,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
/* alloc new snap context */ /* alloc new snap context */
err = -ENOMEM; err = -ENOMEM;
if (num > ULONG_MAX / sizeof(u64) - sizeof(*snapc)) if (num > (ULONG_MAX - sizeof(*snapc)) / sizeof(u64))
goto fail; goto fail;
snapc = kzalloc(sizeof(*snapc) + num*sizeof(u64), GFP_NOFS); snapc = kzalloc(sizeof(*snapc) + num*sizeof(u64), GFP_NOFS);
if (!snapc) if (!snapc)
......
...@@ -130,10 +130,12 @@ enum { ...@@ -130,10 +130,12 @@ enum {
Opt_nodirstat, Opt_nodirstat,
Opt_rbytes, Opt_rbytes,
Opt_norbytes, Opt_norbytes,
Opt_asyncreaddir,
Opt_noasyncreaddir, Opt_noasyncreaddir,
Opt_dcache, Opt_dcache,
Opt_nodcache, Opt_nodcache,
Opt_ino32, Opt_ino32,
Opt_noino32,
}; };
static match_table_t fsopt_tokens = { static match_table_t fsopt_tokens = {
...@@ -153,10 +155,12 @@ static match_table_t fsopt_tokens = { ...@@ -153,10 +155,12 @@ static match_table_t fsopt_tokens = {
{Opt_nodirstat, "nodirstat"}, {Opt_nodirstat, "nodirstat"},
{Opt_rbytes, "rbytes"}, {Opt_rbytes, "rbytes"},
{Opt_norbytes, "norbytes"}, {Opt_norbytes, "norbytes"},
{Opt_asyncreaddir, "asyncreaddir"},
{Opt_noasyncreaddir, "noasyncreaddir"}, {Opt_noasyncreaddir, "noasyncreaddir"},
{Opt_dcache, "dcache"}, {Opt_dcache, "dcache"},
{Opt_nodcache, "nodcache"}, {Opt_nodcache, "nodcache"},
{Opt_ino32, "ino32"}, {Opt_ino32, "ino32"},
{Opt_noino32, "noino32"},
{-1, NULL} {-1, NULL}
}; };
...@@ -232,6 +236,9 @@ static int parse_fsopt_token(char *c, void *private) ...@@ -232,6 +236,9 @@ static int parse_fsopt_token(char *c, void *private)
case Opt_norbytes: case Opt_norbytes:
fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES; fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES;
break; break;
case Opt_asyncreaddir:
fsopt->flags &= ~CEPH_MOUNT_OPT_NOASYNCREADDIR;
break;
case Opt_noasyncreaddir: case Opt_noasyncreaddir:
fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR; fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
break; break;
...@@ -244,6 +251,9 @@ static int parse_fsopt_token(char *c, void *private) ...@@ -244,6 +251,9 @@ static int parse_fsopt_token(char *c, void *private)
case Opt_ino32: case Opt_ino32:
fsopt->flags |= CEPH_MOUNT_OPT_INO32; fsopt->flags |= CEPH_MOUNT_OPT_INO32;
break; break;
case Opt_noino32:
fsopt->flags &= ~CEPH_MOUNT_OPT_INO32;
break;
default: default:
BUG_ON(token); BUG_ON(token);
} }
...@@ -334,10 +344,12 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt, ...@@ -334,10 +344,12 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt,
*path += 2; *path += 2;
dout("server path '%s'\n", *path); dout("server path '%s'\n", *path);
err = ceph_parse_options(popt, options, dev_name, dev_name_end, *popt = ceph_parse_options(options, dev_name, dev_name_end,
parse_fsopt_token, (void *)fsopt); parse_fsopt_token, (void *)fsopt);
if (err) if (IS_ERR(*popt)) {
err = PTR_ERR(*popt);
goto out; goto out;
}
/* success */ /* success */
*pfsopt = fsopt; *pfsopt = fsopt;
...@@ -926,6 +938,7 @@ static int __init init_ceph(void) ...@@ -926,6 +938,7 @@ static int __init init_ceph(void)
if (ret) if (ret)
goto out; goto out;
ceph_xattr_init();
ret = register_filesystem(&ceph_fs_type); ret = register_filesystem(&ceph_fs_type);
if (ret) if (ret)
goto out_icache; goto out_icache;
...@@ -935,6 +948,7 @@ static int __init init_ceph(void) ...@@ -935,6 +948,7 @@ static int __init init_ceph(void)
return 0; return 0;
out_icache: out_icache:
ceph_xattr_exit();
destroy_caches(); destroy_caches();
out: out:
return ret; return ret;
...@@ -944,6 +958,7 @@ static void __exit exit_ceph(void) ...@@ -944,6 +958,7 @@ static void __exit exit_ceph(void)
{ {
dout("exit_ceph\n"); dout("exit_ceph\n");
unregister_filesystem(&ceph_fs_type); unregister_filesystem(&ceph_fs_type);
ceph_xattr_exit();
destroy_caches(); destroy_caches();
} }
......
...@@ -367,7 +367,7 @@ static inline u32 ceph_ino_to_ino32(__u64 vino) ...@@ -367,7 +367,7 @@ static inline u32 ceph_ino_to_ino32(__u64 vino)
u32 ino = vino & 0xffffffff; u32 ino = vino & 0xffffffff;
ino ^= vino >> 32; ino ^= vino >> 32;
if (!ino) if (!ino)
ino = 1; ino = 2;
return ino; return ino;
} }
...@@ -733,6 +733,8 @@ extern ssize_t ceph_listxattr(struct dentry *, char *, size_t); ...@@ -733,6 +733,8 @@ extern ssize_t ceph_listxattr(struct dentry *, char *, size_t);
extern int ceph_removexattr(struct dentry *, const char *); extern int ceph_removexattr(struct dentry *, const char *);
extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci); extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci);
extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci); extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci);
extern void __init ceph_xattr_init(void);
extern void ceph_xattr_exit(void);
/* caps.c */ /* caps.c */
extern const char *ceph_cap_string(int c); extern const char *ceph_cap_string(int c);
......
...@@ -8,9 +8,12 @@ ...@@ -8,9 +8,12 @@
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/slab.h> #include <linux/slab.h>
#define XATTR_CEPH_PREFIX "ceph."
#define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
static bool ceph_is_valid_xattr(const char *name) static bool ceph_is_valid_xattr(const char *name)
{ {
return !strncmp(name, "ceph.", 5) || return !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
!strncmp(name, XATTR_SECURITY_PREFIX, !strncmp(name, XATTR_SECURITY_PREFIX,
XATTR_SECURITY_PREFIX_LEN) || XATTR_SECURITY_PREFIX_LEN) ||
!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
...@@ -21,79 +24,91 @@ static bool ceph_is_valid_xattr(const char *name) ...@@ -21,79 +24,91 @@ static bool ceph_is_valid_xattr(const char *name)
* These define virtual xattrs exposing the recursive directory * These define virtual xattrs exposing the recursive directory
* statistics and layout metadata. * statistics and layout metadata.
*/ */
struct ceph_vxattr_cb { struct ceph_vxattr {
bool readonly;
char *name; char *name;
size_t name_size; /* strlen(name) + 1 (for '\0') */
size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val, size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val,
size_t size); size_t size);
bool readonly;
}; };
/* directories */ /* directories */
static size_t ceph_vxattrcb_entries(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_dir_entries(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
return snprintf(val, size, "%lld", ci->i_files + ci->i_subdirs); return snprintf(val, size, "%lld", ci->i_files + ci->i_subdirs);
} }
static size_t ceph_vxattrcb_files(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_dir_files(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
return snprintf(val, size, "%lld", ci->i_files); return snprintf(val, size, "%lld", ci->i_files);
} }
static size_t ceph_vxattrcb_subdirs(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_dir_subdirs(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
return snprintf(val, size, "%lld", ci->i_subdirs); return snprintf(val, size, "%lld", ci->i_subdirs);
} }
static size_t ceph_vxattrcb_rentries(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_dir_rentries(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
return snprintf(val, size, "%lld", ci->i_rfiles + ci->i_rsubdirs); return snprintf(val, size, "%lld", ci->i_rfiles + ci->i_rsubdirs);
} }
static size_t ceph_vxattrcb_rfiles(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_dir_rfiles(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
return snprintf(val, size, "%lld", ci->i_rfiles); return snprintf(val, size, "%lld", ci->i_rfiles);
} }
static size_t ceph_vxattrcb_rsubdirs(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_dir_rsubdirs(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
return snprintf(val, size, "%lld", ci->i_rsubdirs); return snprintf(val, size, "%lld", ci->i_rsubdirs);
} }
static size_t ceph_vxattrcb_rbytes(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
return snprintf(val, size, "%lld", ci->i_rbytes); return snprintf(val, size, "%lld", ci->i_rbytes);
} }
static size_t ceph_vxattrcb_rctime(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
return snprintf(val, size, "%ld.%ld", (long)ci->i_rctime.tv_sec, return snprintf(val, size, "%ld.09%ld", (long)ci->i_rctime.tv_sec,
(long)ci->i_rctime.tv_nsec); (long)ci->i_rctime.tv_nsec);
} }
static struct ceph_vxattr_cb ceph_dir_vxattrs[] = { #define CEPH_XATTR_NAME(_type, _name) XATTR_CEPH_PREFIX #_type "." #_name
{ true, "ceph.dir.entries", ceph_vxattrcb_entries},
{ true, "ceph.dir.files", ceph_vxattrcb_files}, #define XATTR_NAME_CEPH(_type, _name) \
{ true, "ceph.dir.subdirs", ceph_vxattrcb_subdirs}, { \
{ true, "ceph.dir.rentries", ceph_vxattrcb_rentries}, .name = CEPH_XATTR_NAME(_type, _name), \
{ true, "ceph.dir.rfiles", ceph_vxattrcb_rfiles}, .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
{ true, "ceph.dir.rsubdirs", ceph_vxattrcb_rsubdirs}, .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
{ true, "ceph.dir.rbytes", ceph_vxattrcb_rbytes}, .readonly = true, \
{ true, "ceph.dir.rctime", ceph_vxattrcb_rctime}, }
{ true, NULL, NULL }
static struct ceph_vxattr ceph_dir_vxattrs[] = {
XATTR_NAME_CEPH(dir, entries),
XATTR_NAME_CEPH(dir, files),
XATTR_NAME_CEPH(dir, subdirs),
XATTR_NAME_CEPH(dir, rentries),
XATTR_NAME_CEPH(dir, rfiles),
XATTR_NAME_CEPH(dir, rsubdirs),
XATTR_NAME_CEPH(dir, rbytes),
XATTR_NAME_CEPH(dir, rctime),
{ 0 } /* Required table terminator */
}; };
static size_t ceph_dir_vxattrs_name_size; /* total size of all names */
/* files */ /* files */
static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val, static size_t ceph_vxattrcb_file_layout(struct ceph_inode_info *ci, char *val,
size_t size) size_t size)
{ {
int ret; int ret;
...@@ -103,21 +118,32 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val, ...@@ -103,21 +118,32 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
(unsigned long long)ceph_file_layout_su(ci->i_layout), (unsigned long long)ceph_file_layout_su(ci->i_layout),
(unsigned long long)ceph_file_layout_stripe_count(ci->i_layout), (unsigned long long)ceph_file_layout_stripe_count(ci->i_layout),
(unsigned long long)ceph_file_layout_object_size(ci->i_layout)); (unsigned long long)ceph_file_layout_object_size(ci->i_layout));
if (ceph_file_layout_pg_preferred(ci->i_layout))
ret += snprintf(val + ret, size, "preferred_osd=%lld\n", if (ceph_file_layout_pg_preferred(ci->i_layout) >= 0) {
val += ret;
size -= ret;
ret += snprintf(val, size, "preferred_osd=%lld\n",
(unsigned long long)ceph_file_layout_pg_preferred( (unsigned long long)ceph_file_layout_pg_preferred(
ci->i_layout)); ci->i_layout));
}
return ret; return ret;
} }
static struct ceph_vxattr_cb ceph_file_vxattrs[] = { static struct ceph_vxattr ceph_file_vxattrs[] = {
{ true, "ceph.file.layout", ceph_vxattrcb_layout}, XATTR_NAME_CEPH(file, layout),
/* The following extended attribute name is deprecated */ /* The following extended attribute name is deprecated */
{ true, "ceph.layout", ceph_vxattrcb_layout}, {
{ true, NULL, NULL } .name = XATTR_CEPH_PREFIX "layout",
.name_size = sizeof (XATTR_CEPH_PREFIX "layout"),
.getxattr_cb = ceph_vxattrcb_file_layout,
.readonly = true,
},
{ 0 } /* Required table terminator */
}; };
static size_t ceph_file_vxattrs_name_size; /* total size of all names */
static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) static struct ceph_vxattr *ceph_inode_vxattrs(struct inode *inode)
{ {
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
return ceph_dir_vxattrs; return ceph_dir_vxattrs;
...@@ -126,14 +152,59 @@ static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) ...@@ -126,14 +152,59 @@ static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode)
return NULL; return NULL;
} }
static struct ceph_vxattr_cb *ceph_match_vxattr(struct ceph_vxattr_cb *vxattr, static size_t ceph_vxattrs_name_size(struct ceph_vxattr *vxattrs)
{
if (vxattrs == ceph_dir_vxattrs)
return ceph_dir_vxattrs_name_size;
if (vxattrs == ceph_file_vxattrs)
return ceph_file_vxattrs_name_size;
BUG();
return 0;
}
/*
* Compute the aggregate size (including terminating '\0') of all
* virtual extended attribute names in the given vxattr table.
*/
static size_t __init vxattrs_name_size(struct ceph_vxattr *vxattrs)
{
struct ceph_vxattr *vxattr;
size_t size = 0;
for (vxattr = vxattrs; vxattr->name; vxattr++)
size += vxattr->name_size;
return size;
}
/* Routines called at initialization and exit time */
void __init ceph_xattr_init(void)
{
ceph_dir_vxattrs_name_size = vxattrs_name_size(ceph_dir_vxattrs);
ceph_file_vxattrs_name_size = vxattrs_name_size(ceph_file_vxattrs);
}
void ceph_xattr_exit(void)
{
ceph_dir_vxattrs_name_size = 0;
ceph_file_vxattrs_name_size = 0;
}
static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
const char *name) const char *name)
{ {
do { struct ceph_vxattr *vxattr = ceph_inode_vxattrs(inode);
if (strcmp(vxattr->name, name) == 0)
if (vxattr) {
while (vxattr->name) {
if (!strcmp(vxattr->name, name))
return vxattr; return vxattr;
vxattr++; vxattr++;
} while (vxattr->name); }
}
return NULL; return NULL;
} }
...@@ -502,17 +573,15 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value, ...@@ -502,17 +573,15 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode);
int err; int err;
struct ceph_inode_xattr *xattr; struct ceph_inode_xattr *xattr;
struct ceph_vxattr_cb *vxattr = NULL; struct ceph_vxattr *vxattr = NULL;
if (!ceph_is_valid_xattr(name)) if (!ceph_is_valid_xattr(name))
return -ENODATA; return -ENODATA;
/* let's see if a virtual xattr was requested */ /* let's see if a virtual xattr was requested */
if (vxattrs) vxattr = ceph_match_vxattr(inode, name);
vxattr = ceph_match_vxattr(vxattrs, name);
spin_lock(&ci->i_ceph_lock); spin_lock(&ci->i_ceph_lock);
dout("getxattr %p ver=%lld index_ver=%lld\n", inode, dout("getxattr %p ver=%lld index_ver=%lld\n", inode,
...@@ -568,7 +637,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) ...@@ -568,7 +637,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); struct ceph_vxattr *vxattrs = ceph_inode_vxattrs(inode);
u32 vir_namelen = 0; u32 vir_namelen = 0;
u32 namelen; u32 namelen;
int err; int err;
...@@ -596,11 +665,12 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) ...@@ -596,11 +665,12 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
goto out; goto out;
list_xattr: list_xattr:
vir_namelen = 0; /*
/* include virtual dir xattrs */ * Start with virtual dir xattr names (if any) (including
if (vxattrs) * terminating '\0' characters for each).
for (i = 0; vxattrs[i].name; i++) */
vir_namelen += strlen(vxattrs[i].name) + 1; vir_namelen = ceph_vxattrs_name_size(vxattrs);
/* adding 1 byte per each variable due to the null termination */ /* adding 1 byte per each variable due to the null termination */
namelen = vir_namelen + ci->i_xattrs.names_size + ci->i_xattrs.count; namelen = vir_namelen + ci->i_xattrs.names_size + ci->i_xattrs.count;
err = -ERANGE; err = -ERANGE;
...@@ -698,17 +768,17 @@ int ceph_setxattr(struct dentry *dentry, const char *name, ...@@ -698,17 +768,17 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct ceph_vxattr *vxattr;
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); int issued;
int err; int err;
int dirty;
int name_len = strlen(name); int name_len = strlen(name);
int val_len = size; int val_len = size;
char *newname = NULL; char *newname = NULL;
char *newval = NULL; char *newval = NULL;
struct ceph_inode_xattr *xattr = NULL; struct ceph_inode_xattr *xattr = NULL;
int issued;
int required_blob_size; int required_blob_size;
int dirty;
if (ceph_snap(inode) != CEPH_NOSNAP) if (ceph_snap(inode) != CEPH_NOSNAP)
return -EROFS; return -EROFS;
...@@ -716,12 +786,9 @@ int ceph_setxattr(struct dentry *dentry, const char *name, ...@@ -716,12 +786,9 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
if (!ceph_is_valid_xattr(name)) if (!ceph_is_valid_xattr(name))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (vxattrs) { vxattr = ceph_match_vxattr(inode, name);
struct ceph_vxattr_cb *vxattr =
ceph_match_vxattr(vxattrs, name);
if (vxattr && vxattr->readonly) if (vxattr && vxattr->readonly)
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
/* preallocate memory for xattr name, value, index node */ /* preallocate memory for xattr name, value, index node */
err = -ENOMEM; err = -ENOMEM;
...@@ -730,11 +797,9 @@ int ceph_setxattr(struct dentry *dentry, const char *name, ...@@ -730,11 +797,9 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
goto out; goto out;
if (val_len) { if (val_len) {
newval = kmalloc(val_len + 1, GFP_NOFS); newval = kmemdup(value, val_len, GFP_NOFS);
if (!newval) if (!newval)
goto out; goto out;
memcpy(newval, value, val_len);
newval[val_len] = '\0';
} }
xattr = kmalloc(sizeof(struct ceph_inode_xattr), GFP_NOFS); xattr = kmalloc(sizeof(struct ceph_inode_xattr), GFP_NOFS);
...@@ -744,6 +809,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name, ...@@ -744,6 +809,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
spin_lock(&ci->i_ceph_lock); spin_lock(&ci->i_ceph_lock);
retry: retry:
issued = __ceph_caps_issued(ci, NULL); issued = __ceph_caps_issued(ci, NULL);
dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued));
if (!(issued & CEPH_CAP_XATTR_EXCL)) if (!(issued & CEPH_CAP_XATTR_EXCL))
goto do_sync; goto do_sync;
__build_xattrs(inode); __build_xattrs(inode);
...@@ -752,7 +818,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name, ...@@ -752,7 +818,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
if (!ci->i_xattrs.prealloc_blob || if (!ci->i_xattrs.prealloc_blob ||
required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) { required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) {
struct ceph_buffer *blob = NULL; struct ceph_buffer *blob;
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
dout(" preaallocating new blob size=%d\n", required_blob_size); dout(" preaallocating new blob size=%d\n", required_blob_size);
...@@ -766,12 +832,13 @@ int ceph_setxattr(struct dentry *dentry, const char *name, ...@@ -766,12 +832,13 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
goto retry; goto retry;
} }
dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued));
err = __set_xattr(ci, newname, name_len, newval, err = __set_xattr(ci, newname, name_len, newval,
val_len, 1, 1, 1, &xattr); val_len, 1, 1, 1, &xattr);
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
ci->i_xattrs.dirty = true; ci->i_xattrs.dirty = true;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
if (dirty) if (dirty)
__mark_inode_dirty(inode, dirty); __mark_inode_dirty(inode, dirty);
...@@ -816,8 +883,8 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name) ...@@ -816,8 +883,8 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
int ceph_removexattr(struct dentry *dentry, const char *name) int ceph_removexattr(struct dentry *dentry, const char *name)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct ceph_vxattr *vxattr;
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode);
int issued; int issued;
int err; int err;
int required_blob_size; int required_blob_size;
...@@ -829,22 +896,19 @@ int ceph_removexattr(struct dentry *dentry, const char *name) ...@@ -829,22 +896,19 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
if (!ceph_is_valid_xattr(name)) if (!ceph_is_valid_xattr(name))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (vxattrs) { vxattr = ceph_match_vxattr(inode, name);
struct ceph_vxattr_cb *vxattr =
ceph_match_vxattr(vxattrs, name);
if (vxattr && vxattr->readonly) if (vxattr && vxattr->readonly)
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
err = -ENOMEM; err = -ENOMEM;
spin_lock(&ci->i_ceph_lock); spin_lock(&ci->i_ceph_lock);
__build_xattrs(inode);
retry: retry:
issued = __ceph_caps_issued(ci, NULL); issued = __ceph_caps_issued(ci, NULL);
dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued));
if (!(issued & CEPH_CAP_XATTR_EXCL)) if (!(issued & CEPH_CAP_XATTR_EXCL))
goto do_sync; goto do_sync;
__build_xattrs(inode);
required_blob_size = __get_required_blob_size(ci, 0, 0); required_blob_size = __get_required_blob_size(ci, 0, 0);
...@@ -865,10 +929,10 @@ int ceph_removexattr(struct dentry *dentry, const char *name) ...@@ -865,10 +929,10 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
} }
err = __remove_xattr_by_name(ceph_inode(inode), name); err = __remove_xattr_by_name(ceph_inode(inode), name);
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
ci->i_xattrs.dirty = true; ci->i_xattrs.dirty = true;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
if (dirty) if (dirty)
__mark_inode_dirty(inode, dirty); __mark_inode_dirty(inode, dirty);
......
...@@ -208,7 +208,7 @@ extern struct kmem_cache *ceph_cap_cachep; ...@@ -208,7 +208,7 @@ extern struct kmem_cache *ceph_cap_cachep;
extern struct kmem_cache *ceph_dentry_cachep; extern struct kmem_cache *ceph_dentry_cachep;
extern struct kmem_cache *ceph_file_cachep; extern struct kmem_cache *ceph_file_cachep;
extern int ceph_parse_options(struct ceph_options **popt, char *options, extern struct ceph_options *ceph_parse_options(char *options,
const char *dev_name, const char *dev_name_end, const char *dev_name, const char *dev_name_end,
int (*parse_extra_token)(char *c, void *private), int (*parse_extra_token)(char *c, void *private),
void *private); void *private);
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
struct ceph_msg; struct ceph_msg;
struct ceph_connection; struct ceph_connection;
extern struct workqueue_struct *ceph_msgr_wq; /* receive work queue */
/* /*
* Ceph defines these callbacks for handling connection events. * Ceph defines these callbacks for handling connection events.
*/ */
...@@ -54,7 +52,6 @@ struct ceph_connection_operations { ...@@ -54,7 +52,6 @@ struct ceph_connection_operations {
struct ceph_messenger { struct ceph_messenger {
struct ceph_entity_inst inst; /* my name+address */ struct ceph_entity_inst inst; /* my name+address */
struct ceph_entity_addr my_enc_addr; struct ceph_entity_addr my_enc_addr;
struct page *zero_page; /* used in certain error cases */
bool nocrc; bool nocrc;
...@@ -101,7 +98,7 @@ struct ceph_msg { ...@@ -101,7 +98,7 @@ struct ceph_msg {
struct ceph_msg_pos { struct ceph_msg_pos {
int page, page_pos; /* which page; offset in page */ int page, page_pos; /* which page; offset in page */
int data_pos; /* offset in data payload */ int data_pos; /* offset in data payload */
int did_page_crc; /* true if we've calculated crc for current page */ bool did_page_crc; /* true if we've calculated crc for current page */
}; };
/* ceph connection fault delay defaults, for exponential backoff */ /* ceph connection fault delay defaults, for exponential backoff */
......
...@@ -201,7 +201,9 @@ enum { ...@@ -201,7 +201,9 @@ enum {
Opt_ip, Opt_ip,
Opt_last_string, Opt_last_string,
/* string args above */ /* string args above */
Opt_share,
Opt_noshare, Opt_noshare,
Opt_crc,
Opt_nocrc, Opt_nocrc,
}; };
...@@ -217,7 +219,9 @@ static match_table_t opt_tokens = { ...@@ -217,7 +219,9 @@ static match_table_t opt_tokens = {
{Opt_key, "key=%s"}, {Opt_key, "key=%s"},
{Opt_ip, "ip=%s"}, {Opt_ip, "ip=%s"},
/* string args above */ /* string args above */
{Opt_share, "share"},
{Opt_noshare, "noshare"}, {Opt_noshare, "noshare"},
{Opt_crc, "crc"},
{Opt_nocrc, "nocrc"}, {Opt_nocrc, "nocrc"},
{-1, NULL} {-1, NULL}
}; };
...@@ -277,8 +281,9 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name) { ...@@ -277,8 +281,9 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name) {
return err; return err;
} }
int ceph_parse_options(struct ceph_options **popt, char *options, struct ceph_options *
const char *dev_name, const char *dev_name_end, ceph_parse_options(char *options, const char *dev_name,
const char *dev_name_end,
int (*parse_extra_token)(char *c, void *private), int (*parse_extra_token)(char *c, void *private),
void *private) void *private)
{ {
...@@ -289,7 +294,7 @@ int ceph_parse_options(struct ceph_options **popt, char *options, ...@@ -289,7 +294,7 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
opt = kzalloc(sizeof(*opt), GFP_KERNEL); opt = kzalloc(sizeof(*opt), GFP_KERNEL);
if (!opt) if (!opt)
return err; return ERR_PTR(-ENOMEM);
opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr), opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
GFP_KERNEL); GFP_KERNEL);
if (!opt->mon_addr) if (!opt->mon_addr)
...@@ -398,10 +403,16 @@ int ceph_parse_options(struct ceph_options **popt, char *options, ...@@ -398,10 +403,16 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
opt->mount_timeout = intval; opt->mount_timeout = intval;
break; break;
case Opt_share:
opt->flags &= ~CEPH_OPT_NOSHARE;
break;
case Opt_noshare: case Opt_noshare:
opt->flags |= CEPH_OPT_NOSHARE; opt->flags |= CEPH_OPT_NOSHARE;
break; break;
case Opt_crc:
opt->flags &= ~CEPH_OPT_NOCRC;
break;
case Opt_nocrc: case Opt_nocrc:
opt->flags |= CEPH_OPT_NOCRC; opt->flags |= CEPH_OPT_NOCRC;
break; break;
...@@ -412,12 +423,11 @@ int ceph_parse_options(struct ceph_options **popt, char *options, ...@@ -412,12 +423,11 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
} }
/* success */ /* success */
*popt = opt; return opt;
return 0;
out: out:
ceph_destroy_options(opt); ceph_destroy_options(opt);
return err; return ERR_PTR(err);
} }
EXPORT_SYMBOL(ceph_parse_options); EXPORT_SYMBOL(ceph_parse_options);
......
此差异已折叠。
...@@ -283,7 +283,8 @@ static struct crush_map *crush_decode(void *pbyval, void *end) ...@@ -283,7 +283,8 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
ceph_decode_32_safe(p, end, yes, bad); ceph_decode_32_safe(p, end, yes, bad);
#if BITS_PER_LONG == 32 #if BITS_PER_LONG == 32
err = -EINVAL; err = -EINVAL;
if (yes > ULONG_MAX / sizeof(struct crush_rule_step)) if (yes > (ULONG_MAX - sizeof(*r))
/ sizeof(struct crush_rule_step))
goto bad; goto bad;
#endif #endif
r = c->rules[i] = kmalloc(sizeof(*r) + r = c->rules[i] = kmalloc(sizeof(*r) +
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册