+
+void set_filter_ops(struct snap_cache *cache, struct inode *inode)
+{
+ /* XXX now set the correct snap_{file,dir,sym}_iops */
+ if (S_ISDIR(inode->i_mode)) {
+ inode->i_op = filter_c2udiops(cache->cache_filter);
+ inode->i_fop = filter_c2udfops(cache->cache_filter);
+ } else if (S_ISREG(inode->i_mode)) {
+ if ( !filter_c2cfiops(cache->cache_filter) ) {
+ filter_setup_file_ops(cache->cache_filter, inode,
+ ¤tfs_file_iops,
+ ¤tfs_file_fops,
+ ¤tfs_file_aops);
+ }
+ CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
+ inode->i_ino, inode->i_op);
+ inode->i_fop = filter_c2uffops(cache->cache_filter);
+ inode->i_op = filter_c2ufiops(cache->cache_filter);
+ if (inode->i_mapping)
+ inode->i_mapping->a_ops = filter_c2ufaops(cache->cache_filter);
+
+ }
+ else if (S_ISLNK(inode->i_mode)) {
+ if ( !filter_c2csiops(cache->cache_filter) ) {
+ filter_setup_symlink_ops(cache->cache_filter, inode,
+ ¤tfs_sym_iops, ¤tfs_sym_fops);
+ }
+ inode->i_op = filter_c2usiops(cache->cache_filter);
+ inode->i_fop = filter_c2usfops(cache->cache_filter);
+ CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
+ inode->i_ino, inode->i_op);
+ }
+}
+int currentfs_setxattr(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags)
+{
+ struct snap_cache *cache;
+ struct inode *inode = dentry->d_inode;
+ struct inode_operations *iops;
+ int rc;
+
+ ENTRY;
+
+ cache = snap_find_cache(inode->i_dev);
+ if (!cache) {
+ CERROR("currentfs_setxattr: cannot find cache\n");
+ RETURN(-EINVAL);
+ }
+
+ iops = filter_c2cfiops(cache->cache_filter);
+
+ if (!iops || !iops->setxattr) {
+ RETURN(-EINVAL);
+ }
+ if ( snap_needs_cow(inode) != -1 ) {
+ CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+ snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+ }
+
+ rc = iops->setxattr(dentry, name, value, size, flags);
+
+ RETURN(rc);
+}
+int currentfs_removexattr(struct dentry *dentry, const char *name)
+{
+ struct snap_cache *cache;
+ struct inode *inode = dentry->d_inode;
+ struct inode_operations *iops;
+ int rc;
+
+ ENTRY;
+
+ cache = snap_find_cache(inode->i_dev);
+ if (!cache) {
+ CERROR("currentfs_setxattr: cannot find cache\n");
+ RETURN(-EINVAL);
+ }
+
+ iops = filter_c2cfiops(cache->cache_filter);
+
+ if (!iops || !iops->removexattr) {
+ RETURN(-EINVAL);
+ }
+
+ if (snap_needs_cow(inode) != -1) {
+ CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+ snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+ }
+ rc = iops->removexattr(dentry, name);
+
+ RETURN(rc);
+}
+
+int currentfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct snap_cache *cache;
+ struct inode *inode = dentry->d_inode;
+ struct inode_operations *iops;
+ int rc;
+
+ ENTRY;
+
+ cache = snap_find_cache(inode->i_dev);
+ if (!cache) {
+ CERROR("currentfs_setxattr: cannot find cache\n");
+ RETURN(-EINVAL);
+ }
+
+ iops = filter_c2cfiops(cache->cache_filter);
+
+ if (!iops || !iops->setattr) {
+ RETURN(-EINVAL);
+ }
+ if ( snap_needs_cow(inode) != -1 ) {
+ CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+ snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+ }
+
+ rc = iops->setattr(dentry, attr);
+
+ RETURN(rc);
+}