]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/ceph/super.h
ceph: quota: don't allow cross-quota renames
[mirror_ubuntu-bionic-kernel.git] / fs / ceph / super.h
index 2beeec07fa76ce199e7d461831b9b93a705419ee..54e7f2ed89635ebd1582c9b64905aea5d7dd4a3c 100644 (file)
@@ -102,11 +102,11 @@ struct ceph_fs_client {
 
        /* writeback */
        mempool_t *wb_pagevec_pool;
-       struct workqueue_struct *wb_wq;
-       struct workqueue_struct *pg_inv_wq;
-       struct workqueue_struct *trunc_wq;
        atomic_long_t writeback_count;
 
+       struct workqueue_struct *inode_wq;
+       struct workqueue_struct *cap_wq;
+
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_dentry_lru, *debugfs_caps;
        struct dentry *debugfs_congestion_kb;
@@ -256,7 +256,8 @@ struct ceph_inode_xattr {
  */
 struct ceph_dentry_info {
        struct ceph_mds_session *lease_session;
-       u32 lease_gen, lease_shared_gen;
+       int lease_shared_gen;
+       u32 lease_gen;
        u32 lease_seq;
        unsigned long lease_renew_after, lease_renew_from;
        struct list_head lru;
@@ -309,6 +310,9 @@ struct ceph_inode_info {
        u64 i_rbytes, i_rfiles, i_rsubdirs;
        u64 i_files, i_subdirs;
 
+       /* quotas */
+       u64 i_max_bytes, i_max_files;
+
        struct rb_root i_fragtree;
        int i_fragtree_nsplits;
        struct mutex i_fragtree_mutex;
@@ -353,7 +357,7 @@ struct ceph_inode_info {
        int i_rd_ref, i_rdcache_ref, i_wr_ref, i_wb_ref;
        int i_wrbuffer_ref, i_wrbuffer_ref_head;
        atomic_t i_filelock_ref;
-       u32 i_shared_gen;       /* increment each time we get FILE_SHARED */
+       atomic_t i_shared_gen;       /* increment each time we get FILE_SHARED */
        u32 i_rdcache_gen;      /* incremented each time we get FILE_CACHE. */
        u32 i_rdcache_revoking; /* RDCACHE gen to async invalidate, if any */
 
@@ -366,10 +370,8 @@ struct ceph_inode_info {
        struct list_head i_snap_realm_item;
        struct list_head i_snap_flush_item;
 
-       struct work_struct i_wb_work;  /* writeback work */
-       struct work_struct i_pg_inv_work;  /* page invalidation work */
-
-       struct work_struct i_vmtruncate_work;
+       struct work_struct i_work;
+       unsigned long  i_work_mask;
 
 #ifdef CONFIG_CEPH_FSCACHE
        struct fscache_cookie *fscache;
@@ -491,6 +493,13 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
 #define CEPH_I_ERROR_FILELOCK  (1 << 12) /* have seen file lock errors */
 
 
+/*
+ * Masks of ceph inode work.
+ */
+#define CEPH_I_WORK_WRITEBACK          0 /* writeback */
+#define CEPH_I_WORK_INVALIDATE_PAGES   1 /* invalidate pages */
+#define CEPH_I_WORK_VMTRUNCATE         2 /* vmtruncate */
+
 /*
  * We set the ERROR_WRITE bit when we start seeing write errors on an inode
  * and then clear it when they start succeeding. Note that we do a lockless
@@ -668,6 +677,9 @@ struct ceph_file_info {
        short fmode;     /* initialized on open */
        short flags;     /* CEPH_F_* */
 
+       spinlock_t rw_contexts_lock;
+       struct list_head rw_contexts;
+
        /* readdir: position within the dir */
        u32 frag;
        struct ceph_mds_request *last_readdir;
@@ -684,6 +696,49 @@ struct ceph_file_info {
        int dir_info_len;
 };
 
+struct ceph_rw_context {
+       struct list_head list;
+       struct task_struct *thread;
+       int caps;
+};
+
+#define CEPH_DEFINE_RW_CONTEXT(_name, _caps)   \
+       struct ceph_rw_context _name = {        \
+               .thread = current,              \
+               .caps = _caps,                  \
+       }
+
+static inline void ceph_add_rw_context(struct ceph_file_info *cf,
+                                      struct ceph_rw_context *ctx)
+{
+       spin_lock(&cf->rw_contexts_lock);
+       list_add(&ctx->list, &cf->rw_contexts);
+       spin_unlock(&cf->rw_contexts_lock);
+}
+
+static inline void ceph_del_rw_context(struct ceph_file_info *cf,
+                                      struct ceph_rw_context *ctx)
+{
+       spin_lock(&cf->rw_contexts_lock);
+       list_del(&ctx->list);
+       spin_unlock(&cf->rw_contexts_lock);
+}
+
+static inline struct ceph_rw_context*
+ceph_find_rw_context(struct ceph_file_info *cf)
+{
+       struct ceph_rw_context *ctx, *found = NULL;
+       spin_lock(&cf->rw_contexts_lock);
+       list_for_each_entry(ctx, &cf->rw_contexts, list) {
+               if (ctx->thread == current) {
+                       found = ctx;
+                       break;
+               }
+       }
+       spin_unlock(&cf->rw_contexts_lock);
+       return found;
+}
+
 struct ceph_readdir_cache_control {
        struct page  *page;
        struct dentry **dentries;
@@ -914,11 +969,11 @@ extern void ceph_add_cap(struct inode *inode,
                         unsigned cap, unsigned seq, u64 realmino, int flags,
                         struct ceph_cap **new_cap);
 extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
+extern void __ceph_remove_caps(struct inode* inode);
 extern void ceph_put_cap(struct ceph_mds_client *mdsc,
                         struct ceph_cap *cap);
 extern int ceph_is_any_caps(struct inode *inode);
 
-extern void ceph_queue_caps_release(struct inode *inode);
 extern int ceph_write_inode(struct inode *inode, struct writeback_control *wbc);
 extern int ceph_fsync(struct file *file, loff_t start, loff_t end,
                      int datasync);
@@ -1019,4 +1074,11 @@ extern int ceph_locks_to_pagelist(struct ceph_filelock *flocks,
 extern int ceph_fs_debugfs_init(struct ceph_fs_client *client);
 extern void ceph_fs_debugfs_cleanup(struct ceph_fs_client *client);
 
+/* quota.c */
+extern void ceph_handle_quota(struct ceph_mds_client *mdsc,
+                             struct ceph_mds_session *session,
+                             struct ceph_msg *msg);
+extern bool ceph_quota_is_max_files_exceeded(struct inode *inode);
+extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new);
+
 #endif /* _FS_CEPH_SUPER_H */