]> err.no Git - linux-2.6/blobdiff - fs/fuse/fuse_i.h
fuse: add atomic open+truncate support
[linux-2.6] / fs / fuse / fuse_i.h
index 69c7750d55b8e59cfd95a0322f45557a74c0fdfe..b24fc9b386f826b10220f39136f4eda8def271f4 100644 (file)
 #define FUSE_MAX_PAGES_PER_REQ 32
 
 /** Maximum number of outstanding background requests */
-#define FUSE_MAX_BACKGROUND 10
+#define FUSE_MAX_BACKGROUND 12
+
+/** Congestion starts at 75% of maximum */
+#define FUSE_CONGESTION_THRESHOLD (FUSE_MAX_BACKGROUND * 75 / 100)
 
 /** It could be as large as PATH_MAX, but would that have any uses? */
 #define FUSE_NAME_MAX 1024
@@ -60,6 +63,13 @@ struct fuse_inode {
 
        /** Time in jiffies until the file attributes are valid */
        u64 i_time;
+
+       /** The sticky bit in inode->i_mode may have been removed, so
+           preserve the original mode */
+       mode_t orig_i_mode;
+
+       /** Version of last attribute change */
+       u64 attr_version;
 };
 
 /** FUSE specific file data */
@@ -69,6 +79,9 @@ struct fuse_file {
 
        /** File handle used by userspace */
        u64 fh;
+
+       /** Refcount */
+       atomic_t count;
 };
 
 /** One input argument of a request */
@@ -213,7 +226,7 @@ struct fuse_req {
        unsigned page_offset;
 
        /** File used in the request (or NULL) */
-       struct file *file;
+       struct fuse_file *ff;
 
        /** vfsmount used in release */
        struct vfsmount *vfsmount;
@@ -239,6 +252,9 @@ struct fuse_conn {
        /** Lock protecting accessess to  members of this structure */
        spinlock_t lock;
 
+       /** Mutex protecting against directory alias creation */
+       struct mutex inst_mutex;
+
        /** Refcount */
        atomic_t count;
 
@@ -283,6 +299,9 @@ struct fuse_conn {
        /** waitq for blocked connection */
        wait_queue_head_t blocked_waitq;
 
+       /** waitq for reserved requests */
+       wait_queue_head_t reserved_req_waitq;
+
        /** The next unique request id */
        u64 reqctr;
 
@@ -295,9 +314,15 @@ struct fuse_conn {
            reply, before any other request, and never cleared */
        unsigned conn_error : 1;
 
+       /** Connection successful.  Only set in INIT */
+       unsigned conn_init : 1;
+
        /** Do readpages asynchronously?  Only set in INIT */
        unsigned async_read : 1;
 
+       /** Do not send separate SETATTR request before open(O_TRUNC)  */
+       unsigned atomic_o_trunc : 1;
+
        /*
         * The following bitfields are only for optimization purposes
         * and hence races in setting them will not cause malfunction
@@ -336,6 +361,9 @@ struct fuse_conn {
        /** Is interrupt not implemented by fs? */
        unsigned no_interrupt : 1;
 
+       /** Is bmap not implemented by fs? */
+       unsigned no_bmap : 1;
+
        /** The number of requests waiting for completion */
        atomic_t num_waiting;
 
@@ -362,6 +390,12 @@ struct fuse_conn {
 
        /** Key for lock owner ID scrambling */
        u32 scramble_key[4];
+
+       /** Reserved request for the DESTROY message */
+       struct fuse_req *destroy_req;
+
+       /** Version counter for attribute changes */
+       u64 attr_version;
 };
 
 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -391,7 +425,8 @@ extern const struct file_operations fuse_dev_operations;
  * Get a filled in inode
  */
 struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
-                       int generation, struct fuse_attr *attr);
+                       int generation, struct fuse_attr *attr,
+                       u64 attr_valid, u64 attr_version);
 
 /**
  * Send FORGET command
@@ -402,7 +437,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
 /**
  * Initialize READ or READDIR request
  */
-void fuse_read_fill(struct fuse_req *req, struct file *file,
+void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff,
                    struct inode *inode, loff_t pos, size_t count, int opcode);
 
 /**
@@ -415,9 +450,9 @@ void fuse_file_free(struct fuse_file *ff);
 void fuse_finish_open(struct inode *inode, struct file *file,
                      struct fuse_file *ff, struct fuse_open_out *outarg);
 
-/** */
-struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags,
-                                  int opcode);
+/** Fill in ff->reserved_req with a RELEASE request */
+void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode);
+
 /**
  * Send RELEASE or RELEASEDIR request
  */
@@ -452,7 +487,8 @@ void fuse_init_symlink(struct inode *inode);
 /**
  * Change attributes of an inode
  */
-void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr);
+void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+                           u64 attr_valid, u64 attr_version);
 
 /**
  * Initialize the client device
@@ -511,11 +547,6 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
 /* Abort all requests */
 void fuse_abort_conn(struct fuse_conn *fc);
 
-/**
- * Get the attributes of a file
- */
-int fuse_do_getattr(struct inode *inode);
-
 /**
  * Invalidate inode attributes
  */
@@ -540,3 +571,13 @@ int fuse_ctl_add_conn(struct fuse_conn *fc);
  * Remove connection from control filesystem
  */
 void fuse_ctl_remove_conn(struct fuse_conn *fc);
+
+/**
+ * Is file type valid?
+ */
+int fuse_valid_type(int m);
+
+/**
+ * Is task allowed to perform filesystem operation?
+ */
+int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task);